Skip to content

feat(review): validate and scope the incremental anchor inside fetch-pr - #9100

Merged
wenshao merged 19 commits into
mainfrom
feat/review-fetch-since
Aug 16, 2026
Merged

feat(review): validate and scope the incremental anchor inside fetch-pr#9100
wenshao merged 19 commits into
mainfrom
feat/review-fetch-since

Conversation

@wenshao

@wenshao wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Moves the incremental-review scoping into the CLI. qwen review fetch-pr gains --since <sha> — the head the last clean round reviewed, from the local review cache or the posted ledger marker. The command validates the anchor against the fetched history (hex allowlist first, so an anchor recovered from a cache file or a posted marker is never handed to git flag-shaped; then cat-file -e, merge-base --is-ancestor, rev-parse behind an injectable probe) and rules one of three ways, recorded as the report's new incremental field: effective — the report's diff and chunk plan are scoped to since..head; upToDate — the anchor is the head (or the commits since it change no bytes), and the report keeps the full-range plan because the flows that continue past an up-to-date anchor (a model change, --comment) run a full review; refused — every reason names a CAUSE (not-an-ancestor, unknown-commit, behind-merge-base, hunks-outside-pr-diff, containment-unverified, base-untrusted, capture-failed, partition-failed), with a full-range fallback and the reason on stderr; whether a plan exists is the separate diffPath field. The full range is read once per round and is what emptyDiff/collapsedFromUpstream are computed from — both are facts about the PR's whole diff, never about a round's scope. An accepted delta is additionally checked for HUNK containment against that full range: an ancestor anchor can still produce hunks the PR's own diff does not contain (an "undo per feedback" revert), and a comment anchored on one 422s the entire Create Review call.

SKILL.md Step 1's two incremental bullets now read the report instead of running git: the cache is read before fetch-pr and its lastCommitSha passed as --since; the marker-anchor path (CI, fresh clones) re-runs the same command with --since appended once pr-context's side file lands.

Why it's needed

The incremental path was the one diff this skill still asked the orchestrator to hand-compute: Step 1 said git diff <lastCommitSha>..HEAD inside the worktree, and the recovered-anchor bullet asked for hand-run cat-file / merge-base --is-ancestor checks — the exact shape the skill forbids everywhere else, because the diff is a file the CLI writes, never a command a run can skip, sample, or get wrong (DESIGN.md: "Why the diff is a file, not a command"). A hand-computed delta also never got a chunk plan or budget: the incremental scope bypassed buildDiffPlan entirely, so a large delta hit the same truncation traps the full-diff path was built to avoid. This is item 2 of the #8946 roadmap (the anchor itself landed in #9067) and the foundation for item 3 (consumer-union scoping, which needs the delta computed where the plan is built).

Reviewer Test Plan

How to verify

  • cd packages/cli && npx vitest run src/commands/review/fetch-pr.test.ts — the new resolveIncrementalAnchor coverage: a valid anchor behind the head scopes; anchor-at-head reports upToDate and keeps the full range; unknown / rebased-away anchors are refused with their reasons; flag-shaped and non-hex anchors (--upload-pack=…, HEAD, $(rm -rf /), 6-char strings) never reach the probe at all; an anchor rev-parse cannot name is refused rather than riding a full-range diff as effective: true.
  • Read the handler wiring in fetch-pr.ts: the delta capture runs before the merge-base capture and does not consult the base (a failed base fetch does not cost the incremental path); an empty delta upgrades to upToDate and recaptures the full range; a failed delta capture downgrades to effective: false, reason: 'capture-failed' rather than letting the report claim a scope the capture never produced.
  • Read SKILL.md Step 1: the incremental-check bullet's outcome table now keys on incremental (effective/upToDate/reason), and the recovered-anchor bullet re-runs fetch-pr --since instead of hand-running git.

Evidence (Before & After)

N/A — CLI plumbing plus skill text. Before: the incremental diff was git diff run by the orchestrating model inside the worktree, unvalidated, unplanned, unchunked. After: resolveIncrementalAnchor is unit-pinned, the delta flows through the same buildDiffPlan pipeline as the full diff, and the report says which range it planned and why.

Tested on

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

Environment (optional)

Unit tests only (npx vitest run in packages/cli and packages/core). Full src/commands/review suite: 2453/2454 green — the one failure is stale-bundle.test.ts, pre-existing on a clean checkout of this machine (stale local build), unrelated. Core SKILL.test.ts 8/8.

Risk & Scope

  • Main risk or tradeoff: a wrongly-scoped delta would under-review the PR. Three layers hold the line, all in the CLI now: the hex allowlist and ancestry validation refuse anything the fetched history cannot vouch for (fail-open to the FULL diff, never to a narrower one); the upToDate state keeps the full-range plan so the continuing flows never run on an empty scope; and the report names the range it planned, so the orchestrator and the terminal report can disclose it.
  • Not validated / out of scope: the runFetchPr handler wiring is not unit-tested (it needs live git+gh; the suite's existing convention tests only the pure helpers, and the new decision logic is one of them). Consumer-union scoping (delta hunks ∪ callers of changed exports) is item 3 and deliberately not here.
  • Breaking changes / migration notes: none. --since is optional; without it the command behaves byte-for-byte as before, and the report gains no field.

Linked Issues

Refs #8946 (incremental/delta review). Builds on #9067 (the posted-marker anchor).

中文说明

What this PR does(本 PR 做什么)

把增量审查的范围计算移入 CLI。qwen review fetch-pr 新增 --since <sha>——上一轮干净审查覆盖到的 head(来自本地 review cache 或发布的 ledger marker)。命令在取回的历史上校验锚点(先过 hex 白名单,从 cache 文件或发布 marker 恢复的锚点绝不会以旗标形状传给 git;再经可注入探针跑 cat-file -emerge-base --is-ancestorrev-parse),裁决三种结果之一,记录为报告的新 incremental 字段:effective——报告的 diff 与 chunk plan 收窄为 since..headupToDate——锚点即 head(或其后的 commit 不改任何字节),报告保留全量 plan,因为越过 up-to-date 锚点继续的流程(模型变更、--comment)跑的是全量审查;refused——每个 reason 都命名一个原因not-an-ancestorunknown-commitbehind-merge-basehunks-outside-pr-diffcontainment-unverifiedbase-untrustedcapture-failedpartition-failed),回退全量并在 stderr 说明;是否存在 plan 由独立的 diffPath 字段表示。全量范围每轮只读一次,emptyDiff/collapsedFromUpstream 均由它计算——两者都是关于 PR 整体 diff 的事实,与本轮范围无关。被接受的 delta 还要对全量做 hunk 包含性校验:祖先关系正确的锚点仍可能产出 PR 自身 diff 中不存在的 hunk("按反馈撤销"型提交),一条锚定在那里的评论会 422 掉整个 Create Review 调用。

SKILL.md Step 1 的两个增量 bullet 改为读报告而非跑 git:cache 在 fetch-pr 之前读取并把 lastCommitSha 作为 --since 传入;marker 锚点路径(CI、新 clone)在 pr-context 的 side file 落地后,用追加 --since 的同一命令重跑。

Why it's needed(为什么需要)

增量路径是这个 skill 中最后一处仍要求编排者手算的 diff:Step 1 写着在 worktree 里跑 git diff <lastCommitSha>..HEAD,recovered-anchor bullet 要求手跑 cat-file / merge-base --is-ancestor 校验——这正是 skill 在其他所有地方都禁止的形态,因为 diff 是 CLI 写出的文件,绝不是模型可以跳过、采样或跑错的命令(DESIGN.md:"Why the diff is a file, not a command")。手算的 delta 也从未有过 chunk plan 和预算:增量范围完全绕过 buildDiffPlan,大 delta 会撞上全量路径专门规避的截断陷阱。本 PR 是 #8946 路线图的第 2 项(锚点本身已在 #9067 落地),也是第 3 项(消费方并集,需要 delta 在构建 plan 的地方计算)的地基。

Reviewer Test Plan(评审验证计划)

How to verify(如何验证)

  • cd packages/cli && npx vitest run src/commands/review/fetch-pr.test.ts——新增 resolveIncrementalAnchor 覆盖:head 之前的合法锚点收窄范围;锚点即 head 时报告 upToDate 并保留全量;未知/被 rebase 掉的锚点带原因拒绝;旗标形状与非 hex 锚点(--upload-pack=…HEAD$(rm -rf /)、6 字符串)根本不会触达探针;rev-parse 无法命名的锚点被拒绝,而不是以 effective: true 搭全量 diff。
  • 阅读 fetch-pr.ts 的 handler 接线:delta 捕获先于 merge-base 捕获且不依赖 base(base fetch 失败不影响增量路径);空 delta 升级为 upToDate 并重新捕获全量;delta 捕获失败降级为 effective: false, reason: 'capture-failed',而不是让报告声称一个从未产出的范围。
  • 阅读 SKILL.md Step 1:增量检查 bullet 的结果表现在以 incremental 为键(effective/upToDate/reason),recovered-anchor bullet 改为重跑 fetch-pr --since 而非手跑 git。

Evidence (Before & After)(前后证据)

N/A——CLI 管线加 skill 文本。之前:增量 diff 是编排模型在 worktree 里手跑的 git diff,未校验、无 plan、无 chunk。之后:resolveIncrementalAnchor 被单测钉住,delta 走与全量相同的 buildDiffPlan 管线,报告说明它 plan 的是哪个范围、为什么。

Tested on(测试平台)

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

Environment(环境,可选)

仅单元测试(在 packages/clipackages/corenpx vitest run)。src/commands/review 全套件 2453/2454 通过——唯一失败为本机既有的 stale-bundle.test.ts(本地陈旧构建),与本次无关。core SKILL.test.ts 8/8。

Risk & Scope(风险与范围)

  • 主要风险/权衡:错误收窄的 delta 会导致审查不足。三层防线全部在 CLI 内:hex 白名单与祖先校验拒绝取回历史无法担保的一切(失败方向是回退全量,绝不是更窄);upToDate 态保留全量 plan,继续的流程绝不会跑在空范围上;报告写明它 plan 的范围,编排者与终端报告都可披露。
  • 未验证/超出范围:runFetchPr handler 接线未做单测(需要真实 git+gh;本套件既有惯例只测纯 helper,新裁决逻辑就是其中之一)。消费方并集(delta hunks ∪ 被改 export 的调用方)是第 3 项,刻意不在本 PR。
  • 破坏性变更/迁移说明:无。--since 可选;不传时命令行为与之前逐字节一致,报告也不新增字段。

Linked Issues(关联 issue)

Refs #8946(增量/delta review)。基于 #9067(发布 marker 携带锚点)。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@wenshao
wenshao force-pushed the feat/review-fetch-since branch from 5565641 to fb3096d Compare August 13, 2026 13:34
@github-actions

Copy link
Copy Markdown
Contributor

Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration.

中文

请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-run after the rebase onto main (4cdbb9f65f).

  • Template ✓ — all required sections present, bilingual body.
  • Problem — observed gap, not theoretical: the incremental path was the last diff the review skill asked the orchestrator to hand-compute (Step 1 literally said to run git diff <lastCommitSha>..HEAD in the worktree and hand-validate the anchor with cat-file / merge-base), against the skill's own "the diff is a file, never a command" design. Item 2 of the Incremental (delta) review: review only new commits since the last reviewed SHA instead of restarting full passes #8946 roadmap, building on feat(review): carry the incremental anchor sha in the posted ledger marker #9067's posted-marker anchor.
  • Direction — aligned. Anchor validation moves into the command that builds the chunk plan, every refusal fails open to the FULL diff (never a narrower one), and the report names the range it planned.
  • Size — ~903 production-logic lines vs ~2,947 test lines (9 test files). The only core-path touch is the bundled review skill itself (SKILL.md +13/−9, SKILL.test.ts +80). No size threshold triggered; author is a maintainer.
  • Approach — scope has been frozen by maintainer decision since 4c86f15613, with the containment redesign split to a follow-up PR — the right call after sixteen rounds. This push is conflict resolution only, and carries no drive-by changes: all sixteen files are review-command / review-skill.
  • Risk (1e) — no revert-correlated high-risk paths matched.

Moving on to code review. 🔍

中文说明

Rebase 到 main4cdbb9f65f)后的重跑。

  • 模板 ✓ —— 必备小节齐全,正文双语。
  • 问题 —— 已观测到的缺口,不是理论问题:增量路径是 review skill 里最后一处仍要求编排者手算的 diff(Step 1 原本直接写在 worktree 里跑 git diff <lastCommitSha>..HEAD、手动跑 cat-file / merge-base 校验锚点),与 skill 自身「diff 是文件,不是命令」的设计相悖。这是 Incremental (delta) review: review only new commits since the last reviewed SHA instead of restarting full passes #8946 路线图的条目 2,建立在 feat(review): carry the incremental anchor sha in the posted ledger marker #9067 的 marker 锚点之上。
  • 方向 —— 对齐。锚点校验移入构建 chunk plan 的命令内部,所有拒绝都 fail-open 到全量 diff(绝不收窄),报告写明自己规划的区间。
  • 规模 —— 生产逻辑约 903 行,测试约 2,947 行(9 个测试文件)。唯一触及核心路径的是 bundled review skill 本身(SKILL.md +13/−9、SKILL.test.ts +80)。未触发任何规模阈值;作者是维护者。
  • 方案 —— 范围自 4c86f15613 起已由维护者决定冻结,containment 重设计拆到后续 PR——十六轮之后这是正确决定。本次推送只是解冲突,没有夹带改动:十六个文件全部属于 review 命令 / review skill。
  • 风险(1e) —— 未命中任何与 revert 相关的高风险路径。

进入代码审查。🔍

Qwen Code · qwen3.8-max

Reviewed at 4cdbb9f65f9a76cc36dec9631840cde22bdb07be · re-run with @qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Scope of this pass. Round 16 reviewed 4c86f15613; this is the first look at the rebased head, so the review concentrates on the rebase delta and what round 16 left open.

The conflict resolution is what the author says it is — verified, not assumed:

One open item — round 16's only Critical (R16-1) still stands at this head. Verified against this commit, not inferred from the thread: when the base fetch fails outright (mergeBaseSha: null, baseFetchFailed: true — a transient blip, the normal state of a fresh CI checkout), the base-free containment arm demotes to containment-unverified without ever reading baseFetchFailed. That misclassifies a retryable fault as deterministic: this PR's own SKILL.md taxonomy lists containment-unverified among the reasons that "must NOT be retried", yet a re-run re-fetches the base — the component that failed — and would scope normally. The same taxonomy already splits exactly this state for the partition-failed exception (retryable when mergeBaseSha is null AND baseFetchFailed: true), so one transient cause currently gets a retryable label on one path and a deterministic one on the other. Outcome: a planless round, and the recovery flow never re-runs --since for that anchor. The refusal itself (fail closed) is right; the label and its retry class are not. The R16-1 thread has no reply, and the rebase push does not touch it.

Round 16's remaining 25 Suggestions — deferred to the follow-up PR per the maintainer's scope freeze; acknowledged here, not re-raised.

CI on this head — green. One honesty note: my first check-runs read caught the Linux unit suite mid-flight; the jobs API confirms it completed success at 16:11 UTC. No red checks of any kind on this commit.

Check Conclusion
Qwen Code CI — Test (ubuntu-latest, Node 22.x) ✅ success
Qwen Code CI — Test (macos-latest / windows-latest, Node 22.x) skipped (Linux-primary CI design)
Qwen Code CI — Integration Tests (CLI, No Sandbox) skipped
Qwen Code CI — Desktop Shell (ubuntu-22.04 / windows-2022) ✅ success
Qwen Code CI — web-shell E2E Smoke ✅ success
Security Checks — Secret scan (TruffleHog) ✅ success
Security Checks — Dependency CVE audit ✅ success

Sandboxed verification is already in flight — this run's trigger started @qwen-code /verify (run 31957681927) against this head. It is the lane that would settle the claim CI cannot: that the --since acceptance/refusal flow behaves end-to-end as the report contract promises — the handler wiring needs live git+gh, which the unit suite mocks (the author's own disclosure). Report posts separately when the run completes.

Not verified: the author-reported local numbers ("review suite 3142/3143", typecheck/eslint clean under commands/review) — attributed here as the author's claim, not re-run; this review is static and never executes PR code. The CI table above is the test evidence.

中文说明

本轮审查范围。 第 16 轮审查的是 4c86f15613;这是 rebase 后 head 的首次审查,因此集中在 rebase 增量与第 16 轮遗留项。

冲突解决与作者所述一致——已核实,不是转述: #9265 引入的 diffSha256 摘要落在 publish() 内,哈希的是 writeFileSync 实际写入的字节。#9265 的契约是「哈希字节本身,而非其 utf8 解码」(main 自己的测试钉住了这一点,本 head 仍然满足);首次 rebase 做错了,修正后的形态——readRange 按字节返回、只在真正需要文本处解码——已经就位。冲突引入的两处非空断言已移除,改为显式空值分支。不带 --since 的路径行为不变:全量区间读一次、发布、报告形状相同——emptyDiff/collapsedFromUpstream 此前就是全量事实,现在读 fullText

一个遗留项——第 16 轮唯一的 Critical(R16-1)在本 head 上仍然存在。 是对照本 commit 核实的,不是从线程推断的:当 base 拉取整体失败(mergeBaseSha: null, baseFetchFailed: true——瞬时抖动,全新 CI 检出的常态)时,base-free 包含性分支直接降级为 containment-unverified,从不读取 baseFetchFailed。这把可重试故障误分类为确定性理由:本 PR 自己写的 SKILL.md 分类把 containment-unverified 列入「绝不重试」,而重跑会重新拉取 base——恰恰是失败的组件——本可正常收窄。同一份分类对 partition-failed 例外已经做过完全相同的拆分(mergeBaseSha 为 null 且 baseFetchFailed: true 时可重试),于是同一个瞬时原因目前在一条路径上是可重试标签,在另一条上是确定性标签。后果:本轮无 plan,且恢复流永远不会对该锚点重跑 --since。拒绝本身(fail closed)是对的;错的是标签和它的重试类别。R16-1 线程没有回复,rebase 推送也没有触及它。

第 16 轮其余 25 条 Suggestion —— 按维护者的范围冻结决定推迟到后续 PR;此处确认,不再重提。

本 head 的 CI —— 全绿。 一点诚实说明:我第一次读 check-runs 时 Linux 单测还在跑;jobs API 确认它已于 16:11 UTC 以 success 完成。本 commit 上没有任何红色检查。上方表格为机器可读区,finalize 工作流会在 CI 变化时原地更新。

沙箱验证已在运行——本次触发已启动 @qwen-code /verify(run 31957681927),针对本 head。它是唯一能落定 CI 无法落定的主张的途径:--since 的接受/拒绝流程端到端是否符合报告契约——handler 接线需要真实 git+gh,单测是 mock 的(作者自己也如此披露)。运行结束后报告会单独发布。

未验证: 作者自报的本地数字(「review 套件 3142/3143」、commands/review typecheck/eslint 干净)——此处仅作为作者声明转述,未重跑;本审查是静态的,从不执行 PR 代码。上方 CI 表格即测试证据。

Qwen Code · qwen3.8-max

Reviewed at 4cdbb9f65f9a76cc36dec9631840cde22bdb07be · re-run with @qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 3/5 — the rebase is exactly what it claims and I verified it line by line, CI is green on this head, but round 16's only Critical remains open and unacknowledged, and that is a maintainer's call, not mine.

Honest read: on engineering merit this PR has earned its approval. Sixteen rounds of hardening are real — the fail-open discipline is consistent, the reason/diffPath split finally makes the report contract honest, and the freeze-and-split decision (containment redesign to a follow-up) was the right call at round 16. The rebase itself is careful: the byte-hash miss was caught by main's own test and corrected the right way, which is exactly what that discipline is for. My independent baseline for "validate and scope an incremental anchor" is what landed here; I found no simpler path it missed, and nothing in the rebase delta beyond conflict resolution.

What keeps me from approving is one verified fact, not a vibe: R16-1. The base-free containment arm labels a transient base-fetch failure containment-unverified — a reason this PR's own SKILL.md files under "must NOT be retried" — while the same transient cause gets a retryable label one path over, in the partition-failed exception. Under this PR's own freeze policy Criticals are still fixed before merge; the thread has no reply, and the rebase note does not mention it. Two human approvals landed on this head after round 16 was public, so this may be a deliberate acceptance — but nothing on the PR says so, and I am not going to guess.

@wenshao — one question stands between this head and an approval: fix R16-1 here (branch on baseFetchFailed in that arm, mirroring the partition-failed exception — a small change with the taxonomy already written for it), or consciously defer it to the follow-up PR and say so on the thread. Either answer resolves this run.

Housekeeping: the standing round-16 CHANGES_REQUESTED review already gates this PR and is deliberately NOT re-submitted. No approval is posted this run and no deferred-approval marker is emitted — the verdict is defer, not approve. The sandboxed /verify report will post separately when its run completes.

中文说明

置信度:3/5 —— rebase 与它声称的完全一致,我逐行核实;本 head 的 CI 全绿;但第 16 轮唯一的 Critical 仍未闭环、也没有任何回应,而那是维护者的决定,不是我的。

直说:论工程质量,这个 PR 已经配得上批准。十六轮加固是实打实的——fail-open 纪律一以贯之,reason 与 diffPath 的拆分终于让报告契约诚实,冻结范围并把 containment 重设计拆出去在第 16 轮是正确决定。rebase 本身也很谨慎:字节哈希的错误被 main 自己的测试抓住并以正确方式修正,这正是该纪律存在的意义。我为「校验并收窄增量锚点」写下的独立基线就是最终落地的方案;没有找到它错过的更简路径,rebase 增量里也没有解冲突之外的东西。

挡住我的不是感觉,是一个核实过的事实:R16-1。base-free 包含性分支把一次瞬时的 base 拉取失败标成 containment-unverified——本 PR 自己写的 SKILL.md 把这个理由归入「绝不重试」——而同一个瞬时原因在隔壁的 partition-failed 例外里却拿到可重试标签。按本 PR 自己的冻结政策,Critical 仍然要在合并前修复;该线程没有回复,rebase 说明也没有提到它。两位人类维护者在第 16 轮公开之后批准了本 head,所以这也可能是有意识的接受——但 PR 上没有任何话这么说,我不打算猜。

@wenshao —— 本 head 与批准之间只隔一个问题:在这里修掉 R16-1(在该分支上按 baseFetchFailed 分流,镜像 partition-failed 例外的写法——改动很小,分类表已经为它写好),或者有意识地把它推迟到后续 PR 并在线程里说明。两种回答都能结束本轮。

流程说明:既有的第 16 轮 CHANGES_REQUESTED 评审仍在拦截本 PR,刻意不重复提交。本轮不发布批准、也不发出推迟批准标记——裁决是 defer,不是 approve。沙箱 /verify 运行结束后报告会单独发布。

Qwen Code · qwen3.8-max

Reviewed at 4cdbb9f65f9a76cc36dec9631840cde22bdb07be · re-run with @qwen-code /triage

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 84.49% 84.49% 90.27% 83.71%
Core 88.03% 88.03% 89.57% 86.58%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   84.49 |    83.71 |   90.27 |   84.49 |                   
 src               |   85.69 |    81.73 |   88.03 |   85.69 |                   
  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.12 |    82.41 |   88.88 |   88.12 | ...3108,3114,3180 
  ...liCommands.ts |   88.64 |    82.96 |      80 |   88.64 | ...77-579,593,692 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   72.26 |     74.7 |   91.58 |   72.26 |                   
  acpAgent.ts      |   71.66 |    74.53 |   91.13 |   71.66 | ...35,12840-12842 
  ...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.09 |    86.16 |   96.35 |   91.09 |                   
  Session.ts       |    90.4 |    84.68 |   95.96 |    90.4 | ...16,11643-11647 
  ...entTracker.ts |    96.8 |    89.36 |      90 |    96.8 | 137-143,221       
  ...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.11 |     86.3 |     100 |   94.11 | ...11,315,395,399 
  ...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.7 |    93.37 |   96.87 |    95.7 |                   
  ...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 |   99.18 |    96.47 |     100 |   99.18 | 355-356           
 ...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      |   91.03 |       80 |   66.66 |   91.03 |                   
  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         |   90.08 |    77.84 |     100 |   90.08 | ...81,884-887,899 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   89.08 |    88.57 |   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.61 |   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.91 |   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 |     90.9 |     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 |    57.14 |     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 |   89.29 |    89.26 |   89.91 |   89.29 |                   
  agent-prompt.ts  |   93.94 |    92.55 |   97.43 |   93.94 | ...2755,2910-2990 
  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       |   89.81 |    84.68 |   84.61 |   89.81 | ...89-594,596-597 
  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.07 |    93.13 |   97.29 |   97.07 | ...2814,2842-2864 
  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      |   93.53 |     93.3 |   85.71 |   93.53 | ...1085,1219-1224 
  findings.ts      |   91.19 |     91.5 |   96.29 |   91.19 | ...1143,1152-1153 
  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    |   93.26 |    80.93 |     100 |   93.26 | ...1202,1264-1280 
  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 |    90.08 |     100 |      94 | ...50-451,466-471 
  ...ve-anchors.ts |   78.34 |    89.28 |      75 |   78.34 | ...83-188,200-217 
  run.ts           |   84.16 |    89.06 |   94.11 |   84.16 | ...88,604-652,665 
  save-artifact.ts |   90.25 |    83.33 |   94.11 |   90.25 | ...25-328,421-424 
  script-lint.ts   |   81.14 |    79.23 |   88.88 |   81.14 | ...59-773,775-797 
  submit.ts        |   85.01 |    86.36 |      90 |   85.01 | ...99,588,615-651 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  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.69 |    95.09 |   98.61 |   97.69 |                   
  agent-briefs.ts  |      99 |      100 |      50 |      99 | 746-747           
  ...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.89 |     100 |     100 | 805,845           
  coverage.ts      |    96.6 |    93.05 |     100 |    96.6 | ...1115,1669-1670 
  deadline.ts      |   98.67 |    94.05 |     100 |   98.67 | 207,618,650,718   
  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 |                   
  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 |   97.36 |    95.37 |     100 |   97.36 | ...86,409,770,787 
  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       
  run-ledger.ts    |   98.15 |     93.7 |     100 |   98.15 | ...23,521,627,650 
  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 | 172               
  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 |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.94 |    89.86 |   96.28 |   94.94 |                   
  ...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 |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...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 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     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          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  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.12 |    94.18 |   95.29 |   98.12 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1416,1432-1433 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.49 |      100 |   90.47 |   98.49 | 85-86,126-127     
  ...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.14 |    84.53 |   90.94 |   88.14 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.43 |    92.95 |     100 |   93.43 | ...20-321,324-326 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 685               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    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.1 |    77.83 |   94.73 |    90.1 | ...1014,1021-1026 
  ...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.63 |    91.57 |     100 |   98.63 | ...1489,1491-1492 
  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-144             
  ...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.46 |    80.62 |    75.6 |   84.46 | ...7591,7597-7598 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.25 |    88.99 |     100 |   94.25 | ...28,532-533,572 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   90.96 |    91.34 |   72.32 |   90.96 | ...2731,2745-2749 
  ...-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 |   93.89 |     87.5 |     100 |   93.89 | ...18-519,525-526 
  ...e-remember.ts |   98.23 |    92.56 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   83.98 |    90.29 |     100 |   83.98 | ...48-156,216-237 
  ...me-storage.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.26 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   80.37 |    80.96 |   94.04 |   80.37 |                   
  ...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.26 |   98.52 |   93.03 | ...1624,1671-1682 
  dispatch.ts      |   75.59 |    78.48 |   91.37 |   75.59 | ...5363,5420-5426 
  index.ts         |   82.43 |    80.18 |   91.07 |   82.43 | ...2360,2444-2445 
  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 |   92.81 |    90.51 |     100 |   92.81 |                   
  ...me-manager.ts |     100 |      100 |     100 |     100 |                   
  ...-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    |   77.56 |    68.68 |   90.08 |   77.56 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  discovery.ts     |   85.77 |    76.92 |      90 |   85.77 | ...49-250,255-256 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.75 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |   75.99 |    65.18 |   85.71 |   75.99 | ...1883,1974-1975 
  ...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.3 |    59.78 |   93.33 |    86.3 | ...1160,1184-1191 
  ...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.83 |    77.58 |     100 |   94.83 | ...18,327-330,350 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/serve/routes  |   86.07 |    80.33 |   94.72 |   86.07 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |   98.63 |    95.65 |     100 |   98.63 | 76                
  ...nel-notify.ts |   86.45 |       88 |     100 |   86.45 | ...,83-87,103-104 
  ...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          |    82.4 |    71.42 |     100 |    82.4 | ...-94,96-101,121 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.29 |    82.94 |   92.59 |   87.29 | ...1275,1318-1319 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   87.07 |    82.14 |   90.41 |   87.07 | ...4985,4987-4988 
  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.92 |    79.69 |     100 |   90.92 | ...81-482,501-502 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.15 |    74.95 |   92.98 |   88.15 | ...2027,2072-2073 
  ...-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 
  ...management.ts |   87.44 |    84.23 |     100 |   87.44 | ...1667,1687-1692 
  ...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 |   78.92 |    66.21 |      80 |   78.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   91.77 |    89.32 |   96.95 |   91.77 |                   
  access-log.ts    |    98.7 |    97.14 |     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.7 |    72.77 |     100 |    86.7 | ...57,774,837-846 
  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 |    73.33 |   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.55 |    87.27 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   95.86 |    93.37 |     100 |   95.86 | ...-848,1026-1030 
  telemetry.ts     |   99.04 |    97.44 |     100 |   99.04 | ...37,652,794-796 
 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.66 |    87.77 |   91.11 |   90.66 |                   
  index.ts         |   90.14 |    87.08 |   89.74 |   90.14 | ...1466-1470,1473 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.49 |    89.25 |      98 |   92.49 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 105-118           
  ...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 |   88.23 |    86.84 |     100 |   88.23 | ...94-199,232-233 
  ...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.24 |    75.58 |   67.39 |   73.24 |                   
  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        |      60 |      100 |   35.29 |      60 | ...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 |   70.51 |       74 |    62.5 |   70.51 | ...09,336,389-394 
  ...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.35 |    83.55 |   89.88 |   83.35 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  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 |   69.07 |     72.6 |   84.61 |   69.07 | ...78-611,622-623 
  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 |   71.96 |    79.54 |   79.56 |   71.96 |                   
  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 |       0 |        0 |       0 |       0 | 1-598             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-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.28 |    66.99 |     100 |   79.28 | ...08,511,514-520 
  ...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 |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-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 |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-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 |       0 |        0 |       0 |       0 | 1-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 |       0 |        0 |       0 |       0 | 1-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 |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...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 |    42.3 |    68.69 |   73.68 |    42.3 |                   
  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 |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-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.26 |    86.89 |   85.57 |   90.26 |                   
  ...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.4 |   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 |    86.86 |      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 |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-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   |   84.16 |    81.76 |   85.13 |   84.16 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  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 |    79.56 |    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    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   85.93 |    83.93 |   87.78 |   85.93 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     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.86 |    71.67 |   83.33 |   86.86 | ...1540,1562-1566 
  ...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 |      42 |       75 |     100 |      42 | 42-44,53-59,62-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   |       0 |        0 |       0 |       0 | 1-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.36 |    84.33 |   77.77 |   87.36 | ...5692-5694,5696 
  ...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.61 |    85.68 |   95.81 |   87.61 |                   
  ...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.46 |     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.38 |    92.38 |     100 |   98.38 | 108,136-137,343   
  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.24 |     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.03 |     97.1 |     100 |   96.03 | 103-106           
  ...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 |   82.86 |    79.48 |     100 |   82.86 | ...88-610,741-742 
  ...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     |   97.94 |    95.49 |   94.11 |   97.94 | ...82-283,443-444 
  ...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.3 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    66.38 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     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.92 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |      100 |       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.57 |    87.31 |    92.7 |   81.57 |                   
  ...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.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  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                
  ...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.03 |    86.58 |   89.57 |   88.03 |                   
 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.45 |    84.65 |   94.88 |   90.45 |                   
  ...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 
 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.22 |    86.83 |   89.31 |   91.22 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  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 |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   92.92 |    90.57 |   84.61 |   92.92 | ...2012,2061-2064 
  ...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 | ...1705,1711-1712 
  ...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.72 |    84.65 |   89.05 |   82.72 |                   
  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   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  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.09 |    86.63 |   75.15 |   84.09 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   83.38 |    86.34 |   73.59 |   83.38 | ...8728,8732-8733 
  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.46 |    88.19 |    93.3 |   92.46 |                   
  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 |   90.05 |    84.67 |   96.15 |   90.05 | ...6219,6247-6263 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  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 | 680-681,750       
  ...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.86 |    90.62 |   95.61 |   91.86 |                   
  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.48 |    91.27 |     100 |   95.48 | ...1309,1317,1416 
  ...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.62 |   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.26 |   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      |   79.94 |    79.28 |    90.9 |   79.94 |                   
  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   |   71.88 |    65.71 |   71.42 |   71.88 | ...55-656,663-664 
  ...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.81 |   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 |     79.1 |   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.97 |   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 |    47.82 |   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.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   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.3 |    85.75 |    96.9 |    90.3 |                   
  ...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 |   91.92 |    86.38 |    94.8 |   91.92 | ...2365,2392-2393 
  ...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 |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...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 |     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             
  ...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.79 |   96.05 |   89.31 | ...2643,2657-2677 
  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.28 |   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 |    88.31 |   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.1 |   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 |      100 |       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 | ...69-570,586-592 
  ...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.92 |    87.48 |   88.59 |   86.92 |                   
  agent.ts         |   85.51 |    86.38 |   86.17 |   85.51 | ...4333,4367-4377 
  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.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.95 |    89.65 |   96.91 |   92.95 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  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.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  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.6 |     100 |   90.88 | ...25-626,628-630 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  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 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   96.21 |    85.34 |     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 |       92 |     100 |     100 | 50-52             
  ...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 |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  ...-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 |       64 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     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.59 |     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.

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 explored to full depth (tool budget reached): "This PR moves incremental-review scoping into the CLI:…": none — all planned checks completed within budget..

中文说明

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

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

未探索到全部深度(达到工具调用预算):"This PR moves incremental-review scoping into the CLI:…"none — all planned checks completed within budget.

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

Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/core/src/skills/bundled/review/SKILL.md
Comment thread packages/core/src/skills/bundled/review/SKILL.md Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/core/src/skills/bundled/review/SKILL.md Outdated
@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 13, 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: 76 passed · 0 failed · 76 total

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

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

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

Verification report

PR #9100 — feat(review): validate and scope the incremental anchor inside fetch-pr

Verdict: merge-ready — 76/76 scripted assertions passed, 0 unexpected failures.
Verified head: f54a3d1d778aeee58f8d18203549553983dd9ef9 (merge 6affbf0164, base tip 1095e0bbc4).
First verification round (no previous-report.md present).

中文摘要
  • 结论: merge-ready。76/76 脚本断言通过,0 意外失败。
  • A/B 结论: 不传 --since 时,base(1095e0bbc4)与 head 的真实 runFetchPr handler 在 6 个场景下 report/stderr/stdout 逐字节一致(见 "A/B regression" 表与 04-ab-regression.png)——无回归。传 --since 时,resolveIncrementalAnchor 对真实 git(非 mock)的 49 项断言全部通过:合法锚点收窄、锚点即 head 报 upToDate、未知/非祖先/旗标形状锚点一律回退全量且原因入报告,hex 白名单在任何探针之前短路。
  • Findings(均非阻塞): ① agent-prompt 的 role-7 --base diffBase 接线无单测(变异 M7 存活,232/232 绿;行为本身经 harness 8/8 验证正确)——建议补测;② isEmptyDiff 前的 !scopedDelta && 为死子句(变异 M1 存活),属无害冗余,真正承重的是 isCollapsedFromUpstream 前的同名门(变异 M2 被杀);③ 若 buildDiffPlan 在 delta 上抛错,降级后 incremental 仍报 effective: truediffPath 为 null——过声明但有界(diffPath 为 null 是主信号且有 WARNING)。
  • 未覆盖: 逐 commit 归因(shallow checkout 仅可达 2 个 commit 中的 1 个,验证的是聚合 diff);对真实 git+gh 的端到端 fetch-pr(无网络/凭据,handler 经 producer mock 与编译产物的纯函数对真实 git 验证);SKILL.md 编排 prose 的模型遵循度;Windows/macOS。

Central claim and A/B proof

Central claim: fetch-pr --since <sha> validates the anchor against the fetched history (hex allowlist → cat-file -emerge-base --is-ancestorrev-parse, behind an injectable probe) and rules effective (diff+plan scoped to since..head), upToDate (full-range plan kept), or refused (unknown-commit / not-an-ancestor / capture-failed) — and the failure direction is always the FULL diff, never a narrower or misstated scope.

Secondary claims: (1) the empty-delta capture must not leak into emptyDiff and upToDate demotes when the full-range capture did not survive (the shipped Critical); (2) emptyDiff/collapsedFromUpstream are skipped on a delta scope and incremental.diffBase feeds Agent 7's --base; (3) without --since the command is byte-for-byte unchanged.

A/B regression (no --since), base vs head — witness 04-ab-regression.png

One byte-identical vitest harness driven through the real runFetchPr handler (producers mocked identically) in a scratch worktree at HEAD^1 and in the head tree; normalized report JSON + stderr + stdout compared per scenario.

cell scenario head base comparison
S1 merge-base resolved, non-empty diff 6/6 6/6 IDENTICAL
S2 merge-base unresolvable (stderr warn, diffPath null) IDENTICAL
S3 capture throws (diffPath null, "Failed to capture diff") IDENTICAL
S4 genuinely empty full diff → emptyDiff: true IDENTICAL
S5 collapse ratio fires on full range IDENTICAL
S6 baseFetchFailed with non-empty diff IDENTICAL

6/6 cells byte-for-byte identical — the no-flag behavior is unchanged by the refactor. (Control cleanliness: the base worktree's node_modules were symlinks into the head install; the PR leaves package.json/lockfile untouched, and vitest aliases @qwen-code/qwen-code-core to each tree's own core source — readlink -f asserted; the PR's only core change is SKILL.md text, so no code confound.)

Anchor ruling against REAL git (compiled dist, no mocks) — witness 02-anchor-real-git.png

resolveIncrementalAnchor imported from the built dist/ and driven with real git cat-file -e / merge-base --is-ancestor / rev-parse child processes over a scratch repo (mainline, unmerged side branch, merged side branch). 49/49: valid anchor → effective + full-sha diffBase; anchor-at-head → upToDate, diffBase: null; unknown 40-hex → unknown-commit after exactly one commitExists call; side-branch commit → not-an-ancestor; merged-branch ancestry effective; 15 flag-shaped/non-hex inputs (--upload-pack=…, HEAD, $(rm -rf /), 6-hex, 65-hex, interior space, trailing newline, empty, …) never reach a probe and are refused; JS-level non-strings refused without throwing; mixed-case and unique 7-char abbreviations resolve safely; a 200 000-char anchor is refused in 0.11 ms with zero probe calls.

Feature cells through the real handler — 4/4

Cells the shipped suite does not pin: delta scope works when the base fetch failed (range needs no base); a refused anchor still falls back to a successful full-range capture; a delta-capture failure falls back to a successful full capture; anchor-at-head through the handler yields upToDate with the full range.

Mutation matrix — witness 01-mutation-matrix.png

Each mutant applied to the head source, fetch-pr.test.ts/agent-prompt.test.ts run, then restored via git checkout.

mutant observed classification
M0 positive control (isEmptyDiff inverted) KILLED (3 red, incl. 2 pre-existing isEmptyDiff tests) harness-alive proof
M1 drop !scopedDelta gate on emptyDiff SURVIVED (46/46) dead code — with scopedDelta, diffText is the non-empty delta, so isEmptyDiff (needs diffText.trim()==='') can never be true; harmless redundancy
M2 drop !scopedDelta gate on collapsedFromUpstream KILLED by "scopes the plan to a valid anchor…" (expected true to be undefined) load-bearing gate pinned
M3 drop diffPath reset before fallback KILLED by "does not let an empty delta leak into emptyDiff…" Critical half #1 pinned
M4 drop upToDate→capture-failed demotion KILLED by the same test Critical half #2 pinned
M5 drop hex allowlist regex KILLED by "never hands a flag-shaped or non-hex anchor to git" security gate pinned
M6 rename builder option sincesinceX KILLED by the builder test registration pinned
M7 revert role-7 base to mergeBaseSha SURVIVED (232/232) coverage gap — behavior verified correct by 03-agent7-brief.png (8/8)
M8 positive control (role gate '7''77') KILLED (6 red) agent-prompt suite-alive proof

No mutant regressed from killed to survived; both positive controls prove each suite can fail.

Reviewer Test Plan walkthrough

  1. npx vitest run src/commands/review/fetch-pr.test.ts46/46 on head (matches the claimed coverage; the anchor/flag-shape/rev-parse cases all pass).
  2. Handler wiring reads — confirmed in code and by M3/M4/F-cells: delta capture precedes the full-range capture and never consults mergeBaseSha; empty delta upgrades to upToDate and recaptures full; failed delta downgrades to capture-failed.
  3. SKILL.md Step 1 — outcome table now keys on incremental (effective/upToDate/reason); recovered-anchor bullet re-runs fetch-pr --since; setup-batch ordering names the side-file re-run before repo-context. SKILL.test.ts 8/8.

Findings (non-blocking)

F-1 (Suggestion) — role-7 --base diffBase wiring has no unit test. Mutant M7 (revert to mergeBaseSha) survives agent-prompt.test.ts 232/232, while positive control M8 kills 6 tests — the suite is alive but nothing asserts the new selection. The behavior itself is correct (harness 03-agent7-brief.png: delta round welds diffBase, upToDate/refused/malformed shapes fall back to mergeBaseSha, 8/8). A future refactor could silently send Agent 7's test-efficacy probe the full range on a delta round; add one test pinning --base per incremental shape.

F-2 (nit) — the !scopedDelta gate on isEmptyDiff is dead code. When scopedDelta, diffText is the non-empty delta, so isEmptyDiff is false regardless; M1 survives. Harmless defensive redundancy; the sibling gate on isCollapsedFromUpstream is the load-bearing one (M2 killed). Completeness reporting, not a merge condition.

F-3 (nit) — buildDiffPlan degradation overstates scope on a delta. If buildDiffPlan(diffText) throws on a scoped delta, the handler resets diffPath/diffPathAbsolute but leaves incremental: {effective: true, diffBase} in the report — a scope claim with no diff file. Bounded: diffPath: null plus the loud WARNING remain the master signals and the failure direction is fallback-to-manual, the same as the pre-existing full-range degradation. Consider demoting incremental to capture-failed on that path for symmetry with the upToDate demotion.

Not covered

  • Per-commit attribution: the shallow checkout makes only 1 of the 2 PR commits locally reachable (rev-list HEAD^1..HEAD^2 = 1 vs 2 in the metadata); the aggregate HEAD^1..HEAD diff was verified instead.
  • Live end-to-end fetch-pr against real git fetch + gh (no network/token in this container). The handler was exercised through its producer seams and the compiled pure functions against real git; the wire to GitHub was not.
  • SKILL.md prose compliance — whether an orchestrating model follows the new bullets is behavioral and out of scope; SKILL.test.ts (8/8) covers structure.
  • Windows/macOS (Linux node:22-bookworm container).
  • Repo-wide suites beyond the affected surface; targeted gates below are what ran.

Targeted gates (exact counts)

  • packages/cli src/commands/review: 69 files, 2508 passed | 4 skipped | 0 failed (the author's stale-bundle failure does not reproduce here — it passes with a fresh build, consistent with their "stale local build" note; stale-bundle.test.ts 28/28 green).
  • packages/cli fetch-pr.test.ts: 46/46. packages/core review SKILL.test.ts: 8/8.
  • tsc --noEmit (cli): clean. eslint on the 5 changed .ts files: clean; gate proven live (planted unused-var/any violations reported, then removed).

Methodology

Environment: node:22-bookworm CI container, refs/pull/9100/merge at depth 2 (HEAD 6affbf0164, base 1095e0bbc4, head f54a3d1d77); npm ci + npm run build pre-run at HEAD. Harnesses live in harness/ (anchor-real-git.mjs, agent7-brief.mjs, ab-compare.mjs, mutation-summary.mjs); raw per-cell logs in logs/ (01–10). The A/B base arm ran a scratch git worktree at HEAD^1 with symlinked node_modules (lockfile untouched by the PR) and was removed afterwards; the anchor and brief harnesses import the compiled dist/ and drive real git / the pure brief builder with no stub of the unit under test. Evidence PNGs rendered by scripts/verify-capture.mjs.

Evidence images

01-mutation-matrix

02-anchor-real-git

03-agent7-brief

04-ab-regression

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Triage re-run completed a full review of the new head 25aa69e053df6c6baaf3f73832b7b9e37f572d46 (the third commit, answering the six R2 findings). All three stage comments above were updated in place. Verdict: approve, deferred until CI lands green on the reviewed commit — the finalize workflow posts the commit-pinned approval when the checks settle. Sandboxed verification of this head is running in parallel and will post its own report.

中文说明

Triage re-run 已完成对新 head 25aa69e053df6c6baaf3f73832b7b9e37f572d46(第三个 commit,逐条回应六条 R2 发现)的完整审查。上方三条 stage 评论均已原地更新。结论:批准,推迟到 CI 在被审 commit 上落绿——检查落定后由 finalize 工作流发布钉住该 commit 的批准。本 head 的沙箱验证正在并行运行,将单独发布报告。

Qwen Code · 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.

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.

Partially reviewed — gaps disclosed. Suggestions are inline.

Not explored to full depth (tool budget reached): "You are review agent reverse-audit — Reverse audit agent…": none — all checks above completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none (finished within budget).; "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started were completed within budget..

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

中文说明

仅完成部分审查,审查缺口已披露。 建议见行内评论。

未探索到全部深度(达到工具调用预算):"You are review agent reverse-audit — Reverse audit agent…"none — all checks above completed within budget."You are review agent reverse-audit — Reverse audit agent…"none (finished within budget)."You are review agent reverse-audit — Reverse audit agent…"none — all checks I started were completed within budget.

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

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

Comment thread packages/cli/src/commands/review/agent-prompt.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts
Comment thread packages/cli/src/commands/review/fetch-pr.ts
@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 13, 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: 74 passed · 0 failed · 74 total

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

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

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

Verification report

<!-- qwen-triage:verify -->
<!-- qwen-triage:verify-substantive -->

Sandboxed verification: ✅ passed — merge-ready (agent verdict) - follow-up round at head 25aa69e053

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: 74 passed · 0 failed · 74 total

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

第二轮(follow-up)验证,新 head 25aa69e053(第 3 个 commit:clamp 锚点到 merge base、captureRange 只返回文本、partition 失败降级、full-range-unavailable 独立原因、补齐测试钉点)。74/74 脚本断言通过,0 意外失败。

  • 上轮 findings 状态:F-1(role-7 --base 无测试)→ fixed(变异 M-F1 本轮被杀,1 failed | 232 passed);F-2(isEmptyDiff 前的 !scopedDelta 死门)→ stands(M-F2 仍存活,无害冗余,同意保留);F-3(delta 上 partition 失败过声明)→ fixed(M-F3 被杀,1 failed)。
  • A/B 结论:不传 --since 时 base(8e0033d64d)与 head 的 6 场景 report/stderr 逐字节一致(12/12 工件相同,见 03-ab-regression-identical.png);resolveIncrementalAnchor 对真实 git 28/28,新增 behind-merge-base clamp 在部分合入拓扑下正确拒绝、边界(锚点==merge base、null base 跳过 clamp)正确,见 01-anchor-real-git-clamp.png
  • 新 finding(非阻塞 nit)upToDate 全量范围在 buildDiffPlan partition 失败后不被降级(delta 路径在同一 catch 里降级了,upToDate 没有)——报告在 diffPath 为 null 时仍声称 effective/upToDate;有界(diffPath:null + WARNING 是主信号,无 scope 分歧),并附实测最小修复(else-if 分支降级为 full-range-unavailable,套件 283/283 不变)。
  • 未覆盖:逐 commit 归因(shallow,3 个 commit 仅 1 个可达);真实 git fetch+gh 端到端;SKILL.md 编排 prose 的模型遵循度;Windows/macOS。
Verification report

PR #9100 — feat(review): validate and scope the incremental anchor inside fetch-pr (round 2)

Verdict: merge-ready — 74/74 scripted assertions passed, 0 unexpected failures.
Verified head: 25aa69e053df6c6baaf3f73832b7b9e37f572d46 (merge 2724f2998e, base tip 8e0033d64d).
Follow-up round: previous-report.md present (round 1 at head f54a3d1d77, verdict merge-ready, 76/76).

Previous-round finding status (re-measured at the new head)

# finding (round 1) severity status at 25aa69e053 evidence
F-1 role-7 --base diffBase wiring unpinned (mutant survived 232/232) Suggestion fixed new agent-prompt test kills the revert mutant (M-F1: 1 failed | 232 passed, at agent-prompt.test.ts:2190); 02-mutation-matrix-round2.png
F-2 !scopedDelta gate on isEmptyDiff is dead code nit stands (agree) M-F2 re-run: still SURVIVED all-green; the load-bearing sibling gate on collapsedFromUpstream remains pinned; harmless defensive redundancy, kept deliberately
F-3 buildDiffPlan partition failure overstates scope on a delta (effective: true over a planless report) nit fixed the catch now demotes to capture-failed; M-F3 killed (1 failed, at fetch-pr.test.ts:585); status line post-planning re-measured by feature cell F5

Declined/deferred rows were re-measured, not diffed: F-2's classification rests on this round's M-F2 run, not round 1's.

Central claim (round-2 delta) and A/B proof

Central claim: resolveIncrementalAnchor clamps the anchor to the merge base — an anchor that is an ancestor of the head but OLDER than the merge base (a partial merge landing between rounds, or a tampered deep-history sha) is refused as behind-merge-base, failing open to the FULL diff; null merge base skips the clamp. The failure direction is never a wider scope.

Secondary claims: (1) round-1 findings F-1/F-3 are fixed and F-2's classification holds; (2) the captureRange/acceptCapture refactor keeps no---since behavior byte-identical; (3) the new full-range-unavailable reason and the post-planning status line behave as specified on every demotion path.

Anchor ruling against REAL git (compiled dist, no mocks) — witness 01-anchor-real-git-clamp.png

Scratch repo with the partial-merge topology (main lands C1 via merge while the PR branch continues to C2; merge-base = C1; cached anchor M1 now older than the base). Probes wired exactly as the handler does (cat-file -e <sha>^{commit}, merge-base --is-ancestor a b, rev-parse <sha>^{commit}). 28/28:

cell oracle result
anchor M1 < merge base C1 behind-merge-base, diffBase null PASS
clamp probe shape merge-base --is-ancestor <mergeBase> <anchor> PASS
anchor == merge base effective; delta == full PR range (f2.txt only) PASS
null merge base clamp skipped → effective (base-free design) PASS
anchor C1..C2 delta is only f2.txt PASS
anchor == head upToDate, diffBase null PASS
unknown 40-hex / tree sha / side-branch / base-side merge commit unknown-commit ×2 / not-an-ancestor ×2 PASS
7-char abbreviation, mixed-case hex resolve to full sha, effective PASS
12 flag-shaped/non-hex inputs refused with 0 probe calls PASS
200k-char anchor refused in 0.10 ms, 0 probes PASS
garbage mergeBaseSha fails CLOSED → behind-merge-base PASS

A/B regression (no --since), base 8e0033d64d vs head — witness 03-ab-regression-identical.png

Byte-identical vitest harness (same mocks, same scenarios) through the real handler in a scratch worktree at HEAD^1 and in the head tree; normalized report JSON + stderr compared per scenario. 6/6 cells byte-identical (12/12 artifacts), 6/6 in-arm oracles per side:

cell scenario head base comparison
S1 merge-base resolved, non-empty diff 6/6 oracles 6/6 IDENTICAL
S2 merge-base unresolvable (warn, diffPath null) IDENTICAL
S3 capture throws (diffPath null) IDENTICAL
S4 genuinely empty full diff → emptyDiff: true IDENTICAL
S5 collapse ratio fires on full range IDENTICAL
S6 baseFetchFailed with non-empty diff IDENTICAL

Control cleanliness: the base worktree has no nested node_modules (gitignored); the root ajv is 6.12.6 while core needs 8.20.0 from packages/core/node_modules, so the per-package nested node_modules were symlinked into the base tree (lockfile untouched by the PR — git diff HEAD^1..HEAD names no package.json/lockfile). The unit under test imports only cli-local modules and node builtins; vitest aliases @qwen-code/qwen-code-core to each tree's own source; readlink -f asserted. The only normalized difference between arms is the tree-root prefix inside diffPathAbsolute.

Handler feature cells (paths the shipped suite does not pin) — witness 04-feature-cells-handler.png

cell oracle result
F1 valid anchor + baseFetchFailed (merge base null) → delta effective, clamp skipped, "Incremental: scoped to" + WARNING PASS
F2 delta capture throws, full range succeeds → capture-failed, full diff captured, stderr "reviewing the full diff." PASS
F3 empty delta → upToDate, full-range capture THROWS → full-range-unavailable, stderr "no diff could be captured" (not "reviewing the full diff") PASS
F4 partition failure on the upToDate full range → documents residual shape (see N-1) PASS (documents)
F5 delta partition failure → status line narrates the demoted state ("refused (capture-failed); no diff could be captured"), never "scoped to" PASS
F6 behind-merge-base AND full-range capture also fails → refused with reason, no diff, correct stderr PASS

Mutation matrix (round 2) — witness 02-mutation-matrix-round2.png

Each mutant applied to the head source, fetch-pr.test.ts + agent-prompt.test.ts run (283/283 unmutated control green), restored byte-exact.

mutant observed classification
M0 positive control (isEmptyDiff → false) KILLED (1 failed) suite-alive proof
M-CLAMP drop the merge-base clamp KILLED (3 failed: unit clamp test + handler end-to-end + probe-shape) round-2 central claim pinned
M-F1 revert role-7 base to mergeBaseSha (round-1 M7) KILLED (1 failed | 232 passed, agent-prompt.test.ts:2190) F-1 fix pinned — survived 232/232 in round 1
M-F3 drop the partition-failure demotion (round-1 fix) KILLED (1 failed, fetch-pr.test.ts:585) F-3 fix pinned
M-F2 drop !scopedDelta gate on isEmptyDiff (round-1 M1) SURVIVED (all green) dead code, stands — with scopedDelta, diffText is the non-empty delta so isEmptyDiff can never be true; the sibling gate on collapsedFromUpstream is the load-bearing one
M-REASON conflate full-range-unavailable into capture-failed KILLED (1 failed, reason + stderr text) new reason pinned
M-ORDER transpose the clamp probe operands KILLED (2 failed) operand order pinned by invocation-shape assertions

No mutant regressed from killed to survived; both positive-control expectations (M0 kill, M-F2 survive-as-classified) hold. Every kill failed the INTENDED assertion (failure messages quote expected-vs-actual; see logs/mutation-matrix.log).

Reviewer Test Plan walkthrough

  1. npx vitest run src/commands/review/fetch-pr.test.ts50/50 (round 1: 46/46; +4 new handler cells). agent-prompt.test.ts 233/233 (+1).
  2. Handler wiring reads — re-verified by behavior, not reading: delta capture precedes the full-range capture and never consults the base (F1); empty delta upgrades to upToDate and recaptures full (suite + F3); failed delta downgrades to capture-failed with a successful full fallback (F2).
  3. SKILL.md Step 1 — cache read before fetch-pr with --since; outcome table keys on incremental; recovered-anchor bullet re-runs fetch-pr --since ("never run git against an anchor yourself"); setup-batch names the side-file re-run before repo-context. SKILL.test.ts 8/8.

Findings (non-blocking)

N-1 (nit) — an upToDate ruling survives a buildDiffPlan partition failure without demotion. The round-2 catch demotes a delta-scoped ruling (scopedDelta && anchor) but not the upToDate shape: when the full-range capture succeeded (so the pre-planning full-range-unavailable demotion did not fire) and buildDiffPlan then throws, the report publishes incremental: {effective: true, upToDate: true} with diffPath: null — the same overclaim class round 1's F-3 fixed for the delta path, one sibling down. Measured by feature cell F4. Bounded: diffBase is null everywhere (no scope divergence between Agent 7 and other readers, unlike the delta case), diffPath: null plus the loud partition WARNING remain the master signals, and the SKILL's upToDate stop-flow does not need the diff. Suggested fix, measured in a scratch copy (diff below): add else if (anchor?.incremental.upToDate) demoting to full-range-unavailable in the same catch. With the patch: the PR suite is 283/283 (unchanged), F4 flips red with the intended mismatch (expected effective:true / received effective:false, reason:'full-range-unavailable') — i.e. the suite is green on both sides and F4 is the fixture that pins the axis; the other five feature cells stay green (zero collateral).

     if (scopedDelta && anchor) {
       anchor.incremental = {
         since: anchor.incremental.since,
         effective: false,
         reason: 'capture-failed',
       };
+    } else if (anchor?.incremental.upToDate) {
+      anchor.incremental = {
+        since: anchor.incremental.since,
+        effective: false,
+        reason: 'full-range-unavailable',
+      };
     }

F-2 (carried, nit) — the !scopedDelta gate on isEmptyDiff remains dead code. Re-measured: M-F2 survives all-green at the new head. Harmless defensive redundancy; the load-bearing sibling gate is pinned (round-1 M2, and this round's "suppresses the full-range flags" cell). Completeness reporting, not a merge condition — I agree with leaving it.

Not covered

  • Per-commit attribution: the shallow checkout makes only 1 of the 3 PR commits reachable (rev-list HEAD^1..HEAD^2 = 1 vs 3 in the metadata snapshot); the aggregate HEAD^1..HEAD diff was verified instead.
  • Live end-to-end fetch-pr against real git fetch + gh (no network/token in this container). The handler was exercised through its producer seams (vitest) and the compiled pure function against real git; the wire to GitHub was not.
  • SKILL.md prose compliance — whether an orchestrating model follows the new bullets is behavioral; SKILL.test.ts (8/8) covers structure.
  • Windows/macOS (Linux node:22-bookworm container).
  • Repo-wide suites beyond the affected surface; targeted gates below are what ran.

Targeted gates (exact counts)

  • packages/cli src/commands/review: 69 files, 2513 passed | 4 skipped | 0 failed (the author's stale-bundle failure does not reproduce on a fresh build — consistent with their note).
  • fetch-pr.test.ts 50/50; agent-prompt.test.ts 233/233; packages/core review SKILL.test.ts 8/8.
  • tsc --noEmit: cli clean, core clean. eslint on the 6 changed files: clean; gate proven live (planted unused-var + any reported as 2 errors, then removed).

Methodology

Environment: node:22-bookworm CI container, refs/pull/9100/merge at depth 2 (HEAD 2724f2998e, base 8e0033d64d, head 25aa69e053); npm ci + npm run build pre-run at HEAD. Harnesses in harness/ (anchor-real-git.mjs, ab-harness.test.ts, ab-compare.mjs, feature-cells.test.ts, mutation-run.mjs); raw logs in logs/. The A/B base arm ran a scratch worktree at HEAD^1 (removed afterwards) with symlinked per-package node_modules (lockfile untouched); the anchor harness imports the compiled dist/ and drives real git child processes with the handler's exact probe shapes; feature cells drive the real handler with producer mocks. Evidence PNGs rendered by scripts/verify-capture.mjs. Assertion tally: 28 anchor + 12 in-arm oracles + 12 cross-arm comparisons + 7 mutants + 6 feature cells + 2 fix-measurement + 7 gates = 74.

Evidence images

01-anchor-real-git-clamp

02-mutation-matrix-round2

03-ab-regression-identical

04-feature-cells-handler

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

Qwen Code · sandboxed verification

Evidence images

01-anchor-real-git-clamp

02-mutation-matrix-round2

03-ab-regression-identical

04-feature-cells-handler

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

Qwen Code · sandboxed verification

@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 25aa69e053df6c6baaf3f73832b7b9e37f572d46 — 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.

⚠️ 机器人在 25aa69e053df6c6baaf3f73832b7b9e37f572d46既没有裁决也没有 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.

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.

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 explored to full depth (tool budget reached): "该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…": could not execute fetch-pr.test.ts / agent-prompt.test.ts under vitest — the worktree and parent checkout have no node_modules , and a full npm install e…; "该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…": none — no check was left unfinished at the ceiling.; "该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…": running the two changed test files (blocked by missing node_modules in worktree and parent).; "该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…": typecheck of the changed files (same missing-dependency environment)..

中文说明

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

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

未探索到全部深度(达到工具调用预算):"该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…"could not execute fetch-pr.test.ts / agent-prompt.test.ts under vitest — the worktree and parent checkout have no node_modules , and a full npm install e…"该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…"none — no check was left unfinished at the ceiling."该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…"running the two changed test files (blocked by missing node_modules in worktree and parent)."该 PR 将增量审查的锚点校验与范围计算移入 CLI:fetch-pr 新增 --since…"typecheck of the changed files (same missing-dependency environment).

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

Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts
Comment thread packages/cli/src/commands/review/fetch-pr.ts
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
Comment thread packages/cli/src/commands/review/fetch-pr.ts Outdated
@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 13, 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: 120 passed · 0 failed · 120 total

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

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

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

Verification report

<!-- qwen-triage:verify -->
<!-- qwen-triage:verify-substantive -->

Sandboxed verification: ✅ passed — merge-ready (agent verdict) - follow-up round 3 at head a3ae0e8554

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

Scripted assertions: 120 passed · 0 failed · 120 total

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

第三轮(follow-up)验证,新 head a3ae0e8554(第 4 个 commit:planless 原因收敛为 full-range-unavailable、delta 轮按 TREE 判空、base-untrusted 拒绝、SHA_RE 统一、demote() 收敛、缩写展开钉点)。120/120 脚本断言通过,0 意外失败。

  • 上轮 findings 状态:F-1(role-7 --base 无钉点)→ fixed 且仍被钉(M-F1r 被杀,1 failed | 285 passed);F-3(partition 失败过声明)→ fixed 且仍被钉(M-F3r 被杀);F-2(!scopedDelta 死门)→ superseded:该合取门已随 round-3 三元式消失,其冗余谱系以 M6(丢掉 tree 分支,286/286 存活)形式并入新 N-2 分类;N-1(upToDate 在 partition 失败后不被降级)→ stands(E1 复测,形态未变),并附在新 head 上实测的最小修复。
  • A/B 结论:不传 --since 时 base(8e0033d64d)与 head 的 6 场景 report/stderr 逐字节一致(35/35,见 03-ab-regression-identical-round3.png);resolveIncrementalAnchor 对真实 git 35/35(base-untrusted、SHA_RE 大小写、缩写展开、优先级,见 01-anchor-real-git-round3.png)。
  • 新 findings(均非阻塞):N-2——commit 4 的 tree 判空触发路径无测试钉点anchorIsValid({collapsed:true}) 脚手架从未被调用;M4/M6 存活),行为本身已验证工作(E2);N-3——SHA_RE 统一是行为变化(大小写敏感),混合大小写锚点由 effective 变为 unknown-commit,方向 fail-safe 且为有意为之,但 M2 存活(无钉点);N-4——base-untrustedbehind-merge-base 的优先级无钉点(M7 存活,两种顺序皆拒绝,危害低)。
  • 未覆盖:逐 commit 归因(shallow;但 4 个 commit 对象本地可达,round-3 delta 单独验证);真实 git fetch+gh 端到端;SKILL.md 编排 prose 的模型遵循度;Windows/macOS。
Verification report

PR #9100 — feat(review): validate and scope the incremental anchor inside fetch-pr (round 3)

Verdict: merge-ready — 120/120 scripted assertions passed, 0 unexpected failures.
Verified head: a3ae0e8554ceac2b412e34754733491ec241d353 (merge 9391f669a3, base tip 8e0033d64d).
Follow-up round: previous-report.md present (round 2 at head 25aa69e053, verdict merge-ready, 74/74). Round-3 delta isolated exactly: all four PR commit objects are locally reachable despite the shallow clone, so git diff 25aa69e053..a3ae0e8554 names commit 4's change set (fetch-pr.ts +119/-54, fetch-pr.test.ts +103, ledger.ts +8, SKILL.md +2/-1).

Previous-round finding status (re-measured at a3ae0e8554)

# finding severity status at new head evidence
F-1 (r1) role-7 --base diffBase wiring unpinned Suggestion fixed, still pinned M-F1r (revert to mergeBaseSha) KILLED — 1 failed | 285 passed, first fail scopes Agent 7's probe base to the delta on an incremental round
F-2 (r1) !scopedDelta gate on isEmptyDiff dead code nit superseded the conjunction gate no longer exists; round 3's ternary made the delta side the tree check. The redundancy lineage survives as M6 (drop the tree branch → 286/286), now classified as coverage gap N-2 rather than dead code, because the branch is reachable (E2) but unpinned
F-3 (r1) partition failure overstates scope on a delta nit fixed, still pinned M-F3r (drop the delta-partition demotion) KILLED — 1 failed | 285 passed, first fail demotes a delta whose partition failed — no incremental claim over a planless report
N-1 (r2) upToDate survives a buildDiffPlan partition failure without demotion nit stands E1 re-measured: residual {effective: true, upToDate: true} over diffPath: null with the "up to date with the head" status line; bounded as in round 2; fix re-measured at the new head (see N-1 entry below)

Declined/deferred rows were re-measured, not diffed: F-1/F-3 pins rest on this round's mutant runs; N-1's residual was re-driven through the real handler at the new head.

Central claim (round-3 delta) and A/B proof

Central claim: every refusal that ends with NO captured diff reports the single planless reason full-range-unavailable (the three shapes that used to publish capture-failed over a zero-chunk plan: delta partition failure; delta throw with the full-range fallback also throwing; delta throw with no merge base — plus the generality beyond them), while the stderr status line still names the underlying refusal; and a delta round judges emptiness by TREE comparison under the same stale-base guard, so a PR that collapses to empty between rounds is flagged emptyDiff instead of fanning agents over hunks GitHub's empty PR diff does not contain. Secondary claims: base-untrusted refuses the anchor when the base fetch failed (clamp cannot rule on a stale base); the anchor-shape predicate is now the ledger's SHA_RE (single predicate); abbreviated anchors expand to the full sha in diffBase.

Anchor ruling against REAL git (compiled dist, no mocks) — witness 01-anchor-real-git-round3.png

Scratch repo with the partial-merge topology (main lands C1 via --no-ff while the PR branch continues to C2; merge-base = C1). Probes wired exactly as the handler does. 35/35:

cell oracle result
anchor older than merge base behind-merge-base, clamp probe shape is-ancestor(base, anchor) PASS
fetchFailed + anchor behind base base-untrusted wins (precedence), clamp never asked PASS
fetchFailed with null sha base-untrusted PASS
null sha, fetch OK clamp skipped → effective (base-free design) PASS
anchor == merge base effective; delta text == full PR range (f3 only) PASS
anchor == head upToDate PASS
unknown 40-hex / tree sha / side branch / base-side merge unknown-commit ×2 / not-an-ancestor ×2 PASS
valid anchor + garbage mergeBase fails CLOSED → behind-merge-base PASS
7-char abbreviation effective; diffBase is the FULL resolved sha, not the input PASS
mixed-case hex unknown-commit with 0 probe calls (SHA_RE is case-sensitive — round-2 behavior change, see N-3) PASS
10 flag-shaped/non-hex inputs refused with 0 probes PASS
200k-char anchor refused < 10 ms, 0 probes PASS
predicate enumeration (old /i vs SHA_RE) divergence is EXACTLY upper/mixed-case hex; direction old-accepts/new-refuses (fail-safe) PASS

A/B regression (no --since), base 8e0033d64d vs head — witness 03-ab-regression-identical-round3.png

Identical vitest harness (same mocks, six scenarios) through the real handler in a scratch worktree at HEAD^1 and in the head tree; normalized report JSON + per-scenario stderr compared. 35/35 (28 in-arm oracles, 6 cross-arm byte comparisons, 1 no-incremental-without---since):

cell scenario comparison
S1 merge-base resolved, non-empty diff IDENTICAL
S2 merge-base unresolvable (warn, diffPath null) IDENTICAL
S3 capture throws (diffPath null) IDENTICAL
S4 genuinely empty full diff → emptyDiff: true IDENTICAL
S5 collapse ratio fires on full range IDENTICAL
S6 baseFetchFailed with non-empty diff (both flags decline) IDENTICAL

Control cleanliness: the base worktree had no nested node_modules (gitignored); root + per-package node_modules were symlinked from the head install (lockfile untouched by the PR). node_modules/@qwen-code/qwen-code-core resolves (via the symlinks) into the HEAD core — named and neutralized: git diff HEAD^1..HEAD -- packages/core is SKILL.md only, so the shared core is a proven-identical input, asserted by diff rather than by realpath. The only normalized difference between arms is the tree-root prefix inside diffPathAbsolute (stripped) and timestamps (stripped).

Handler feature cells (paths the shipped suite does not pin) — witness 04-feature-cells-round3.png

cell oracle result
E1 upToDate + full-range capture OK + partition throws → residual {effective:true, upToDate:true}, diffPath null, status "up to date" (N-1 stands) PASS (documents)
E2 collapsed delta round (head tree == merge-base tree, anchor..head non-empty) → emptyDiff: true, collapsedFromUpstream suppressed PASS
E3 collapsed trees but merge base null → tree ruling declines, emptyDiff undefined PASS
E4 behind-merge-base AND full-range capture throws → full-range-unavailable; stderr names behind-merge-base + "no diff could be captured" PASS
E5 baseFetchFailed end-to-end → base-untrusted, full-range fallback captured, delta never attempted, stderr "reviewing the full diff." PASS
E6 upToDate whose full-range capture throws (round-2 F3 regression) → full-range-unavailable, stderr never "reviewing the full diff" PASS
E7 delta partition failure → full-range-unavailable; stderr names the underlying capture-failed PASS

Mutation matrix (round 3) — witness 02-mutation-matrix-round3.png

Each mutant applied to the head source; fetch-pr.test.ts + agent-prompt.test.ts run (CTRL 286/286); restored byte-exact.

mutant observed classification
M0 positive control (drop the SHA_RE shape gate) KILLED (1 failed — never hands a flag-shaped or non-hex anchor to git) suite-alive proof
M1 drop the base-untrusted block KILLED (1 failed — refuses an anchor when the merge base is too stale to clamp against) round-3 refusal pinned
M2 re-introduce the case-insensitive predicate SURVIVED (286/286) N-3: intentional behavior change, unpinned
M3 drop the final planless catch-all KILLED (2 failed — partition-failure reason + planless-reason tests) Critical fix #1 pinned
M4 tree equality → false (emptyDiff can never fire on a delta) SURVIVED (286/286) N-2: Critical fix #2's fire path unpinned
M5 drop !baseFetchFailed on the tree ruling SURVIVED (286/286) dead code — unreachable (scopedDelta ⟹ resolver ruled ⟹ !fetchFailed); harmless redundancy
M6 F-2 lineage: always the text path SURVIVED (286/286) superseded form of F-2; now the N-2 coverage gap
M7 transpose clamp before the fetchFailed check SURVIVED (286/286) N-4: precedence unpinned; both orders refuse (fail-safe)
M8 status line names the final reason, not the underlying refusal KILLED (1 failed — reports the planless reason whatever refused the anchor first) stderr naming pinned
M-F1r revert role-7 base to mergeBaseSha KILLED (1 failed | 285 passed) F-1 fix still pinned at new head
M-F3r drop the delta-partition demotion KILLED (1 failed | 285 passed) F-3 fix still pinned at new head

No mutant regressed from killed to survived. Every kill failed the INTENDED assertion (failure names quote expected-vs-actual; see logs/kill-counts.log). The M4/M6 survivors are the completeness story of this round: the shipped suite added the collapsed mock option but no test ever calls anchorIsValid({ collapsed: true }) — the scaffolding for the pin exists and is dead.

Findings (non-blocking)

N-1 (carried from round 2, nit) — an upToDate ruling still survives a buildDiffPlan partition failure undemoted. Re-measured by E1 at the new head: the report publishes incremental: {effective: true, upToDate: true} with diffPath: null, and the post-planning status line says "is up to date with the head — nothing new to review" over a zero-chunk plan. Round 3's new catch-all (if (anchor && !anchor.incremental.effective && diffPath === null)) does not reach this shape because upToDate keeps effective: true, and the upToDate demotion runs BEFORE the partition catch nulls diffPath — the validity control still runs before the artifact it invalidates exists. Round 3's own docstring now claims full-range-unavailable "is stamped … whenever the run ends with no captured diff at all", which this shape violates, and SKILL.md's upToDate --comment flow ("the report already holds the full-range diff and plan") is false in it. Bounded as in round 2: diffPath: null plus the loud partition WARNING remain the master signals, and the stop-flow does not need the diff. Suggested fix, measured in a scratch copy at the new head (witness 05-n1-candidate-fix-flips-e1.png): add an else if demotion in the partition catch. With the patch: E1 flips red with the intended mismatch (effective: true → false, + reason: "full-range-unavailable", - upToDate: true), E2–E7 stay green (zero collateral), and the PR suite is 286/286 unchanged — i.e. the suite is green on both sides and E1 is the fixture that pins the axis; the fix should ship with it.

     if (scopedDelta) demote('capture-failed');
+    else if (anchor?.incremental.upToDate) demote('full-range-unavailable');
   }

N-2 (new, suggestion) — the tree-based emptyDiff fire path is unpinned. Commit 4's Critical fix works (E2: a collapsed delta round sets emptyDiff: true; E3: the null-base guard holds), but no shipped test exercises it: anchorIsValid({ collapsed: true }) is dead scaffolding, and M4 (tree equality → false) plus M6 (drop the tree branch) survive 286/286. The unflagged shape is the one the code comment calls expensive — a round that reviews hunks GitHub's empty PR diff does not contain, where one anchored comment 422s the whole Create Review call — so a silent regression here would not be caught by any green run. The fixture already exists in the suite's own mock; a one-test addition pins it. Completeness reporting, not a merge condition: the behavior is verified at head.

N-3 (new, nit) — the SHA_RE unification is a behavior change (case sensitivity), unpinned. The replaced fetch-pr predicate was /^[0-9a-f]{7,64}$/i; the ledger's SHA_RE is not. Mixed/upper-case hex anchors now refuse as unknown-commit with 0 probe calls (R18/R19) where round 2 resolved them effective. The direction is fail-safe (refusal → full-range review), the change is deliberate (commit message and ledger docstring both name the case divergence), and real anchor sources cannot produce upper case (the cache's lastCommitSha comes from rev-parse, the marker's sha is validated by SHA_RE itself). Enumeration shows the divergence is exactly upper/mixed-case hex (R24/R25). M2 (re-introduce /i) survives 286/286 — a mixed-case cell would pin the new contract.

N-4 (new, nit) — the base-untrusted vs behind-merge-base precedence is unpinned. M7 (clamp before the fetchFailed check) survives 286/286: with the default probe both orders refuse, so the observable difference only appears when a fetchFailed base is also not an ancestor of the anchor — both outcomes are refusals failing open to the full range, so severity is low; the order is nonetheless a design claim ("a stale base declines to rule rather than ruling") worth one test.

M5 (completeness, nit) — the !baseFetchFailed guard inside the tree branch is unreachable. scopedDelta true implies the resolver ruled the anchor effective, which implies fetchFailed was false; the guard can never decide an outcome. Harmless defensive redundancy in the same lineage as F-2; the load-bearing sibling guard on collapsedFromUpstream remains pinned (the !scopedDelta conjunction ahead of it is intact at the call site).

Not covered

  • Per-commit attribution: git rev-list --count HEAD^1..HEAD^2 = 1 vs 4 commits in the metadata (shallow). All four commit objects are nonetheless locally reachable, so the round-3 delta (25aa69e053..a3ae0e8554) was verified as its own change set; commits 1–3 remain attributed to rounds 1–2.
  • Live end-to-end fetch-pr against real git fetch + gh (no network/token). The handler was driven through its producer seams (vitest) and the compiled pure function against real git child processes; the wire to GitHub was not.
  • SKILL.md prose compliance — whether an orchestrating model follows the updated bullets is behavioral; SKILL.test.ts (8/8) covers structure.
  • Windows/macOS (Linux node:22-bookworm container).
  • Repo-wide suites beyond the affected surface; targeted gates below are what ran.
  • The M2/M4/M5/M6/M7 survivors are completeness reporting, not merge conditions; none changes an observable behavior at head.

Targeted gates (exact counts)

  • packages/cli src/commands/review: 69 files, 2516 passed | 4 skipped | 0 failed (2520 total).
  • fetch-pr.test.ts 53/53; agent-prompt.test.ts 233/233 (286 combined, CTRL run).
  • packages/core review SKILL.test.ts 8/8.
  • tsc --noEmit: cli clean, core clean. eslint on the six changed TS files: clean; gate proven live (planted unused-var + any reported as 2 errors, then removed; source restored byte-exact).

Methodology

Environment: node:22-bookworm CI container, refs/pull/9100/merge at depth 2 (HEAD 9391f669a3, base 8e0033d64d, head a3ae0e8554); npm ci + npm run build pre-run at HEAD. Harnesses in harness/ (anchor-real-git.mjs imports the compiled dist and drives real git with the handler's exact probe shapes; ab-harness.test.ts + ab-compare.mjs run the identical six-scenario harness in the head tree and a scratch worktree at HEAD^1 and byte-compare normalized dumps; feature cells drove the real handler with producer mocks). Raw logs in logs/ (anchor, mutation matrix, kill counts, A/B dumps and compare, N-1 fix failure detail). The base worktree was removed after the A/B cells were captured; every mutation and the candidate fix were restored byte-exact (git diff empty at report time). Evidence PNGs rendered by scripts/verify-capture.mjs. Assertion tally: 35 anchor + 29 feature-cell + 10 matrix rows + 2 carried re-measurements + 35 A/B + 3 fix-measurement + 6 gates = 120.

Evidence images

01-anchor-real-git-round3

02-mutation-matrix-round3

03-ab-regression-identical-round3

04-feature-cells-round3

05-n1-candidate-fix-flips-e1

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

Qwen Code · sandboxed verification

Evidence images

01-anchor-real-git-round3

02-mutation-matrix-round3

03-ab-regression-identical-round3

04-feature-cells-round3

05-n1-candidate-fix-flips-e1

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

Qwen Code · sandboxed verification

@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 a3ae0e8554ceac2b412e34754733491ec241d353 — 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.

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

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

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

@wenshao

wenshao commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto main (now 4cdbb9f65f) — the PR had gone CONFLICTING after ten commits landed, five of them touching this PR's files.

Every conflict was additive and resolved by keeping both sides, except one that needed a real decision. #9265 added diffSha256 — a digest of the captured diff, used for the resume comparison — and set it inside the capture, next to the diffPath assignments this PR had moved out into a separate publish step. Keeping main's line where it sat would have digested every capture including ones no reader ever sees, so the digest moved to publish() with the paths it describes.

That resolution was wrong on the first attempt and main's own test caught it: I hashed the published text, and #9265 ships hashes the BYTES, not a utf8 decode of them — precisely because a diff of a binary-adjacent or latin1 file contains bytes that are not valid UTF-8, and decoding collapses them onto U+FFFD before hashing. So readRange and publish are byte-valued now and the decode happens only where text is actually wanted. Same failure class this PR has been fighting in the oracle, arriving through a different door.

Also removed the two non-null assertions that refactor introduced, by branching on the bytes rather than asserting them.

Review suite 3142/3143, typecheck clean under commands/review, eslint clean. Two typecheck errors elsewhere (sanitizeFilenameComponent in run-ledger.ts and transcripts.ts) reproduce identically on a pristine origin/main worktree — a stale local core/dist, not this branch. The one test failure remains stale-bundle.test.ts, same story.

Scope stays frozen: this is conflict resolution, not new work.

@qwen-code /triage

中文说明

已 rebase 到 main(新 head 4cdbb9f65f)。此前 PR 变为 CONFLICTING——main 合入了十个 commit,其中五个动到本 PR 的文件。

所有冲突都是增量式的、按「两边都保留」解决,只有一处需要真正的判断。#9265 新增了 diffSha256(抓取到的 diff 的摘要,用于 resume 比对),并把它设置在抓取函数内部,紧挨着本 PR 已经移出到独立发布步骤的 diffPath 赋值。若原样保留 main 的位置,就会对每一次抓取都计算摘要,包括任何读者都不会看到的那些;因此摘要随它所描述的路径一起移入 publish()

这个解决方案第一版是错的,而且是被 main 自己的测试抓出来的:我对发布的文本做了哈希,而 #9265 带来了 hashes the BYTES, not a utf8 decode of them——原因正是:二进制相邻或 latin1 文件的 diff 含有非法 UTF-8 字节,解码会先把它们塌成 U+FFFD 再哈希。于是 readRangepublish 改为按字节处理,解码只发生在确实需要文本的地方。这与本 PR 在 oracle 上一直在对付的是同一类失效,只是从另一扇门进来。

同时去掉了该重构引入的两处非空断言,改为对字节本身做分支判断。

review 套件 3142/3143,commands/review typecheck 干净,eslint 干净。其它位置的两个 typecheck 报错(run-ledger.tstranscripts.ts 中的 sanitizeFilenameComponent)在纯净 origin/main worktree 上完全一致复现——是本机 core/dist 陈旧,与本分支无关。唯一的测试失败仍是 stale-bundle.test.ts,同理。

范围保持冻结:这次是解冲突,不是新工作。

@wenshao

wenshao commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 16, 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: 93 passed · 0 failed · 93 total

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

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

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

Verification report

PR #9100 — feat(review): validate and scope the incremental anchor inside fetch-pr (round 4)

Verdict: merge-ready — 93/93 scripted assertions passed, 0 unexpected failures.
Verified head: 4cdbb9f65f9a76cc36dec9631840cde22bdb07be (merge 0e04948138, base tip c48809341b).
Follow-up round: previous-report.md present (round 3 at head a3ae0e8554, verdict merge-ready, 120/120). The round-3 head object is NOT locally reachable (the PR was rebased; depth-2 graft), so the round-3→round-4 delta cannot be named as a commit set; the aggregate HEAD^1..HEAD diff (16 files, +3817/−55) was verified instead — see Not covered.

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

第四轮(follow-up)验证,新 head 4cdbb9f65f。round 3 之后的增量以 hunk 包含性 oracle(建立在共享 diff parser 上)、探针三路退出分裂(确定性拒绝 vs git 表面故障)、大小写归一化、core.quotePath 钉点、partition 救援为主。93/93 脚本断言通过,0 意外失败。

  • 上轮 findings 状态(全部在新 head 复测,见下表):N-1(upToDate 不降级)→ 作者有意拒绝修复建议并反向钉住(M8 被杀),SKILL.md 已改为让继续流程读 diffPath,本轮认同该取舍;N-2(tree 判空无钉点)→ fixed(机制换成 fullText 判空,M9 被杀,杀它的测试正是为该突变体写的);N-3(大小写敏感无钉点)→ fixed(方向反转:归一化接受而非拒绝,E3 + M7 被杀);N-4(优先级无钉点)→ fixed(E4 实测 3 次探针、clamp 从未被问,M10 被杀);F-1/F-3 仍被钉。
  • A/B 结论:不传 --since 时 base(c48809341b)与 head 的 6 场景 report/stderr 逐字节一致(18/18,见 02-ab-regression-identical.png);唯一有意的捕获形态变化(非 ASCII 路径不再 C 式引号)由真实 git 对比单元 C7/C8 单独实测。
  • 核心主张证明:delta 只有在包含性 oracle 证明其每个 hunk 都在 PR 全量 diff 内时才成为审查范围;oracle 被证伪、无法裁决、缺失(无 base)三种失败全部闭合到全量(hunks-outside-pr-diff/containment-unverified),真实 git 31/31(见 01-anchor-containment-real-git.png);15/15 突变体被杀、0 存活、阳性对照成立(见 03-mutation-matrix-15-of-15-killed.png)。
  • 新 findings:无。
  • 未覆盖:逐 commit 归因(shallow,round-3 head 不可达);真实 git fetch+gh 端到端;SKILL.md 编排 prose 的模型遵循度;Windows/macOS;探针 120s 超时击杀路径的实弹演练(形状由单测钉)。

Previous-round finding status (re-measured at 4cdbb9f65f)

# finding severity status at new head evidence
F-1 (r1) role-7 --base diffBase wiring unpinned Suggestion fixed, still pinned M14 (revert role-7 base to the merge base) KILLED by scopes Agent 7's probe base to the delta on an incremental round; the weld is additionally SHA-shape-checked now (M13 KILLED)
F-2 (r1) !scopedDelta gate dead code nit superseded, lineage closed the tree-branch lineage is gone; its coverage gap (round-3 N-2) is now pinned — see N-2 row
F-3 (r1) partition failure overstates scope on a delta nit fixed (mechanism refactored), pinned the demotion now lives in the partition-rescue block (effective && !upToDatepartition-failed/capture-failed); its presence is pinned by the shipped retries the FULL range when the delta will not tile, and demotes + names the partitioner, not the capture tests (green in the 381/381 CTRL), and M8/M9 pin the demotion's conditions
N-1 (r2) upToDate survives a partition failure undemoted nit declined-with-rationale — agree E1 re-measured (04-e-cells-carried-findings.png): residual {effective: true, upToDate: true} over diffPath: null stands, now INTENTIONAL and pinned in the opposite direction (M8, demoting upToDate, KILLED by keeps upToDate through a partition failure). The round-3 doc inconsistency is fixed: SKILL.md's continuing flows now key on diffPath ("unless diffPath is null … the ordinary degraded state"), and the stop flow consumes no plan. The rationale holds — upToDate is a fact about the anchor proven without the base; the loud partition WARNING remains. See adjudication below.
N-2 (r3) tree-based emptyDiff fire path unpinned Suggestion fixed the tree comparison was replaced by full-range-keyed flags; E2 re-measured (emptied PR on a delta round: emptyDiff: true, scope refused as hunks-outside-pr-diff — strictly safer than round 3). M9 (key emptyDiff on the PUBLISHED diff) KILLED by degrades when the diff FILE cannot be written, a test whose comment names exactly this mutant
N-3 (r3) SHA_RE case sensitivity unpinned nit fixed (direction reversed) the handler now normalises case (rawSince.toLowerCase()) instead of refusing; E3 end-to-end: UPPERCASE anchor effective with lowercased since; M7 (drop normalisation) KILLED by accepts a valid UPPERCASE anchor, probing the lowercased value
N-4 (r3) base-untrusted vs behind-merge-base precedence unpinned nit fixed E4 end-to-end: base-untrusted with exactly 3 probe calls (exists, resolve, ancestry — the clamp is NEVER asked); M10 (transpose the blocks) KILLED with assertion expected 'behind-merge-base' to be 'base-untrusted'
M5 (r3) unreachable !baseFetchFailed guard nit superseded the tree branch is gone; the sibling guards now read fullText inside isEmptyDiff/isCollapsedFromUpstream, reachable and pinned (suite + M9)

N-1 adjudication (declined fix): I agree with the author's direction. The round-3 suggestion demoted upToDate when the full-range partition failed; the author instead kept it and fixed the two real problems the finding named: the docstring/SKILL.md inconsistency (the continuing flows are now told to read diffPath, and SKILL.md explicitly covers the diffPath: null case), and the unrecorded intent (the keep is now the pinned contract, M8). The residual shape costs nothing observable: the stop flow ("No new changes since last review") needs no plan, and the flows that continue read diffPath exactly like every other degraded round — which E1's dump confirms (diffPath: null, diffPathAbsolute: null, loud WARNING, "up to date" status line).

Central claim and proof

Central claim (round-4 delta): a delta is published as the review scope ONLY after the containment oracle proves every hunk of it is contained in the PR's full diff; all three oracle failure modes — disproved containment (hunks-outside-pr-diff), an oracle that could not rule (containment-unverified), and a missing oracle (no base resolved) — fail closed to the full range; and every git probe splits its exit three ways, so a definitive "no" is never reported as a transient surface failure nor vice versa (fail-closed to the full range, never to a narrower one).

Real-git wire oracle (compiled dist, zero mocks) — witness 01-anchor-containment-real-git.png

Scratch repos with the topologies hand-written fixtures cannot fake: an "undo per feedback" revert branch, a chmod revert (mode-only delta section), a binary-net-zero branch, non-ASCII paths, an invalid-UTF-8 context line, a side branch, blob/tree objects. Probes wired exactly as the handler (three-way split over gitProbe). 31/31:

group cells oracles
anchor rulings (A1–A18) 18 effective/upToDate/unknown-commit/not-an-ancestor/behind-merge-base/base-untrusted; blob+tree sha refused with commit-ness BEFORE ancestry (probe-call counted); abbreviation expands to full sha; UPPER/mixed case normalised; 9 flag-shaped inputs → 0 probes; garbage mergeBase fails CLOSED (throws, never effective); 2k/20k/200k-char anchor ladder refused in ≤0.2 ms with 0 probes
containment on real captures (C1–C13) 13 clean delta contained; undo-revert delta REFUSED (two anchor depths); anchor==merge-base identical-capture contained; chmod-revert mode section REFUSED; binary-net-zero REFUSED; non-ASCII path matched unquoted (quotePath pin verified on BOTH sides — C8 proves default git still quotes); U+FFFD context byte → unverified, never ok; not-a-diff → unverified; deletion at the wrong junction REFUSED while the same deletion at the displayed junction is contained

A/B regression (no --since), base c48809341b vs head — witness 02-ab-regression-identical.png

The identical six-scenario producer-seam harness run through the real handler in the head tree and in a scratch worktree at the base tip; normalized report JSON + stderr compared per scenario. 18/18 (report identical · stderr identical · no incremental field, ×6):

cell scenario comparison
S1 merge-base resolved, non-empty diff IDENTICAL
S2 merge-base unresolvable (warn, diffPath null) IDENTICAL
S3 capture throws (diffPath null) IDENTICAL
S4 genuinely empty full diff → emptyDiff: true IDENTICAL
S5 collapse ratio fires on full range IDENTICAL
S6 baseFetchFailed with non-empty diff (both flags decline) IDENTICAL

Fixtures are ASCII-only by design: the one intentional no---since capture-shape change is the core.quotePath=false pin, measured separately — C7 shows the pinned capture spells cn/架构.md raw, C8 shows default git config C-style-quotes the identical bytes. countDiffChangedLines was already position-based at the base tip (verified against HEAD^1), so the A/B isolates exactly the PR's contribution. Control cleanliness: base worktree had no nested node_modules; root + per-package node_modules symlinked from the head install (lockfile untouched). readlink -f tmp/base-tree/node_modules/@qwen-code/qwen-code-core → head's packages/core; neutralized because git diff HEAD^1..HEAD -- packages/core/src excluding skills is EMPTY (the core diff is SKILL.md + SKILL.test.ts only), asserted by diff rather than realpath.

Handler feature cells (re-measurements, producer seams) — witness 04-e-cells-carried-findings.png

cell shape result
E1 N-1: upToDate + full-range partition throws → {effective:true, upToDate:true}, diffPath AND diffPathAbsolute null, "up to date" status line PASS (documents the declined-fix shape)
E2 N-2: emptied PR on a delta round → emptyDiff: true from the full range, scope refused hunks-outside-pr-diff PASS
E3 N-3: UPPERCASE anchor end to end → effective, since lowercased, delta published PASS
E4 N-4: fetchFailed + valid anchor → base-untrusted, exactly 3 probe calls (clamp never asked), full-range fallback published PASS
E5 clean delta round → scoped status line, published bytes == the delta capture, full-range flags suppressed PASS
E6 unknown anchor + full range in hand → stderr "(unknown-commit); reviewing the full diff." PASS
E7 delta capture throws → capture-failed, full fallback published, never an effective claim PASS

Mutation matrix — witness 03-mutation-matrix-15-of-15-killed.png

Each mutant applied to the head source; the pinning suite run (CTRL 381/381: fetch-pr.test.ts 119 + agent-prompt.test.ts 262); source restored byte-exact (git diff empty after the run). 15/15 KILLED, 0 survivors, no mutant regressed. Every kill failed its INTENDED assertion — quoted from the run:

mutant killed by (first failing test)
M0 positive control: drop the SHA_RE shape gate never hands a flag-shaped or non-hex anchor to git (suite-alive proof)
M1 drop the U+FFFD lossy-decode guard declines to rule when either capture decoded lossily
M2 one line of slack on range containment discriminates BOTH boundary directions
M3 deletions matched by content only (no junction) draws the deletion budget from the ENCLOSING hunk, not the whole file
M4 drop the base-free refusal refuses to scope when NO base resolved — nothing to be contained in
M5 drop the oracle-LOST refusal refuses to scope when the containment oracle was LOST, not absent
M6 ancestry asked about the UNRESOLVED sha splits each probe exit three ways — 0, deterministic, and the surface (3 tests red)
M7 drop case normalisation (N-3) accepts a valid UPPERCASE anchor, probing the lowercased value
M8 demote upToDate rounds on partition failure (N-1 declined-fix) keeps upToDate through a partition failure — the stop flow needs no plan
M9 emptyDiff keyed on the PUBLISHED diff (N-2 lineage) degrades when the diff FILE cannot be written, instead of dying — assertion expected true to be undefined; the test's own comment names this mutant shape
M10 transpose clamp before fetchFailed check (N-4) rules base-untrusted BEFORE the clamp — assertion expected 'behind-merge-base' to be 'base-untrusted'
M11 unlimited deletion budget counts deletions, so one displayed line clears only one
M12 drop the hunk-less-section refusal refuses a delta section with nothing comparable against a covering one that has hunks
M13 weld shape check → non-empty string test scopes Agent 7's probe base to the delta on an incremental round (injection sub-assertions)
M14 F-1 lineage: role-7 base back to merge base scopes Agent 7's probe base to the delta on an incremental round

Findings

None new. Every carried finding is either fixed and pinned (F-1, F-2 lineage, F-3, N-2, N-3, N-4), superseded (F-2, M5), or declined with a rationale this round adjudicated sound (N-1). The PR's own description claims were tested as hypotheses and held: refusals fail open to the FULL range in every driven shape, upToDate keeps the full-range plan for continuing flows, and the report names the range it planned.

Not covered

  • Per-commit attribution: the metadata lists 19 commits; git rev-list --count HEAD^1..HEAD^2 returns 1 (depth-2 graft, --is-shallow-repository true — the count is the shallow-boundary artifact, not a real enumeration). The round-3 head a3ae0e8554 is not locally reachable, so the round-3→round-4 delta cannot be carved as a commit set; the aggregate HEAD^1..HEAD diff was verified instead, and the round-3 findings were re-measured rather than diffed.
  • Live end-to-end fetch-pr against real git fetch + gh (no network/token in the sandbox). The handler was driven through its producer seams and the compiled functions against real git child processes; the wire to GitHub was not. The PR's integration test (fetch-pr.integration.test.ts, part of the green suite) covers the oracle-vs-real-capture seam on the in-repo side.
  • SKILL.md prose compliance — whether an orchestrating model follows the rewritten bullets (including the new retry taxonomy for partition-failed rounds keyed on mergeBaseSha/baseFetchFailed) is behavioral; SKILL.test.ts 20/20 covers structure.
  • Live timeout-kill of a probe (the 120 s SIGTERM → status: null path): pinned by unit tests asserting the three-way contract, not exercised with a real 120 s hang.
  • A size ladder over the containment oracle: its inputs are git-produced captures of the repo under review, not outsider text; the operator/marker-supplied ANCHOR input did get the ladder (A17/A18, sub-ms at 200k chars). The oracle parses each capture once (the perf commit's invariant); no adversarial-size capture was timed.
  • Windows/macOS (Linux node:22-bookworm container). Repo-wide suites beyond the affected surface; the targeted gates below are what ran.

Targeted gates (exact counts)

  • packages/cli src/commands/review: 81 files, 3139 passed | 4 skipped | 0 failed (3143 total) — witness 05-review-suite-gate.png. The author's reported stale-bundle.test.ts failure did not reproduce at head.
  • CTRL (matrix baseline): fetch-pr.test.ts + agent-prompt.test.ts 381/381.
  • packages/core review SKILL.test.ts 20/20 (up from 8 — the PR added structural pins).
  • npm run typecheck (all workspaces): clean.
  • eslint on the 8 changed TS files: clean; gate proven live — planted unused-var + any in ledger.ts, both reported (2 errors), file restored byte-exact.

Methodology

Environment: node:22-bookworm CI container, refs/pull/9100/merge at depth 2 (HEAD 0e04948138, base c48809341b, head 4cdbb9f65f); npm ci + npm run build pre-run at HEAD (dist verified to contain the new exports before use). Harnesses in harness/: anchor-containment-real-git.mjs imports the compiled dist and drives real git (isolated HOME, GIT_CONFIG_GLOBAL=/dev/null, GIT_TERMINAL_PROMPT=0) with the handler's exact probe shapes; zz-ab-verify.test.ts + ab-compare.mjs ran the identical six-scenario harness in the head tree and a scratch worktree at HEAD^1 and byte-compared normalized dumps; zz-e-cells.test.ts drove the real handler with producer mocks for the re-measurements; mutate.py applied/restored the 15 mutants. Raw logs in logs/ (mutation-matrix.log, matrix-run2.txt with per-kill attribution, ab-head.json/ab-base.json, e-cells.json). The base worktree was removed after the A/B cells were captured; every mutation restored byte-exact (git diff empty). Evidence PNGs rendered by scripts/verify-capture.mjs. Assertion tally: 31 real-git cells + 18 A/B comparisons + 23 E-cell expects + 15 matrix kills + 6 gates = 93.

Evidence images

01-anchor-containment-real-git

02-ab-regression-identical

03-mutation-matrix-15-of-15-killed

04-e-cells-carried-findings

05-review-suite-gate

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

Qwen Code · sandboxed verification

@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✅

@wenshao
wenshao added this pull request to the merge queue Aug 16, 2026
Merged via the queue into main with commit f2a6e6c Aug 16, 2026
54 of 55 checks passed
@wenshao

wenshao commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator Author

Round 16's blocker is fixed in 4caeed0.

R16-1 — taken as filed. The base-free arm now branches on the discriminator that was already riding the report: {sha: null, baseFetchFailed: true} — the fresh-CI shape where the re-run repeats exactly the component that failed — demotes as base-untrusted, the class the skill already retries; containment-unverified is reserved for the fetch-fine case (unrelated histories), which a re-run reproduces exactly. Both arms stay fail-closed — nothing is scoped without a containment ruling; only the retry class moved. The pinning test flipped to the deterministic fixture and a new sibling pins the retryable one; the reason-enum docblock and SKILL.md's cause list now name both causes.

The round's Suggestions are deferred without exception — they are logged as candidates for the follow-up change, not taken here.

中文说明

第十六轮的阻断项已在 4caeed0 修复。

R16-1 —— 按原样采纳。base-free 分支现在按报告里本就携带的判别字段分流:{sha: null, baseFetchFailed: true}(全新 CI 检出形态,重跑恰好重复失败的那个组件)降级为 base-untrusted,即 skill 已经重试的类别;containment-unverified 保留给 fetch 正常的情形(无共同祖先的历史),重跑会精确复现。两个分支都保持 fail-closed——没有 containment 裁决就不收窄;改变的只是重试类别。钉住测试翻转为确定性夹具,新增兄弟用例钉住可重试一侧;reason 枚举的文档块与 SKILL.md 的成因列表现在把两种成因都写清了。

本轮的 Suggestion 一律延后不采纳——已记为后续改动的候选项,本轮不动。

wenshao added a commit that referenced this pull request Aug 16, 2026
#9100 has landed, so the paragraphs this would have conflicted with are
settled and the deferred half of this PR can go in.

SKILL.md's recovery taxonomy still enumerated `hunks-outside-pr-diff` and
`containment-unverified` — reasons the report can no longer carry, since the
oracle that produced them is gone. It names `nothing-to-narrow` now, and says
what actually produces it: an "undo per feedback" revert, which puts lines
back the way the base had them so the PR's diff no longer shows that region,
and a capture whose bytes do not survive a UTF-8 round trip.

The retry classification moves with it. The old sentence said "the
containment reasons re-rule identically"; the new one says the narrowing
re-narrows identically, and why — the same two captures select the same
hunks, and a capture that failed a round trip fails it again. Both remain
deterministic for the same sha and outside the retryable set.

Pinned in SKILL.test.ts beside its siblings: moving the reason into the
retryable set fails that test rather than shipping green.
@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 4cdbb9f65f9a76cc36dec9631840cde22bdb07be — 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.

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

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

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

wenshao added a commit that referenced this pull request Aug 16, 2026
main landed #9100 (fetch-pr --since), which owns the anchor-validation
flow this branch gates by model. Resolved so the gate rides on top:

- pr-context.ts keeps main's --since wording and re-adds the model
  clause the marker now carries.
- SKILL.md keeps main's fetch-pr --since flow; main's effective:true
  branch had no model check at all, so the same-model pre-condition is
  restored on both incremental-anchor paths.
- SKILL.test.ts re-points its guard at the surviving contract.
wenshao added a commit that referenced this pull request Aug 16, 2026
…-dep-widening

Brings main's #9100 (fetch-pr --since) through the base PR, which owns
the anchor-scoping flow this branch's `rescope` subcommand was written
to provide.

- SKILL.md keeps the --since flow; the rescope bullet it replaced is
  gone, so `rescope` is no longer invoked by the skill (see the PR
  discussion — the two mechanisms are alternatives, not composable).
- fetch-pr.ts: main re-added the local `fileLineCount` this branch had
  moved to lib/git.ts; kept the moved one (a strict superset, with an
  optional repoRoot) and taught main's git.js mock to export it.
- git.integration.test.ts keeps both new describe blocks.
wenshao added a commit that referenced this pull request Aug 16, 2026
…tal/3-blob-verdicts

SKILL.md: the incremental bullet resolves to main's `fetch-pr --since`
flow (landed in #9100 and arriving through the base PRs), replacing the
`rescope` invocation this stack's first PR documented.
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.13.

wenshao added a commit that referenced this pull request Aug 17, 2026
…hind

main's #9100 declared `incremental?: unknown` on agent-prompt's local
PlanReport, and this branch already had one for the rescoped plan; the
merge kept both, which is TS2300 and failed the build for every PR in
the stack. Kept the documented one.

Missed locally because vitest transpiles through esbuild, which drops
types without checking them — a duplicate interface member is invisible
to the test run and only `tsc --build` sees it.
@wenshao

wenshao commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator Author

Independent verification — real environment, real git, real CLI

Verified at head 4cdbb9f65f9a (merged as f2a6e6c7). Posting post-merge as a reference: the PR's own "Not validated / out of scope" note says the runFetchPr handler wiring needs live git+gh, so that is exactly what I built and drove.

Harness — nothing mocked except GitHub metadata:

  • a bare upstream with real refs/pull/N/head refs and a working clone the CLI runs inside (16 fixture PRs, one per decision path);
  • a stub gh answering only auth status and pr view --json … (metadata; it never touches the diff);
  • a logging/fault-injecting git shim first on PATH — every git argv is recorded, so "which probes ran" is evidence rather than inference, and a matching argv can be made to exit with a chosen status;
  • the CLI built from this PR's head (npm ci && npm run build && npm run bundle, driven as node dist/cli.js review fetch-pr …).

31 runs. Every one of the ten documented outcomes reproduces, and the fail direction is always the full range.

three live rounds

The full decision matrix

decision matrix

# anchor / condition ruling plan
S01 no --since (no incremental field) full, 48 lines
S02 ancestor anchor, round 2 edits a base line effective6cf8c7a..head 39 lines
S28 round 2 only appends lines effective 8 lines
S29 200-line PR, 2-line round 2 effective 15 lines
S23 / S14 / S15 7-hex abbreviation / UPPERCASE / repeated --since a --since b effective (expanded, lower-cased, last wins) 39 lines
S04 anchor is the merge base effective, and the already-read full range is reused — one git diff in the trace 48 lines
S03 anchor is the head upToDate, full-range plan kept 48 lines
S05 empty commit past the anchor upToDate (empty delta), full range re-captured 13 lines
S06 "undo per feedback" revert hunks-outside-pr-diff full
S27 / S30 round 2 edits a line round 1 added (ASCII / non-ASCII path) hunks-outside-pr-diff full
S26 the PR's whole diff is empty, its delta is not hunks-outside-pr-diff and emptyDiff: true 0 lines
S07 base moved past the anchor behind-merge-base full
S08 anchor on another branch not-an-ancestor full
S09 / S10 well-formed sha never seen / a blob sha unknown-commit full
S12 / S13 / S11b --since HEAD / $(touch …) / --since=--upload-pack=touch … unknown-commit, zero git probes, no side effect full
S18 an invalid UTF-8 byte in the capture containment-unverified full
S19 base fetch failed but a base resolved base-untrusted full
S20 no merge base at all containment-unverified, diffPath: null planless
S21 delta git diff fault-injected capture-failed full
S22 cat-file -e exits 3 (surface, not a verdict) capture-failed — the retryable class, not unknown-commit full
S16 / S17 --since "" / --no-since ignored with a stderr note, no field full

Claims checked beyond the reason table

  • Fail-open is always to the FULL range. Every refusal on a fixture whose head is PR-1's — S09, S10, S11b, S12, S13, S19, S21, S22 — published a diff whose diffSha256 is e5043d6ecf06, byte-identical to the no---since baseline. Never a narrower scope. (The three effective rounds on the same head all publish 1c40da650558, and S04 — anchor is the merge base — publishes the baseline digest, which is the reuse showing up in the artefact rather than only in the trace.)
  • An at-head anchor costs nothing. The git trace for S03 holds cat-file -e and rev-parse ^{commit} and then stops: no ancestry probe, no delta capture.
  • emptyDiff / collapsedFromUpstream are full-range facts. S26 flags emptyDiff: true while its own delta is non-empty; S29 is a delta round against an advertised 300-line stat whose 4 changed lines would have tripped the 4× collapse ratio had the flag read the published diff — it does not fire.
  • Agent 7's --base follows the round's scope. On the S02 delta round the generated 7.brief.md welds --base 6cf8c7a887… (the anchor); on the same PR without --since it welds --base 402d4c9c76… (the merge base).
  • core.quotePath=false is observable end to end. A fixture PR touching 架构.md publishes diff --git a/架构.md b/架构.md, and the plan names the path unquoted, where default git emits "a/\346\236\266\346\236\204.md".
  • Injection. No /tmp/pwn… file was ever created; for the flag-shaped and symbolic anchors the trace shows the hex allowlist rejecting them before any git process was spawned.
  • Tests. The eight touched CLI suites: 522/522. packages/core SKILL.test.ts: 20/20. Ubuntu CI green on the merged head.

Findings (none blocking; all post-merge follow-ups)

1 — the containment oracle refuses the commonest incremental shape (efficacy, not correctness).

Minimal repro (S27): round 1 adds helper.ts containing helper v1; round 2 changes it to helper v2. The delta carries -helper v1, a line GitHub's PR diff displays on neither side, so the round is refused — even though the delta's + line is perfectly commentable. Any round that revises or removes code an earlier round added lands here, which is the normal iterative-review shape.

Replayed over this repository's own PR branches (anchor = each branch's midpoint commit, merge-carrying branches excluded so the only cause left is the author's own commits):

engagement on real PRs

3 of 13 would have scoped; 9 refuse with hunks-outside-pr-diff. Diagnosing all nine against the same parser the oracle uses, the clause that fires is "a deletion the PR diff never displays" in 8 of the 9 (pr7248new 2 such deletions, pr7268-review 6, pr7195 9, pr7317 9, pr6998 26, pr7237 57, pr7323 64, pr7379 7; two of them also fail the range check). The ninth, pr8206, fails on a file the PR's net diff does not contain at all. Including merge-carrying branches the rate is 3 of 42.

The refusal is safe and the reason is honest — but the agent-time saving this feature exists for will rarely materialise on multi-round PRs. Worth considering for the follow-up: the 422 risk is confined to comments anchored on the left side of unmatched deletions, and the range check already proves every delta hunk's new-side lines are displayed. Scoping the delta while marking its unmatched deletions un-anchorable would keep the guarantee and recover most of the savings.

2 — three claims in the PR body no longer match the merged code (worth fixing wherever this text is carried forward into #8946's item 3):

  • "the delta capture … does not consult the base (a failed base fetch does not cost the incremental path)" — it does, in both shapes: S19 refuses base-untrusted when the fetch failed and a base still resolved, S20 refuses containment-unverified when no base resolved at all. The final round deliberately closed that fail-open path; the body describes an earlier one.
  • "the runFetchPr handler wiring is not unit-tested" — the merged fetch-pr.test.ts carries ~40 handler-level tests (the fetch-pr report assembly block).
  • "without it the command behaves byte-for-byte as before" — true of the --since-absent control flow, but the same PR pins core.quotePath=false, which changes captured bytes (and diffSha256) for any PR touching a non-ASCII path, with no --since involved. No in-repo consumer reads diffSha256, so the practical impact is nil — the sentence just needs the caveat.

3 — a note, not a defect. --since --upload-pack=… (space form) is rejected by yargs as an unknown argument, so the command exits 1 with no report at all, where the = form degrades gracefully. Only reachable if an orchestrator forwards an unquoted flag-shaped anchor, which the ledger's SHA_RE already prevents.

Verdict

The scoping decision, the reason taxonomy, the fail-open direction and the injection surface all behave exactly as documented under real git, including every fault-injected path. LGTM as merged. The one thing I would carry into the next item is finding 1: the guard is correct, but as written it turns off incremental scoping for roughly three out of four realistic anchors in this repository.

中文版本

独立验证 —— 真实环境、真实 git、真实 CLI

在 head 4cdbb9f65f9a(合并为 f2a6e6c7)上验证。作为合并后的参考发布:本 PR 自己的"未验证/超出范围"一节写明 runFetchPr 的接线需要真实的 git+gh,所以我搭建并驱动的正是这一层。

测试台 —— 除 GitHub 元数据外没有任何 mock:

  • 一个裸仓库 upstream,带真实的 refs/pull/N/head,以及 CLI 实际运行其中的工作副本(16 个 fixture PR,每条裁决路径一个);
  • 一个gh,只回答 auth statuspr view --json …(元数据;完全不碰 diff);
  • 一个位于 PATH 最前的记录 + 故障注入 git 外壳——每一次 git 调用的 argv 都被记录,因此"跑了哪些探针"是证据而非推断,并且可以让匹配的调用以指定状态码退出;
  • 由本 PR head 实际构建的 CLI(npm ci && npm run build && npm run bundle,以 node dist/cli.js review fetch-pr … 驱动)。

共 31 次运行。 文档中的十种结果全部复现,且失败方向始终是回退全量。

完整裁决矩阵

# 锚点 / 条件 裁决 plan
S01 不带 --since (无 incremental 字段) 全量 48 行
S02 祖先锚点,第二轮改的是 base 行 effective6cf8c7a..head 39 行
S28 第二轮只追加行 effective 8 行
S29 200 行 PR,第二轮只改 2 行 effective 15 行
S23 / S14 / S15 7 位缩写 / 大写 / 重复 --since a --since b effective(展开、转小写、取最后一个) 39 行
S04 锚点就是 merge base effective,复用已读取的全量范围——trace 中只有一次 git diff 48 行
S03 锚点就是 head upToDate,保留全量 plan 48 行
S05 锚点之后是空提交 upToDate(空 delta),重新捕获全量 13 行
S06 "按反馈撤销"型回退 hunks-outside-pr-diff 全量
S27 / S30 第二轮修改第一轮新增的行(ASCII / 非 ASCII 路径) hunks-outside-pr-diff 全量
S26 PR 整体 diff 为空,但 delta 不为空 hunks-outside-pr-diff emptyDiff: true 0 行
S07 base 越过了锚点 behind-merge-base 全量
S08 锚点在另一分支上 not-an-ancestor 全量
S09 / S10 格式合法但从未见过的 sha / 一个 blob sha unknown-commit 全量
S12 / S13 / S11b --since HEAD / $(touch …) / --since=--upload-pack=touch … unknown-commit零 git 探针,无副作用 全量
S18 捕获中含非法 UTF-8 字节 containment-unverified 全量
S19 base fetch 失败但仍解析出 base base-untrusted 全量
S20 完全没有 merge base containment-unverifieddiffPath: null 无 plan
S21 注入 delta git diff 失败 capture-failed 全量
S22 cat-file -e 退出码 3(表面故障,非裁决) capture-failed——可重试类,而非 unknown-commit 全量
S16 / S17 --since "" / --no-since 忽略并在 stderr 提示,不产生字段 全量

除结果表之外验证的断言

  • 失败方向永远是回退全量。 所有以 PR-1 的 head 为头的 fixture 上的每一次拒绝——S09、S10、S11b、S12、S13、S19、S21、S22——所发布的 diff,其 diffSha256 均为 e5043d6ecf06,与不带 --since 的基线逐字节相同,绝不会更窄。(同一 head 上三次 effective 轮都发布 1c40da650558;而 S04——锚点即 merge base——发布的正是基线摘要,这让"复用"不只出现在 trace 里,也出现在产物中。)
  • 锚点即 head 时零成本。 S03 的 git trace 里只有 cat-file -erev-parse ^{commit} 便终止:没有祖先探针,没有 delta 捕获。
  • emptyDiff / collapsedFromUpstream 是全量范围的事实。 S26 在自身 delta 非空的情况下仍标记 emptyDiff: true;S29 是一次 delta 轮,对照 GitHub 声明的 300 行,其 4 个变更行若按已发布 diff 计算会触发 4× 折叠比——实际未触发。
  • Agent 7 的 --base 跟随本轮范围。 S02 的 delta 轮生成的 7.brief.md 焊入 --base 6cf8c7a887…(锚点);同一 PR 不带 --since 时焊入 --base 402d4c9c76…(merge base)。
  • core.quotePath=false 端到端可观测。 触及 架构.md 的 fixture PR 发布的是 diff --git a/架构.md b/架构.md,plan 中的路径也未转义;而默认 git 会输出 "a/\346\236\266\346\236\204.md"
  • 注入。 全程没有生成任何 /tmp/pwn… 文件;对旗标形状与符号锚点,trace 显示 hex 白名单在任何 git 进程被创建之前就已拒绝。
  • 测试。 涉及的 8 个 CLI 套件:522/522。packages/coreSKILL.test.ts:20/20。合并 head 的 Ubuntu CI 为绿。

结论性发现(均不阻塞,属合并后跟进)

1 —— 包含性裁决拒绝了最常见的增量形态(是效能问题,不是正确性问题)。

最小复现(S27):第一轮新增 helper.ts,内容 helper v1;第二轮改为 helper v2。delta 携带 -helper v1,而这一行在 GitHub 的 PR diff 的两侧都不显示,于是整轮被拒——尽管 delta 的 + 行完全可以承载评论。任何修改或删除更早一轮所新增代码的轮次都会落到这里,而这正是迭代评审的常态形状。

在本仓库自己的 PR 分支上回放(锚点取每个分支的中点提交,排除含 merge 的分支,使唯一剩下的原因就是作者自己的提交):13 个中只有 3 个会成功收窄;9 个hunks-outside-pr-diff 被拒。用与 oracle 相同的 parser 对这 9 个逐一诊断,触发的子句是"PR diff 从不显示的删除行"的有 8 个pr7248new 2 处、pr7268-review 6 处、pr7195 9 处、pr7317 9 处、pr6998 26 处、pr7237 57 处、pr7323 64 处、pr7379 7 处;其中两个同时还未通过范围检查)。第 9 个 pr8206 失败在一个 PR 净 diff 中根本不存在的文件上。若把含 merge 的分支也算入,比例为 42 中 3。

拒绝本身是安全的,理由也是诚实的——但这个特性存在的意义(节省 agent 时间)在多轮 PR 上很少能兑现。可供后续项考虑:422 风险仅限于锚定在未匹配删除行左侧的评论,而范围检查已经证明每个 delta hunk 的新侧行都是显示的。收窄 delta 的同时把未匹配的删除行标记为不可锚定,既保住保证,也能拿回大部分收益。

2 —— PR 描述中有三处已与合并代码不符(若这段文字被带入 #8946 的第 3 项,值得一并修正):

  • "delta 捕获……不依赖 base(base fetch 失败不影响增量路径)" —— 实际会影响,且是两种形态:S19 在 fetch 失败但仍解析出 base 时判 base-untrusted,S20 在完全没有 base 时判 containment-unverified。最终一轮刻意堵上了那条 fail-open 路径;描述停留在更早的版本。
  • "runFetchPr handler 接线未做单测" —— 合并后的 fetch-pr.test.ts 已有约 40 个 handler 级用例(fetch-pr report assembly 块)。
  • "不传时命令行为与之前逐字节一致" —— 就 --since 缺席时的控制流而言成立,但同一个 PR 钉入了 core.quotePath=false,这会改变任何触及非 ASCII 路径的 PR 的捕获字节(以及 diffSha256),与 --since 无关。仓库内没有任何消费者读取 diffSha256,因此实际影响为零——这句话只是需要补一个限定。

3 —— 一条说明,而非缺陷。 --since --upload-pack=…(空格形式)会被 yargs 当作未知参数拒绝,命令以退出码 1 结束且不产出任何报告,而 = 形式则会优雅降级。仅当编排者转发未加引号的旗标形状锚点时才可达,而 ledger 的 SHA_RE 已经堵住了这一点。

结论

在真实 git(含全部故障注入路径)下,收窄决策、原因分类、fail-open 方向与注入面全部与文档一致。LGTM(按已合并状态)。 唯一希望带入下一项的是发现 1:这个防线是正确的,但按当前写法,它在本仓库大约四分之三的真实锚点上直接关闭了增量收窄。

samuelhsin pushed a commit to samuelhsin/qwen-code that referenced this pull request Aug 20, 2026
… a check (QwenLM#9267)

* refactor(review): build the incremental scope from the PR's diff, not a check

The containment oracle proved, after the fact, that a separately captured
`anchor..head` carried no hunk the PR's own `base..head` diff lacked —
because a comment anchored on a line GitHub does not display answers 422 and
takes the whole all-or-nothing Create Review call with it.

That proof was a hand-written match over two rendered unified diffs, and six
review rounds each closed the reported entrances while the next found new
ones: count-less headers, deletion junctions, lossy UTF-8 decodes that
collapse distinct bytes onto U+FFFD, a budget spent across hunks, content
matched without position. Every one was the same shape — something the delta
carried that the PR's diff did not display, arriving through a gap in the
match. The surface is unbounded because it is a match over arbitrary content.

So the scope is no longer checked against the PR's diff; it is built from it.
The delta is read only for the post-image ranges it touched, and the
published text is assembled out of the full capture's own hunks. Every line
the review sees is a line GitHub displays, by construction rather than by
proof. The oracle goes, and with it the two refusal reasons that existed to
report its verdicts: `hunks-outside-pr-diff` and `containment-unverified`.
One reason replaces them, and it names a fact rather than a failed proof —
`nothing-to-narrow`, when the PR's diff has no hunk left in the range that
changed since the anchor. That is the "undo per feedback" round, where the
commits since the anchor put lines back the way the base had them: there is
genuinely nothing there to re-review, and the round keeps the full range,
which is the review it would have done anyway.

The invariant is asserted directly against real-git captures rather than
argued per shape: every line of the narrowed output must appear in the full
capture, checked over the whole output on each scenario, including the
undo-per-feedback history that defeated the oracle six times. A mutant that
assembles from the delta's bytes instead fails three of the four.

Net effect on the tree: -255 lines of production code and the ~765-line
battery that existed to pin it, against +29 and a four-case integration
suite.

* docs(review): retire the oracle's refusal reasons from the skill

QwenLM#9100 has landed, so the paragraphs this would have conflicted with are
settled and the deferred half of this PR can go in.

SKILL.md's recovery taxonomy still enumerated `hunks-outside-pr-diff` and
`containment-unverified` — reasons the report can no longer carry, since the
oracle that produced them is gone. It names `nothing-to-narrow` now, and says
what actually produces it: an "undo per feedback" revert, which puts lines
back the way the base had them so the PR's diff no longer shows that region,
and a capture whose bytes do not survive a UTF-8 round trip.

The retry classification moves with it. The old sentence said "the
containment reasons re-rule identically"; the new one says the narrowing
re-narrows identically, and why — the same two captures select the same
hunks, and a capture that failed a round trip fails it again. Both remain
deterministic for the same sha and outside the retryable set.

Pinned in SKILL.test.ts beside its siblings: moving the reason into the
retryable set fails that test rather than shipping green.

* fix(review): keep narrowed rounds displayed-only across rename, mode, and huge-hunk shapes

- Refuse to narrow when a delta path does not cross into the full
  capture's keys: git's rename detection can resolve differently
  across the two ranges, and the unmatched section is a displayed
  change that would silently drop from the published scope while the
  round still certified head. The round keeps the full range instead.
- Emit a full section whole when the delta touches it without hunks:
  a since-anchor mode change, pure rename, or binary replacement
  lives in the section header, and the old guard dropped the whole
  section while reporting `effective: true`.
- Weld `incremental.diffBase` to the merge base, not the anchor: the
  published hunks are byte-identical hunks of `mergeBase..head`, so
  Agent 7's test-efficacy probe must recompute that range; the anchor
  range can carry undo hunks the PR's diff does not display at all.
- Assemble the narrowed text without spreading selected hunks into a
  single `push`: a hunk past the ~125k-line argument ceiling crashed
  the whole fetch-pr round with a RangeError instead of degrading.
- Validate the full capture with a fatal UTF-8 decode instead of
  re-encoding a full-size copy to compare, removing ~N of peak
  memory on the large long-lived PR workload.

Pinned by real-git integration scenarios for each shape, including
the deletion-acceptance control and an unconditional null fallback;
the producer→consumer weld test now asserts the merge base end to
end. Each new test was verified to fail against the pre-round code.

* fix(review): close the rename-key divergence in incremental narrowing

- Fail closed on a rename the full capture does not key as the SAME
  rename: when round 1 rewrites a file below git's rename threshold
  and round 2 renames it, `base..head` nets the chain to an addition
  plus a deletion while `anchor..head` carries a 100%-similarity
  rename keyed on the new path. The path guard passed — the new path
  is in the full capture, as the addition — while the rename's
  deletion half sat under the old path and dropped from the published
  scope under `effective: true`. `parseDiff` now exposes `rename
  from`, and the narrowing join refuses unless both captures key the
  same rename; the round keeps the full range, which still displays
  the deletion.
- Fatal-decode the delta symmetrically with the full capture:
  `narrowToDelta` takes the delta's raw bytes and decodes them
  itself. A lossily pre-decoded delta folded an invalid path byte
  onto U+FFFD, which could collide with a legitimate U+FFFD path in
  the full capture and publish an unchanged file's hunks.
- Record the executable bit through git itself in the mode scenarios
  (`git update-index --chmod=...` beside the filesystem chmod):
  `chmodSync` is invisible to git on Windows — libuv cannot set the
  exec bit and `core.fileMode` is false — so the two mode tests
  failed on the Windows merge-queue leg. Verified against a
  Windows-git model (`core.fileMode=false`): 2 failed before, 16/16
  after.
- Assert the narrowing outright where the scenarios are constructed
  to narrow: the null guards on the undo-per-feedback and
  post-anchor-file tests let an all-or-nothing refusal ship green
  with zero assertions executed.
- Pin the unpinned emission shapes: a whole-file deletion riding the
  `+0,0` clamp and inclusive `overlaps`, a mode-only full section
  the delta touches with content hunks, and both hunks of a
  two-region file surviving the join — each verified red against
  the corresponding mutant.
- Enumerate all four null shapes under `nothing-to-narrow` in the
  report's union doc, the demotion arm, and the skill's reason
  bullet; the routing (deterministic, never retried) already held
  for all four.

The rewrite-then-rename regression test fails against the pre-round
code (the probe published [new.ts, other.ts] with the deletion
absent); the mode scenarios fail under the Windows model before the
index-native recording.

* fix(review): keep header-level changes in the narrowed incremental scope

A delta section whose hunks all miss the full capture used to be
dropped whole, taking a post-anchor mode flip or rename out of the
published scope while the round still reported effective. Track
header-level delta changes per path and emit such sections whole,
the hunk-less treatment.

Also close the measured battery-power gaps: the rename guard's
pass-through arm, rename-plus-hunks emission, a single delta hunk
overlapping two full hunks, the multi-file section drop, the
capture-failed disk assertion, the diffBase seam's division of
labor, and the skill's reason taxonomy plus retryable set. (QwenLM#9267)

* test(review): close the narrowing battery's mutation holes (QwenLM#9267)

The headerTouched miss-branch tests never asserted the section's
surviving content hunks, the delta-side UTF-8 refusal test stayed
green with its guard removed, and the battery carried no
no-trailing-newline marker pin and no binary delta section. Add the
missing assertions and the two scenarios, and rebuild the delta-side
refusal test around the U+FFFD collision its comment describes, so
each shape now fails under the mutant it is meant to catch — all
four mutants probed against the battery. Also name what the
merge-base clamp actually prevents in the skill's `base-untrusted`
clause, whose "those" lost its antecedent when the containment
reasons were retired.

* fix(review): carry position-divergent hunks through the narrowing join (QwenLM#9267)

Myers aligns a change inside a run of identical lines against
whatever surrounds it, and the two captures' old sides differ — so
the same post-anchor change can sit at disjoint head-side ranges in
`base..head` and `anchor..head`. The range join then dropped a
change the PR's diff displays while the round still reported
`effective: true`, and the ledger certified head over it — the
change never re-entered any later scope. Fail closed per hunk: a
missed delta hunk whose changed lines the full section also changed
emits the section whole — every line of it is displayed, and clean
siblings still narrow. A netted-out undo contributes no line the
full section displays, so the deliberate section drop is untouched.
Covers both probe-confirmed shapes: the whole-section miss and the
partial miss where a matched sibling hunk kept the file visible.

* fix(review): fail closed when a delta hunk lacks a corroborating full hunk (QwenLM#9267)

* fix(review): key changed-line corroboration by new-side junction (QwenLM#9267)

* fix(review): narrow between files, not within them

Four consecutive rounds reported the same class and each fix was defeated by
the next round's entrance: whole-section miss, partial miss, then two shapes
defeating the position-divergence guard's conjuncts, then content-only
corroboration, then junction-keyed corroboration defeated by a delta hunk
carrying two changes. The reviews were right about the cause each time and
right about the pattern: matching hunks across the two captures is a
heuristic over arbitrary content, which is what the containment oracle this
file replaced also was.

The two captures are independent Myers alignments over overlapping content,
so which HUNK a change lands in is not stable between them — a run of
identical lines lets the same edit be attributed to the run's front in one
and its back in the other. Every guard here tried to recognise that
divergence; none could, because it is a property of the alignment and not of
the change.

What IS stable is which FILE a change belongs to, and the path and rename
guards already fail closed on the one way that could differ. So the unit of
narrowing is the file: a section the delta touched is emitted whole, a
section it did not touch is dropped. Nothing the delta performed can fall out
of a section emitted entire, and the whole position-divergence family stops
existing rather than being caught.

That failure direction is the reason this could not stay as it was. A dropped
hunk left the round reporting `effective: true`, and the ledger then
certified head as the next anchor, so the change was never reviewed by any
round. The deleted oracle failed toward more review; this failed toward
silently less, recorded as complete.

Cost, stated plainly: within a touched file the round now reviews all of that
file's PR hunks, not only the ones that moved since the anchor. The saving
incremental review exists for is the untouched files — a round touching 2 of
40 reviews 2 — and that is unaffected.

Also: a base-free round no longer reports `capture-failed`. The fetch
succeeded and `git merge-base` found no common ancestor, so nothing threw;
naming an infrastructure fault put a deterministic state into the class the
recovery flow retries. It reports `nothing-to-narrow`, and the two pins that
asserted the old reason move with it.

* fix(review): split a base-free round by why the base is missing

The R11-1 fix keyed on `mergeBaseSha === null` alone, but that null has two
causes and only one is deterministic. A base that could not be FETCHED — a
fresh CI clone with no local base ref, hitting a transient fault — is
infrastructure: something did fail, and the re-run re-runs exactly the
component that failed. Reporting `nothing-to-narrow` there put a retryable
state into the never-retried class and pointed operators at "nothing to
narrow" instead of a fetch failure.

The arms are split by `baseFetchFailed` now: fetch failed keeps
`capture-failed`, no-common-ancestor keeps `nothing-to-narrow`. This is the
same distinction SKILL.md's recovery paragraph already draws for a planless
`partition-failed`, applied where the code makes the same choice.

The pin that was supposed to cover this asserted `nothing-to-narrow` over a
`{sha: null, baseFetchFailed: true}` fixture while its comment said "the
fetch succeeded" — a fixture contradicting its own comment, which is what
kept the gap invisible. It is one test over both fixtures now, each with the
reason its cause implies.

* fix(review): split merge-base surface failures from deterministic refusals (QwenLM#9267)

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
pull Bot pushed a commit to Stars1233/qwen-code that referenced this pull request Aug 21, 2026
QwenLM#9332)

* fix(review): gate the recovered incremental anchor on the model that 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.

* feat(review): rescope — deterministic incremental plans, widened one import hop

Incremental review existed only as prose: Step 1 said "compute
git diff <lastCommitSha>..HEAD and use it as the review scope" and left
the mechanics to improvisation. The improvisable route — re-run
plan-diff over a hand-captured interdiff — silently degrades the plan
(no worktreePath, no PR identity, no heaviness), dropping Agent 0, the
modeled-system lens and every invariant agent from the roster.

`qwen review rescope --plan <plan> --anchor <sha>` moves the scope
decision into code: it re-validates the anchor against the history,
captures the interdiff with the pinned flags, widens it by one import
hop — every still-clean source file that imports a changed file
re-enters the scope with its full-range hunks — and rewrites the plan
in place with the same builders fetch-pr used, identity fields riding
through and post-image line counts intact. The plan gains an
`incremental` block; chunk briefs annotate each file's class (changed
= review in full, interaction = review the seam only), and whole-diff
briefs carry the frame once. Failure is directional: any refusal
leaves the plan untouched, so the fallback is the full-range review,
never a skip; an empty interdiff exits 3 and maps to the same-SHA
outcomes.

The widening exists because "clean" was certified against the code as
it stood: a fix that moves a contract can break an unchanged caller,
and an interdiff-only scope never re-opens it. Dependents only, source
only, one hop; the scan is a documented heuristic whose misses keep
exactly the pre-widening floor.

* fix(review): harden rescope and the widening against review findings

Findings from the PR's own review rounds, each verified before fixing:

- Scoped files now carry FULL-RANGE hunks; the interdiff only chooses
  which files are in scope. Since-anchor hunks broke inline-comment
  anchoring: a fix round that restores lines the previous round changed
  produces hunks that exist nowhere in the PR's own diff, and one such
  anchor 422s the whole posted review, all-or-nothing.
- EXT_MAP maps .js to BOTH .ts and .tsx — under react-jsx a .tsx file
  emits .js, and 921 of 6,200 relative .js specifiers in this repo named
  .tsx targets no edge could reach. Root-escape guard is segment-exact
  (a '..config' directory is not an escape), and the documented dist/
  deep-import remap now actually strips the dist/ segment.
- rescope refuses an already-rescoped plan (a second pass derived
  candidates from the shrunk file list and repointed fullDiffPath at the
  file it was about to overwrite) and a plan with missing or malformed
  files[] (normalising to [] silently dropped every widening candidate).
  All git calls are pinned with -C to the plan's worktree: pathspecs
  resolve against git's cwd, and from a subdirectory an unmatched
  pathspec exits 0 with empty output instead of failing.
- incrementalScopeOf honours its degrade contract: interaction entries
  whose edges failed validation are dropped, and a block with no
  surviving scope renders no incremental frame at all.
- Whole-diff briefs name each file with its scope class (capped list);
  chunk briefs state that scope classes override the generic duties for
  interaction files; heavy INTERACTION files get no invariant agents —
  their full-range slice is exactly the code the previous round cleared.
- incremental.contextFiles (23 KB measured on a 300-file plan, with no
  reader) is now a count; fullDiffPath is named in the skill prose.
  SKILL.md states rescope runs from the main checkout, not the worktree.
- Test batch from the mutation findings: exit-code literals pinned,
  --out exercised, diffPathAbsolute asserted, one-hop limit gated,
  same-sha refusal byte-compared, heaviness preservation asserted,
  test-file dependents excluded, cross-package widening exercised,
  fileLineCount covered at the git layer.

* fix(review): round-2 findings — slice the fetched diff, cap and reconcile the frames

Round-2 review findings, each reproduced before fixing:

- The composite is now a BYTE-SLICE of the fetched full-range diff, not
  a pathspec-scoped re-capture: a scoped re-capture cannot see a rename
  source, un-pairs the rename, and renders a whole-file add whose hunks
  exist nowhere in the PR's own diff — the second entrance of the same
  422 anchor class the round-1 redesign closed. Slicing also keeps the
  subset invariant byte-exact. sliceDiffByLines moves to lib/diff-plan.
- deltaFiles is reconciled with the sections the composite actually
  holds (a file restored to its merge-base state names no phantom
  scope; its importers still widen), a files[] whose entries carry no
  usable path refuses like an empty one (zero-compared must never read
  as nothing-changed), and an unwritable --out exits 2 instead of
  throwing.
- The whole-diff frame carries the same scope-class-WINS reconciliation
  as chunk briefs (agents 1a/1b sweep duties re-opened round-1 findings
  over interaction hunks), scope lists cap edges per entry (8) as well
  as entries (30), anchors render inertly, empty-string edges degrade,
  a chunk with no classed files gets no frame, and the frame wording is
  flow-neutral (review's base, not PR base).
- Roster: interaction paths subtract deltaFiles (a path in both lists is
  live delta — widening wins), the field is declared on RosterPlan, and
  heavyFiles' doc is re-attached.
- import-graph: dist deep-imports resolve under BOTH emit layouts
  (dist/src/… and flat dist/…), and the header now states the honest
  wrong-edge cost of unparsed exports maps (one extra widened file,
  never a narrowed scope).
- Tests: rename-preserving slice, restored-file reconciliation, empty
  and zero-usable files[], out-of-worktree cwd run, unwritable --out,
  exact contextFileCount, head-distinct heaviness oracle, .cjs
  resolution, both dist layouts, list/edge caps, both-lists roster
  widening, no-frame-for-unclassed-chunks.

* fix(review): round-3 findings — follow the lineage, absolute full-diff path

Round-3 review findings on the rescope layer:

- R3-1 (Critical): a file renamed BEFORE the anchor and deleted in the
  fix round carries two names — the post-image name in the interdiff,
  the left-side name on the PR diff's deletion section — so the section
  holding its unreviewed hunks matched no scoped name and silently
  vanished (or exited 3 as 'nothing new'). An unmatched delta file is
  now dropped only when a cheap per-file probe proves it a genuine
  RESTORATION (identical blobs on both sides of the PR range); any
  other lineage break refuses to the full range, and the check runs
  before the empty-sections exit so the refusal wins.
- incremental.fullDiffPath is absolute: a cwd-relative path is
  meaningless to the later step the field exists for (R3-9), and the
  exit-3 contract in the header now names both of its causes (R3-8).
- The roster's interaction-path reader applies the same validation the
  brief renderer does — anchor present, every entry carrying a
  surviving edge — and a malformed deltaFiles disables the narrowing
  entirely rather than just its delta-wins subtraction: with no
  trustworthy delta list there is no way to tell a seam-only file from
  a live one, and every malformation here must widen (R3-2, R3-10).
- Tests: rename-then-delete refusal, restored-only exit 3, unwritable
  --out leaves the plan byte-identical, sliceDiffByLines gets a direct
  suite (parse → slice → parse round-trip, byte-exactness over invalid
  UTF-8 and lone CR, range ordering and clamping), and the resolver's
  literal-form candidate is pinned.

* fix(review): certify the ledger anchor with the runtime model identity

* fix(review): pin the posted marker's model wiring and tighten the anchor-gate spec

* fix(review): round-4 findings — chunk-scoped role briefs, resolver gaps

Round-4 review findings:

- R4-1 (Critical): a chunk-scoped ROLE brief (the reverse auditors, the
  one role accepting a chunk) received per-file scope classes only from
  the globally capped list, so on a wide round its own files could be
  elided past entry 30 — the sole reviewer of that territory left
  without their class and with no way to recover the tail. Its own
  chunk's files are now listed in full, and the chunk brief's seam
  bullet drops the display cap for the same reason (R4-2); the cap stays
  where it belongs, on the whole-diff frame.
- The resolver gains the `.jsx` emit row (a JSX source emits `.js` under
  the same convention as `.tsx`, R4-4) and normalises bare-package
  subpaths through the same POSIX rules relative specifiers already get,
  refusing escapes (R4-5).
- A plan file that parses to JSON `null` now refuses instead of throwing
  a TypeError past the catch (R4-7), `fileLineCount` is `-C`-pinned like
  every other git call in the module (R4-9), and a `deltaFiles` array of
  non-string junk disables the roster narrowing exactly as a missing
  list does (R4-11).
- Tests: chunk-scoped role brief listing, `.jsx` and subpath
  normalisation, junk-deltaFiles widening, JSON-null plan refusal.

R4-8 declined with rationale, recorded in the code: a file absent at
BOTH ends of the PR range is either a net-zero add-then-delete (safe to
drop) or a rename-before-anchor whose deletion hunks sit under its
pre-rename name (dropping loses them). This layer cannot tell them
apart, and dropping re-opens the round-3 Critical, so the refusal
stands.

* fix(review): shed the anchor pair first and pin the round-3 findings

The marker's byte-cap loop dropped a finding before the anchor pair;
`dropped` then withheld the pair in the same render, so a capped clean
round lost a ruling it was owed. Shed the pair first — the work list
survives and recovery degrades to the full diff. Plus the round's pins:
attribution-off withholding of the runtime-injected model, the submit
fixture's production filename encoding, the skill's same-model gate
clauses, and the differing-SHA gate in the user docs.

* fix(review): scope the identity-channel claims and pin the branch-1 gate

The boundary comments and DESIGN.md claimed the runtime identity channel
delivers what the mechanism cannot: a model-authored command prefixes its
env, and the override reaches the child (measured in this repo's bash -c
spawn shape), so "the model the session ACTUALLY runs, not the id the
state JSON typed" overstated the guarantee. Scope every PR-owned claim to
what the wiring delivers — the runtime id supersedes the typed one, and
the channel stays forgeable, same posture as the cache path. Plus the
revert-guard's missing pin: branch 1's `If SHAs differ **and** model
matches` clause was unpinned, so a partial revert dropping only it left
every suite green (measured); the pin makes that revert fail and does not
misfire on the PR state.

* fix(review): shed the dead anchor tie-break and pin the reprieve clauses

* fix(review): round-5/6 Criticals — readers for restored files, honest exits

Per the posture announced last round, this lands Criticals only.

- R6-10: a delta file the fix round RESTORED to its merge-base state fell
  between both reader classes — no PR-diff section, so no full review, and
  inside `delta`, so the widening skipped it as a candidate. Its imports of
  files that are still changing therefore had zero readers. The restoration
  probe now runs BEFORE the widening and splits the set: every changed file
  (restored included) still pulls its importers in, because a revert moves
  their seam too — round 1 cleared them against the pre-revert callee, and
  (importer@head x callee@base) is a pairing no round has seen — while the
  restored files themselves become candidates in a second pass keyed on the
  LIVE delta, since a restored file importing another restored file has no
  moving side to check.
- R5-14: nothing past the plan write may throw. "Only exit 0 rewrites the
  plan" needs its contrapositive to hold, and a dead stdout (`qwen … | head`,
  a daemon redirect) made the courtesy reporting raise EPIPE — exit 1 over an
  already-rewritten plan, sending the caller down the "full-range plan
  untouched" branch against an incremental one.
- R6-16: `fetchedSha`/`mergeBaseSha` were taken on type-check faith. Both
  ends of the PR range must be object ids: a clobbered plan naming a moving
  ref would resolve at call time, so the interdiff describes one tree and the
  worktree reads another while the exit-0 plan claims incremental scope.

Each of the three tests was mutation-checked: reverting the fix it pins
turns it red.

* fix(review): round-6/7 Criticals — whole tree entries, and an async-proof exit

Criticals only.

- `restored()` compared blob oids (`rev-parse <ref>:<path>` yields nothing
  else), so a fix round that reverts the content and KEEPS `chmod +x` — or
  swaps a file for a symlink with the same text — was misclassified as
  restored and dropped from scope. Its mode-only section is in the PR's own
  diff (parseDiff emits one, planChunks gives it a chunk), so the incremental
  path narrowed BELOW the full-range floor it is documented to hold and
  exited 3 "nothing new" over a change nobody reviewed. The probe now
  compares the whole tree entry, mode included, via a pathspec-pinned
  `ls-tree`.
- The round-5 EPIPE guard caught only the synchronous throw. A dead stdout
  also surfaces as an ASYNC 'error' event on the stream, which no try/catch
  around the write can intercept and which terminates the process with exit 1
  — over an already-rewritten plan, sending the orchestrator down the
  "full-range plan untouched" branch against an incremental one. A persistent
  no-op 'error' listener makes that shape inert; the test now pins both.

Both tests were mutation-checked: restoring the blob-only probe, or removing
the listeners, turns them red.

* fix(review): stamp the round's model at capture, qualify it by provider

Two ways the same-model gate could certify a range under a model that
did not review it.

1. Deferred post. compose/submit read QWEN_CODE_MODEL at POST time,
   which tracks the session's CURRENT model — review under A, /model to
   B, "post comments" and the marker said B. The next round under B
   then scoped sha..HEAD past code B never saw. fetch-pr now stamps
   reviewModelId into its report when the diff is captured, and compose
   withholds the sha/model pair outright when that stamp disagrees with
   the runtime posting it: the round cannot name who reviewed the range,
   so it certifies nobody and the next round reviews in full. The
   findings still post.

2. One model id, two providers. A bare id is unique only inside one
   provider configuration; two of them exposing 'qwen3-coder-plus' would
   pass each other's gate. Config now publishes
   QWEN_CODE_MODEL_IDENTITY — <model>@<8-hex of authType+baseUrl> —
   beside the bare id, and the review flow prefers it. A runtime that
   publishes neither yields '', which reads as a mismatch, not as
   agreement.

The identity slot is process-global while the model is per-session, so
shellContextEnv hands it down only while it still describes the model
resolved for THIS session; a daemon side-session gets the bare id rather
than another session's qualification, since a confidently wrong identity
passes a gate the coarse one would have failed.

Every new test mutation-checked.

* docs(review): correct the absent-stamp and model-cap notes

The reviewModelId doc claimed compose reads an absent stamp as
"unknown"; it reads it as today's behaviour, and the reason is worth
stating — the report is written at the start of a round and read at its
end, so a missing stamp means an upgrade landed between the two, and a
runtime that publishes no model id empties the other side of the
comparison anyway.

The ledger cap's note predates the provider qualifier, which adds nine
characters to every id it bounds.

* style(review): prettier the reapplied round-model helper

* fix(review): drop the duplicate `incremental` field the merge left behind

main's QwenLM#9100 declared `incremental?: unknown` on agent-prompt's local
PlanReport, and this branch already had one for the rescoped plan; the
merge kept both, which is TS2300 and failed the build for every PR in
the stack. Kept the documented one.

Missed locally because vitest transpiles through esbuild, which drops
types without checking them — a duplicate interface member is invisible
to the test run and only `tsc --build` sees it.

* fix(review): rule the same-model gate in the CLI, key the identity per session

Four blockers from round 9, all in the identity plumbing this PR adds.

R9-1: the recovery path's gate could never fire. The marker's `model` is
the provider-qualified identity (`<model>@<digest>`), but SKILL.md told
the orchestrator to compare it against `{{model}}`, which
BundledSkillLoader substitutes with the BARE `config.getModel()` — two
identity spaces that are never equal, so every same-model continuation
round silently re-reviewed the full diff, which is the whole payoff this
PR exists for. Read loosely instead, a prefix match would have accepted
another provider's same-named model and re-opened the scope-skip the
digest closes.

The comparison now happens in the process holding both values:
`pr-context` renders the verdict — "the same-model contract HOLDS" or
"**Do NOT pass the reviewed-at sha as `--since`**", naming both
identities either way — and the skill obeys that sentence instead of
comparing strings. A section with no verdict is a mismatch. The cache
path keeps its bare-`{{model}}` gate: Step 8 writes `lastModelId` from
the same bare value, so that path is self-consistent.

R9-2: in daemon mode the identity leaked across sessions. The slot is
process-global and first-writer-wins, and withholding by OMITTING the
key is not withholding at all — every spawn site composes the child env
as `{...process.env, ...getShellContextEnvVars()}`, so the stale global
rode the spread and session B stamped its marker under A's identity.
Now registered per session beside the model (dropped together on
unregister) and written as `''` on a miss, the precedent the agent and
prompt ids in that file already set. The global slot stays the
single-session CLI's fallback, guarded so one that describes another
model is dropped rather than mis-qualifying this one.

R9-3 (×2): the two wiring tests never cleared QWEN_CODE_MODEL_IDENTITY,
which the boundary under test prefers — so an ambient value, which this
PR's own Config now publishes into every subprocess, overrode the model
they set. Running the suites inside a Qwen Code session is the
dogfooding path, so that was the normal case, not the exotic one.

Also folds the four inline `?? ` chains into lib/round-model.ts:
`roundModelIdFrom` and `certifierMatchesRound`, the latter pinning
whole-string equality and every unknown — absent certifier, unpublished
runtime, two blanks — as a mismatch.

Every new test mutation-checked.

* feat(review): fold the one-hop widening into `fetch-pr --since`, drop `rescope`

main's QwenLM#9100 landed anchor validation and scoping inside `fetch-pr`,
which is where this work belongs — so the `rescope` subcommand it was
built as is gone (612 lines of command, 728 of test), and what was
unique to it now runs on the `--since` path.

Two changes to what an incremental round reviews.

The scoped diff is a SLICE of the PR's own diff, not a re-capture of
`since..head`. The delta decides WHICH files are in scope; their hunks
come from the full range. Every hunk an agent can anchor a comment on is
therefore byte-identical to one GitHub renders, and an inline-comment
422 takes the whole Create Review call with it. It also dissolves a
refusal: an "undo per feedback" commit reverts lines back to base
content, so a re-captured delta carries hunks the PR's diff does not
contain — `hunks-outside-pr-diff`, which cost the round its whole scope.
Sliced, that file is simply reviewed at the shape GitHub shows.

And the file set is widened by one import hop. A still-clean source file
that imports a changed one re-enters: round 1 cleared it against the
callee's OLD shape, and (importer@head × callee@head) is a pairing no
round has seen. This is only expressible under slicing — an importer is
unchanged by definition, so no delta capture can show it.

`incremental.scope` names each file's class (deltaFiles, interaction
with the edges that pulled each one in, contextFileCount,
restoredFileCount) and the superseded full range stays at
`incremental.fullDiffPath`. A file restored to its merge-base state owes
no review — mode-aware, so a content revert that keeps `chmod +x` is not
a restoration — but still pulls its importers in.

New refusal `lineage-unfollowable`: a delta file with no section of the
PR's own diff under that name (a rename before the anchor) cannot be
sliced, and refusing costs a full review where guessing loses hunks.
An unparseable delta is `containment-unverified`, never `upToDate` — the
empty file list is the parser's, not the tree's, and reading it as
'nothing changed' would stop the round over a failed capture.

The scope logic is a pure module with injected readers, so it is unit
-testable without a repository. Four new fetch-pr cases cover slicing,
widening, restoration and the nothing-new stop; every one
mutation-checked, and each of the four mutants (no slice, no widening,
no restoration probe, widen on the live delta) turns the suite red.

* fix(review): make the blanked identity fall back, and drop the anchor pair whole

Round 10 filed no Criticals; these are the deferred items that were
defects rather than coverage gaps.

The R9-2 blanking silently disabled the bare-id fallback. `??` falls back
on ABSENT, not on empty — and the identity slot is deliberately written
as '' when a session has none to publish, because an omitted key is not
withheld (the spawn-site env spread leaks the parent's stale one). So a
blanked slot meant 'this round has no identity at all' rather than 'no
qualification, use the bare id': the round certified nobody and every
round after it re-reviewed the full diff. Both comments claimed the
opposite. Blanking must cost the qualification, never the identity.

`stripAnchor` dropped a foreign ledger's `sha` and left its `model`
behind — an identity certifying a range that is gone, which every reader
would have to know to ignore. They are written together, withheld
together by compose-review, and serialized only as a pair; they are
dropped as one now.

SKILL.md's recovery path is reached from a cache-path WITHHOLD too, not
only from an absent or refused anchor: a cache holding another model's
anchor stops the round at the cache, and the marker it never looks at
may hold one this model certified.

Five new tests, each mutation-checked: the blank-slot fallback, the
pair-drop, buildMarkdown's identity wiring, the per-session identity
registry (write and mid-session re-key), and `certifierMatchesRound`'s
engage case — every other case there is a refusal, so `return false`
survived them all.

* fix(review): repair the build, the retry class, and two import-graph edges

R1-1 broke `npm run build --workspace=packages/cli` outright:
`mergeBaseSha` is `string | null` and reached `treeEntryUnchanged`
un-narrowed (TS2345), because the guard above tested only `fullBytes` /
`fullText` and the compiler cannot see that a non-null capture implies a
base. Naming the null base in the rejecting conjunct narrows it — and it
is the same conjunct R1-2 needs, so the two fixes are one edit.

I missed this locally twice, and the reason is worth recording: in a
fresh worktree `tsc` bails with TS6305 before checking anything, so the
`grep commands/review` I judged by came back empty and read as clean.
Building core in the worktree first reproduces it immediately.

R1-2: a base-fetch failure was demoted `containment-unverified`, which
this skill's own taxonomy files under "deterministic for the same sha
and must NOT be retried" — so a CI checkout with a flappy base fetch
would pay a full review every round from then on, under a reason that
also misnames the cause (the delta read fine). The three causes are now
split by what a re-run would repeat: `base-untrusted` for a failed
fetch, `capture-failed` for a base that existed and would not read,
`containment-unverified` only for a successful merge-base that found no
common ancestor. SKILL.md's reason list says so too, and the test that
conflated the first and third is split in two.

R1-4: `candidatesFor` tried every extension remap BEFORE the literal
specifier, and `resolveSpecifier` takes the first membership hit — so in
a mixed JS/TS directory where both siblings changed, `./util.js`
resolved to `util.ts`. That is not one extra widened file, the cost this
module budgets for a wrong edge; it DISPLACES the true one, so the seam
brief names a pairing that does not exist while caller × util.js is
named nowhere and retires unreviewed under a `scope.interaction` entry
claiming the caller was covered. Every existing test used a
single-element membership, so none could tell precedence apart.

R1-3: the package-subpath escape check was `startsWith('..')` — the
exact misclassification `repoJoin`'s comment eight lines above names and
avoids segment-exactly. `@q/core/..config/mod.js` is a legal directory,
and reading it as an escape drops the edge silently.

Four new tests, each mutation-checked.

* fix(review): rule the anchor verdict on the sha the side file actually 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.

* fix(review): move the last identity comparison out of prompt text

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.

* fix(review): keep the merge-base probe's exit status, not just its answer

R2-1: `mergeBaseSha === null` conflated the definitive "these histories
share no ancestor" (git exit 1) with a probe that could not ANSWER — exit
128, or a kill, which is the 120s timeout a large long-lived PR under CI
load reaches. The probe was wired through `gitOpt`, which discards the
status, and `lib/git.ts`'s own `gitProbe` doc condemns exactly that
collapse.

The consequence is the retry class again: the round reported
`containment-unverified`, which the taxonomy files under
"deterministic for the same sha and must NOT be retried", so a transient
merge-base failure cost the PR its incremental scope permanently and
named a cause that had not happened.

`GitProbe.mergeBase` now returns `{sha, status}`, `resolveMergeBase`
reports `probeUnavailable`, and the reason keys on it. The flag is
STICKY across candidates: the tracking ref can fail to probe while the
local fallback answers a definitive no-ancestor, and a round that heard
one unanswerable probe has not established determinism.

`probeUnavailable` is required rather than optional on the result type,
so a future producer cannot omit it and have the absence read as
benign — the shape of the last three findings in this class.

Three new tests, all mutation-checked: dropping the status split, and
dropping it from the reason, each turn the suite red.

* refactor(review): retire what slicing made dead, and pin what the caps cut

Suggestions from round 1, all mutation-verified by the reviewer and
re-verified here. Two are defects the slicing change introduced.

R1-8: `diffBase` still carried the ANCHOR while the published bytes had
become sections of `merge-base..head`. Agent 7 welds it into `--base`
and recomputes its own diff, so the probe would run over hunks the round
never reviewed and miss the ones it did — the exact error the field was
added to prevent, arrived at from the other side. The producer stops
writing it on a sliced round; the consumer's fallback to `mergeBaseSha`
is the correct answer there, and it still honours the field on a plan an
older CLI wrote, where a delta-range publish made it true. The
seam-crossing test now asserts the published range instead of the
anchor.

R1-7: `fullDiffPath` was cwd-relative while every agent reads through
`read_file`, which rejects relative paths, from inside `worktreePath`
where `.qwen/tmp/…` resolves to nothing. Absolute now, and the docstring
says NOTHING READS IT rather than naming consumers — the same
over-claim QwenLM#9191's R10-1 caught in the sibling field.

R1-5: `containmentRuling` and its ~200 lines of helpers had no
production caller left — containment is structural once the published
diff is a slice of the PR's own — while a comment still claimed it
"runs on every incremental capture" and `hunks-outside-pr-diff` sat in
the reason union and the SKILL enumeration with no emitter. All gone,
including the integration file that existed only to exercise it.

R1-6: `fileLineCount`'s `repoRoot?` was a dead switch no caller set,
documented for `rescope`, which no longer exists.

R1-10: the capped-lists doc block sat above `chunkScopeBullets`, the
function that is explicitly UNCAPPED, so hover read the cap rationale as
documentation of its own contradiction. Moved to `scopeFileLists`.

R1-11 through R1-15 are test gaps, each named with the mutant that
survived. The caps are now pinned by what they CUT (the `(+N more)`
arithmetic is independent of the `.slice()`, so both markers stayed
correct with the truncation deleted); the malformed-block fixtures reach
the field validators, and one carries a bad anchor with VALID lists —
the only shape the anchor guard alone can reject; the restoration probe
is steered per REF, which pins both "entries differ ⇒ not restored" and
the mode half (a `chmod +x` with unchanged bytes is not a restoration);
the plan⇔slice pairing is asserted where the slice is genuinely smaller;
and the uncapped chunk-scoped path has a fixture that reaches the cap.

Every one of those mutants was re-run here and turns the suite red.

* fix(review): reconcile the incremental docs with slicing, pin the killed probe

* fix(review): keep the scope ruling honest — probe status, rename lineage, two-flag re-run

The restoration probe kept its exit status (an unanswerable ls-tree is
retryable infrastructure, not a deterministic lineage refusal), a restored
rename target carries its deleted source into the lineage check, a lossy
capture fails the scope ruling closed, the side-file re-run passes both
--since flags, a resolved base sheds the probe taint, and the brief
renderer agrees with the roster on what a corrupt delta list means.

* fix(review): brief the seams that have no other surface first

R4-1: an interaction file that carries a section of the PR's diff is
named twice — in `scope.interaction` and, uncapped, in the chunk brief
of whichever chunk holds that section. One that carries NONE is named
once. Those are the restored files the second pass pulls in: their own
content is base content, so no chunk holds them, and the capped
whole-diff list is the only place their seam is briefed at all.

Insertion order appended them LAST, so on any round past
`SCOPE_LIST_CAP` they were the first elided into `(+N more)` — the seam
went unbriefed while `scope.interaction` still recorded it as covered.
Coverage claimed and not delivered, which is the failure direction this
module's header says it does not have.

The cap now bites the redundantly-named entries first. It still bites:
a round with more sectionless entries than the cap elides some, and that
is the honest degradation rather than the silent one.

The module is pure but for two injected readers — the property its
docstring claims to make the whole decision testable without a
repository — and nothing exercised it directly until now; every existing
case reached it through `fetch-pr`. This adds that file, with the
ordering as its first property. Mutation-checked: restoring insertion
order turns it red.

* fix(review): measure the decode, and ask the FULL range about a rename

R5-2: the lossy-decode guard scanned the decoded TEXT for U+FFFD, which
cannot tell a substitution from the code point itself. The code point is
ordinary content — this repository carries four literal ones in source —
so a delta touching any of them, even as context, demoted the round to
`containment-unverified`. That reason sits in the recovery contract's
"deterministic for the same sha and must NOT be retried" class, so the
affected PR paid a full review every round from then on, under a cause
that had not happened. Both documented causes of that reason are false
for this arm.

Measured on the DECODE now: re-encode and compare byte lengths. A
substitution replaces an invalid sequence with three bytes and changes
the length; a buffer that legitimately holds U+FFFD round-trips
unchanged. Only invalid bytes can collide two names onto one, which is
the hazard this guards — the character never could.

R6-1: the rename-source ride-along fired only when the TARGET was
restored, and that is the wrong question. Rename detection is a
similarity threshold and the two ranges compare different pairs of blobs,
so the delta can pair a rename the full range renders as a plain deletion
beside a plain addition. With a live target and that straddle, nothing
rode along, the lineage check passed on the new name alone, and the
source's deletion hunks — content no round had seen — dropped out of the
slice with the anchor advancing past them.

The rule is the direct one: does the FULL range carry a section under the
source's name? If it does, that section is unreviewed content the slice
would drop, so the source rides and the lineage check keeps it. If it does
not, both ranges paired the rename, the net hunks already sit under the
new-side section, and riding the source would demand a section that does
not exist and refuse the round.

Three new tests, each mutation-checked — including an END-TO-END U+FFFD
case, because the unit test of the helper alone left the arm that calls
it free to revert.

* fix(review): ask the decoder whether a capture is valid UTF-8

The byte-length round-trip missed every LENGTH-PRESERVING substitution,
which is the shape a truncated capture actually produces: Node emits one
U+FFFD per maximal ill-formed subpart, and a 3-byte subpart substitutes
to a 3-byte replacement character. `F0 9F 98` — a cut-off 4-byte
sequence — decoded to one U+FFFD of exactly the length it replaced, so
the guard passed it as clean and scope membership was then decided on
collided path strings: a live delta file conflated with a cleared
sibling, its sections dropped from the slice, the anchor advancing past
hunks no round had read.

Asked of the decoder now — `TextDecoder('utf-8', {fatal: true})` — which
is the only thing that knows. A literal U+FFFD in ordinary content still
decodes cleanly, which is the distinction the guard exists to draw.

Four of the reviewer's byte sequences are pinned directly; the
byte-length heuristic calls every one of them clean.

* fix(review): ride the section the full range paired a deletion under

The ride-along asked whether the full range carries a section under the
rename SOURCE's name. The two ranges can also pair the same deletion
with DIFFERENT targets: base has `a.ts = A`; the anchor round rewrites
`a.ts` to `A'` and adds `r.ts ~ A`; the fix round deletes `a.ts` and
adds `q.ts` as an exact copy of `A'`. `anchor..head` pairs `a.ts->q.ts`
(100% similarity, zero hunks); `merge-base..head` pairs `a.ts->r.ts`
and renders `q.ts` as a plain addition. Nothing names `a.ts` in the
full range, so nothing rode along, the lineage check passed on `q.ts`
alone, and the published slice retired the source's net hunks — which
sit under the section labelled `r.ts` — at the next re-anchor. Content
no round had seen, gone from every later delta by construction.

The rule now asks where the full range put the deletion. A section
under the source's name rides as before. Otherwise, when the full range
paired the source with a different target, that carrier section rides
instead; a rename target of the full range is absent at the base by
construction, so the restoration probe cannot misread it as restored
and drop it. Otherwise both ranges paired the delta's own rename, the
net hunks already sit under the new-side section, and riding anything
would refuse the round for nothing — the pinned control for that shape
still scopes by the new name alone.

One battery test built from the two-range rendering: delta pairs, full
does not. It fails at the parent commit (the slice publishes `q.ts`
alone) and passes here.

* fix(review): widen the restored-file hop in both directions

R9-1. A file the fix round reverted plays both parts, and only one was
wired. As a change it pulls its importers in; as an importer, its own
base-era calls now face whatever the PR still moves — and that second
direction is the one a revert makes load-bearing.

Round 1 changes `i.ts` (`foo(x)` → `foo(x, y)`) together with its caller
`r.ts` and clears both at the anchor. The fix round reverts only `r.ts`.
The delta is `{r.ts}`, restored, so `deltaLive` is EMPTY — and the
callee it strands was changed BEFORE the anchor and is unchanged since,
so it is not in `deltaFiles` at all. Two layers then stopped the round:
the second pass resolved `r.ts`'s import against that empty membership
and found no edge, and even with the edge `scoped` took only the
importer side, so the section that actually moves was never kept and
`kept.length === 0` ruled `nothing-new` anyway. `upToDate` does not
advance the anchor, so every re-run rules the same and
`r.ts@base × i.ts@head` — the base-era call against the new contract —
retires reviewed by no round.

The membership is now every file the PR still changes, and the edges'
targets are scoped with their importers. Restored×restored pairs stay
excluded for free: a restored file carries no section, so it is never a
candidate. `contextFileCount` follows the same move — "considered and
not scoped in" is no longer "not an interaction key", now that a seam
can scope a candidate as a target.

One regression test in the pure module; each of the three edits is
killed by it independently. It also trips one existing fixture, which
declared `a.ts` restored while serving a full range that carried a hunk
for it — a state git cannot produce, since a file identical at both ends
of the PR has no section there. That fixture now serves the honest
range, which makes its `not.toContain('a/a.ts')` structural rather than
load-bearing; the comment says so.

* fix(review): gate the widening's worktree reads on lstat before opening

The readWorktree closure fetch-pr hands to widenScope is fed paths the PR's
own file list determines — candidate files and every ancestor package.json
discoverWorkspacePackages walks up. readFileSync follows symlinks and opens
whatever sits there: a planted fifo blocks the synchronous read forever and
a device like /dev/zero grows the buffer until SIGKILL. Neither death mode
throws, so the catch that releases the worktree lease never runs and every
later review of that PR refuses or re-hangs identically.

lstat first and treat anything that is not a regular file as unreadable —
null already means that to the widening, so an irregular path contributes
no edge and the round keeps the unwidened floor. Same gate the pipeline
already applies to this hazard class in script-lint's firstLineOf and
run-ledger's ledgerOccupant.

Witnessed by probe before the fix: the verbatim closure against a modeled
worktree whose src/package.json is a fifo blocked the full timeout budget
(exit 124); gated, it returns in milliseconds. Regression test pins the
gate through runFetchPr — served content carrying a real edge is never
read when lstat says the path is not a regular file — and removing the
gate fails it.

* fix(review): contain the widening's reads, and stop skipping invariants

Two Criticals on the widening, one of them a hole in the lstat gate that
answered the last one.

**The gate defended only the FINAL path component.** `widenScope` hands
the reader paths derived from the diff, and an INTERMEDIATE component
can be a symlink the PR itself planted — ordinary git content that a
standard checkout materializes, needing no platform cooperation. The
path stays lexically inside the worktree while the kernel resolves it
outside. That is an arbitrary-file read AND a channel out, because what
the reader returns is content-derived and reaches `scope.interaction`
in the published report.

Containment is now by filesystem reality: `realpathSync(abs)` must sit
under `realpathSync(resolve(root))`. Same class and same defence as
`script-lint`'s `firstLineOf`, whose comment already names it —
"SYMLINKED ANCESTOR … lstatSync only spares the final component".

The reader moves out of the `fetch-pr` closure into
`lib/worktree-reader.ts` so it can be tested against a real filesystem,
where the kernel does the resolving; a mocked `fs` would have passed
against a fiction, which is how the lexically-inside form got through
the first gate. Six cases there, and `fetch-pr` keeps one mocked test
for the WIRING — that it reaches the worktree through this reader at
all.

**A heavy interaction file keeps its invariant agents.** The skip rested
on the premise that an interaction file's full-range slice is code the
previous round already cleared, which holds only while the merge base
holds still. Nothing enforces that: the anchor gate validates `--since`
against head history, and neither the round cache nor the posted ledger
carries a base identity, so a BACKWARD base move — the author retargets
the PR to an older base, an ordinary GitHub operation — is accepted.
`newBase..anchor` then carries hunks no round has read, they arrive
inside a heavy interaction file's full-range slice, and these three
agents are the only ones that would walk them; the chunk agent for the
same file is briefed for the seam alone.

So the skip is off until an anchor can prove base continuity — recording
the base beside `lastCommitSha` and refusing on a change is a ledger
schema change, and it belongs in its own PR. Removing it costs three
agents on a rare shape (heavy, unchanged since the anchor, importing
something that moved) and gives back the direction this design refuses
to lose in. `incrementalInteractionPaths` and the `incremental` field on
`RosterPlan` go with it.

Both fixes are mutation-checked: dropping the realpath containment turns
the reader's two escape cases red with the canary content, and turns the
`fetch-pr` wiring test red; restoring the interaction skip turns the
roster test red.

* test(review): unit-test the seam narrowToDelta now composes

Round feedback, one of three. `narrowToDelta` is a thin wrapper over
`selectNarrowing` + `assembleSections` since the reshape, and the two
halves are the surface the widening uses — it runs between them and asks
`assembleSections` for a set LARGER than `selection.touched`. Every
scenario in this file drives the wrapper, so a change correct for
`touched` and wrong for any wider set was invisible here.

Two cases, against captures real git produced: the selection reports
only the touched paths while carrying every section the full capture
does (the state the widening needs in order to consider anything), and
the emit answers for whatever subset it is handed — reproducing the
wrapper's own bytes for `touched`, adding the other section whole for a
wider set, and answering null for a set the capture carries nothing for.

Mutation-checked with a mutant shaped like the gap: gating the emit on
`selection.touched` as well as `paths` leaves the wrapper's behaviour
exactly right, and turns exactly one test — the new one — red.

Also rewords a comment in `agent-prompt.test.ts` that read as a
standing admission ("deleting the anchor guard left the suite green")
when it describes the state BEFORE the case beneath it was added.
Deleting `typeof raw.anchor !== 'string'` today is a one-test failure;
the comment now says so.

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants