Skip to content

fix(review): hold a Critical the base tree already fails - #8380

Merged
wenshao merged 8 commits into
mainfrom
fix/hold-criticals-failing-on-base
Aug 2, 2026
Merged

fix(review): hold a Critical the base tree already fails#8380
wenshao merged 8 commits into
mainfrom
fix/hold-criticals-failing-on-base

Conversation

@wenshao

@wenshao wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

A finding that blames the pull request for a failing test is now checked against the measurement the same review already took. When test-delta has recorded that the test in question fails on the merge base as well, the finding is held back from Critical to Suggestion and carries the measurement that demoted it, and the command says on stderr which finding and which file. Nothing is deleted and nothing is ever raised.

Why it's needed

test-delta exists to answer one question: of the tests failing on this PR, which are the PR's own and which were already failing. It reruns the failed commands on the merge base and splits them into netNew and shared. Nothing then read that split back, so a finding could assert "this PR breaks test X" against a file the same run had just measured as failing without the PR, and the two artifacts never met.

Measured on #8368. AuthDialog.test.tsx came back shared in two independent runs, and the merge base e967cc90 fails the very same test:

$ cd .qwen/tmp/review-pr-8368-base/packages/cli && npx vitest run src/ui/auth/AuthDialog.test.tsx
× AuthDialog > drives API key provider steps from endpoint options metadata

A Critical reading "height-based pagination breaks the pre-existing test — MiniMax is on page 2 but the test expects it visible without scrolling" was carried across four rounds and into the composed review anyway. It escaped being posted only because the PR's head had moved during the review and the run refused to submit against a stale head.

The misattribution itself is the one this pipeline has spent the most effort on: a test failing in a file the diff touches is not thereby the diff's fault. The rule that used to produce it was closed off inside test-delta. The round ledger is the other door into the same mistake, and it was open.

Downgrading rather than dropping is deliberate. The measurement contradicts the severity — the PR is not turning a passing test red — but not necessarily the observation, since a test can be red for two reasons at once. A Suggestion stays in front of a human who can restore it by naming which test now fails for a new reason and quoting both sides; a deletion would not.

Reviewer Test Plan

How to verify

npx vitest run --root packages/cli src/commands/review/findings.test.ts69 pass. The cases cover the downgrade, a Critical whose test is not shared, a non-Critical left alone, the path-boundary rule, both shapes of the test-delta artifact, junk input, and the flag end to end through the command handler.

Two independent mutations, each reddening only what it should:

# guard neutered — never downgrade
× findings (command boundary) > holds a Critical back when --test-delta measured its test as failing on base
× holdCriticalsFailingOnBase > holds a Critical that blames the PR for a test the base also fails
Tests  2 failed | 44 passed (46)

# path-boundary check removed
× holdCriticalsFailingOnBase > requires a path boundary, so a longer directory name is not a match
Tests  1 failed | 45 passed (46)

The first mutation reddening the command-boundary case as well as the unit case is the point: the wiring is pinned, not just the function.

packages/core has one unrelated failure, skill-curator.test.ts > reports skippedErrors when rename fails transiently. It reproduces on a clean tree with this branch stashed — the same discipline this PR is about.

Evidence (Before & After)

N/A — no user-visible surface changes. The evidence is the measurement quoted above and the mutation output.

Tested on

OS Status
🍏 macOS ⚠️ not tested
🪟 Windows ⚠️ not tested
🐧 Linux ✅ tested

Environment (optional)

Unit tests, plus two full /review runs against #8368 on this machine.

Risk & Scope

  • Main risk or tradeoff: a Critical that merely mentions a shared test file in passing would be demoted with it. The match needs the finding's own text to name the file on a path boundary, the demotion is announced on stderr and written into the finding, and Suggestion still reaches the reader — so the cost is a visible, reversible severity change rather than a lost finding.
  • Not validated / out of scope: --test-delta is optional and off unless passed. Reviews at low effort, or any run where test-delta did not execute, behave exactly as before. Severities are only ever lowered.
  • Breaking changes / migration notes: none. A malformed or unreadable test-delta artifact yields no shared files rather than throwing — a measurement that cannot be read must not hold a finding back, and must not take the review down either.

Linked Issues

None. Found by dogfooding /review against #8368; relates to the test-delta split introduced for this purpose.

中文说明

这个 PR 做了什么

一条把测试失败归咎于本 PR 的 finding,现在会与同一轮评审已经做过的测量相互对照。当 test-delta 已记录该测试在 merge base 上同样失败时,这条 finding 会从 Critical 降为 Suggestion,并带上让它降级的那次测量,命令同时在 stderr 上说明是哪条 finding、哪个文件。不删除任何东西,也永远不会提升级别。

为什么需要

test-delta 的存在只为回答一个问题:本 PR 上失败的测试里,哪些是 PR 自己造成的,哪些本来就在失败。它在 merge base 上重跑失败命令,并切分为 netNewshared。但此后没有任何环节回头读这个切分,于是一条 finding 可以对着同一轮刚刚测出"没有 PR 也失败"的文件断言"本 PR 弄坏了测试 X",两份产物从未碰面。

#8368 上实测:AuthDialog.test.tsx 在两轮独立运行中都被判为 shared,而 merge base e967cc90 上失败的正是同一个测试(输出见上)。一条写着"height-based pagination 弄坏了既有测试 —— MiniMax 落到了第二页,而测试期望它无需滚动即可见"的 Critical,仍然被结转了四轮并进入 composed 评审。它没有被发出去,仅仅是因为评审期间 PR 的 head 前进了,运行拒绝对着过期的 head 提交。

这种误判正是本流水线投入最多精力去消除的那一类:diff 碰过的文件里有测试失败,不等于该失败由 diff 造成。产生它的那条旧规则已在 test-delta 内部被堵死;而往轮结转是通往同一个错误的另一扇门,此前一直开着。

选择降级而非丢弃是刻意的。测量推翻的是严重级别 —— 本 PR 并没有把一个通过的测试变红 —— 但未必推翻那个观察,因为一个测试可以同时因两个原因而红。降为 Suggestion 后它仍然摆在人类面前,对方可以指出"哪个测试因为新的原因失败"并引用两侧输出来恢复它;删除则做不到。

评审者测试计划

如何验证

npx vitest run --root packages/cli src/commands/review/findings.test.ts —— 69 条通过。七条新用例覆盖:降级本身、所指测试不在 shared 中的 Critical、非 Critical 不受影响、路径边界规则、test-delta 产物的两种形状、垃圾输入,以及经由 command handler 的端到端接线。

两次独立变异,各自只打红它该打红的(输出见上)。第一次变异同时让 command-boundary 用例转红,正是要点所在:被锁住的是接线,而不只是函数。

packages/core 有一条无关失败 skill-curator.test.ts > reports skippedErrors when rename fails transiently,在把本分支 stash 掉的干净树上同样复现 —— 用的正是本 PR 所讲的那条纪律。

证据(前后对比)

N/A —— 没有用户可见的界面变化。证据即上文引用的测量与变异输出。

测试环境

仅在 Linux 上验证(见上表)。

运行环境(可选)

单元测试,外加本机对 #8368 的两轮完整 /review

风险与影响范围

  • 主要风险或权衡:一条只是顺带提到 shared 测试文件的 Critical 也会被一并降级。匹配要求 finding 自身的文本在路径边界上点到该文件,降级会在 stderr 播报并写入该 finding,且 Suggestion 仍然会送达读者 —— 因此代价是一次可见、可逆的级别变化,而不是一条被吞掉的 finding。
  • 未验证 / 不在范围内:--test-delta 是可选项,不传就不启用。低强度评审,或任何未执行 test-delta 的运行,行为与此前完全一致。级别只会被降低。
  • 破坏性变更 / 迁移说明:无。格式错误或读不出的 test-delta 产物会得到"没有 shared 文件"而不是抛错 —— 读不出的测量不该扣住一条 finding,也不该让整轮评审倒下。

关联 Issue

无。发现于对 #8368/review dogfooding;与为此引入的 test-delta 切分相关。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed and well-documented. A Critical finding on #8368 blamed the PR for breaking AuthDialog.test.tsx, while the same run's test-delta had classified that file as shared (failing on the merge base too) in two independent runs. The misattribution was carried across four rounds and nearly made it into a composed review. This is the exact class of error test-delta exists to prevent, and the round ledger was an open door back in.

Direction: aligned — this closes a gap in the review pipeline's own quality control. The downgrade-not-delete design is the right call: the measurement contradicts the severity, not necessarily the observation.

Size: 313 production lines (findings.ts), 653 test lines (findings.test.ts), 42 lines of SKILL.md documentation. Well under any threshold. Author is a maintainer (admin).

Approach: the scope feels right. Three exported functions (holdCriticalsFailingOnBase, sharedFailingFilesOf, namesPath) plus the command wiring and SKILL.md update — every change serves the stated goal. The workspace qualification in sharedFailingFilesOf is the part that matters most: five test paths exist under both packages/cli/src and packages/core/src, and a bare suffix match would demote a real finding about one workspace based on a measurement from the other. No unrelated changes or drive-by refactors.

Risk: no elevated risk signals. No high-risk paths matched.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测且有充分记录。在 #8368 上,一条 Critical finding 将 AuthDialog.test.tsx 的失败归咎于 PR,但同一轮运行的 test-delta 已在两次独立运行中将该文件归类为 shared(在 merge base 上同样失败)。这一误判被结转了四轮,险些进入 composed review。这正是 test-delta 存在所要防止的错误类型,而往轮结转是重新打开的门。

方向:对齐——这修补了 review 流水线自身质量控制的缺口。降级而非删除的设计是正确的:测量推翻的是严重级别,而非观察本身。

规模:313 行生产代码(findings.ts),653 行测试(findings.test.ts),42 行 SKILL.md 文档。远低于任何阈值。作者为维护者(admin)。

方案:范围合理。三个导出函数加命令接线和 SKILL.md 更新——每项改动都服务于既定目标。sharedFailingFilesOf 中的 workspace 限定是最重要的部分:本仓库有五个测试路径同时存在于 packages/cli/srcpackages/core/src 下,裸后缀匹配会基于另一个 workspace 的测量来降级一个真实的 finding。无无关改动或顺手重构。

风险:无升级风险信号。未匹配高风险路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal: given the problem — a Critical blames the PR for a test the base already fails — I would read the test-delta artifact's shared list, check each Critical's failureScenario/summary for a shared file mention, downgrade to Suggestion with an annotation, and wire it through the findings command with a --test-delta flag. Edge cases: missing file, malformed JSON, path matching precision.

Comparison with the diff: the PR matches this approach and exceeds it in the ways that matter:

  • Workspace qualification (sharedFailingFilesOf + repoRelative): the cross-workspace identity problem is the sharp edge. src/utils/errors.test.ts exists under both packages/cli and packages/core — a bare suffix would demote a real finding about core's copy because cli's copy was red. The PR qualifies each entry's paths from its --workspace= command, refuses project-keyed paths it cannot place, and drops any file measured netNew elsewhere. This is the part I would have gotten wrong.

  • Path boundary matching (namesPath): handles the prose context well — sentence-ending periods, extension boundaries (.snap vs end-of-text), leading / rejection (so third_party/packages/... doesn't match), and both-ends checking (so src/a.test.ts doesn't match inside src/a.test.tsx).

  • Re-adjudication respect: if a finding already carries heldByMeasurement for a file and someone raises it back to Critical, the guard leaves it alone. This makes the documented escape hatch ("say which test fails for a NEW reason and file it at Critical again") actually openable — without this check, re-applying the measurement would re-demote it forever.

  • Structured field (heldByMeasurement): not just prose in failureScenario, so a later round reading the artifact can see the hold programmatically. validateFindings round-trips it, and buildReport counts it.

No correctness bugs, security issues, or regressions found. The matching is conservative — summary and failureScenario only, never suggestedFix or locations[].file, which name test files routinely without asserting they're red. The error handling is right: missing file is silent (normal path), unparseable file warns on stderr, and neither takes the findings down.

The SKILL.md move (findings section before Verdict) is deliberate and correct — the measurement must be consulted before the verdict is composed, which is the exact path the #8368 misattribution took.

No findings. Clean review.

Testing

Check Conclusion
Test (ubuntu-latest, Node 22.x) ⏳ in progress
Test (macos-latest, Node 22.x) skipped
Test (windows-latest, Node 22.x) skipped
Desktop Shell (ubuntu-22.04) ✅ success
Classify PR ✅ success

The ubuntu test suite is still running. macOS and Windows tests were skipped (likely conditional on the ubuntu result). Will be updated by the finalize workflow once CI settles.

No user-visible behavioral changes — this is internal review pipeline tooling. Real-scenario testing: N/A.

中文说明

代码审查

独立方案: 给定问题——一条 Critical 将 PR 归咎于 base 上已经失败的测试——我会读取 test-delta 产物的 shared 列表,检查每条 Critical 的 failureScenario/summary 是否提到 shared 文件,降为 Suggestion 并附加注释,然后通过 --test-delta 标志接入 findings 命令。边界情况:文件缺失、JSON 格式错误、路径匹配精度。

与 diff 的比较: PR 与此方案一致,并在关键之处有所超越:workspace 限定解决了跨 workspace 身份问题(五个测试路径同时存在于 cli 和 core 下);路径边界匹配处理了散文上下文中的各种情况;重新裁定尊重机制使文档承诺的逃生门真正可打开;结构化字段使后续轮次可以程序化读取 hold 状态。

未发现正确性 bug、安全问题或回归。匹配是保守的——仅匹配 summaryfailureScenario,不匹配 suggestedFixlocations[].file。错误处理正确:文件缺失静默(正常路径),不可解析文件在 stderr 警告,两者都不会拖垮 findings。

SKILL.md 的移动(findings 部分移到 Verdict 之前)是刻意且正确的——测量必须在 verdict 组合之前被咨询。

无发现。审查干净。

测试

ubuntu 测试套件仍在运行。macOS 和 Windows 测试被跳过。CI 结束后将由 finalize 工作流更新。

无用户可见的行为变化——这是内部 review 流水线工具。真实场景测试:N/A。

Qwen Code · qwen3.8-max-preview

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean across every stage; the problem is real, the fix is precise, and the test coverage is thorough.

This is the kind of PR that makes the pipeline trustworthy. The misattribution it fixes is the one this review system has spent the most effort on — a test failing in a file the diff touches is not thereby the diff's fault — and the round ledger was the last open door into it. The fix is measured: downgrade, never delete; announce every hold on stderr; respect a human who re-raises a held finding; and refuse to act on a measurement it cannot read.

The workspace qualification is the part that earns its complexity. Five test paths exist under both packages/cli/src and packages/core/src, and getting that wrong would demote a real finding about one workspace based on a measurement from the other — the same class of cross-identity collapse this PR exists to prevent, one level down. The test suite covers it explicitly, including the case where a bare suffix would match the wrong workspace.

653 lines of tests for 313 lines of production code, with mutation testing showing each test reddens only what it should. The SKILL.md move puts the measurement before the verdict, which is where it must be.

CI is still running (ubuntu test suite in progress). Approving now with a CI precondition — the finalize workflow will confirm once the suite settles.

中文说明

置信度:5/5 —— 每个阶段都干净;问题真实,修复精确,测试覆盖充分。

这类 PR 让流水线变得可信。它修复的误判正是本 review 系统投入最多精力消除的那一类——diff 碰过的文件里有测试失败,不等于该失败由 diff 造成——而往轮结转是通往它的最后一扇门。修复是有分寸的:降级而非删除;在 stderr 上播报每一次 hold;尊重重新提升已 hold finding 的人类决定;拒绝基于读不出的测量采取行动。

workspace 限定是真正需要其复杂度的部分。五个测试路径同时存在于 packages/cli/srcpackages/core/src 下,搞错这一点会基于另一个 workspace 的测量来降级一个真实的 finding——与本 PR 所要防止的跨身份坍缩属于同一类,只是低了一层。测试套件明确覆盖了这一点,包括裸后缀会匹配错误 workspace 的情况。

653 行测试对应 313 行生产代码,变异测试显示每条测试只打红它该打红的。SKILL.md 的移动将测量放在 verdict 之前,这正是它必须在的位置。

CI 仍在运行(ubuntu 测试套件进行中)。现在批准并附加 CI 前置条件——finalize 工作流将在套件结束后确认。

Qwen Code · qwen3.8-max-preview

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

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.57% 83.57% 89.39% 82.78%
Core 87.61% 87.61% 89.22% 86.24%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.57 |    82.78 |   89.39 |   83.57 |                   
 src               |   84.36 |    81.54 |   88.29 |   84.36 |                   
  cli.ts           |   95.64 |     83.8 |     100 |   95.64 | ...52-553,557-558 
  gemini.tsx       |   72.21 |    76.81 |   80.76 |   72.21 | ...1253-1257,1378 
  ...ractiveCli.ts |   86.46 |    82.39 |    87.5 |   86.46 | ...2492,2498,2553 
  ...liCommands.ts |   88.09 |    84.37 |      90 |   88.09 | ...81,498,532,654 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   69.97 |    72.73 |   89.81 |   69.97 |                   
  acpAgent.ts      |   69.64 |     72.6 |   89.84 |   69.64 | ...65,11370-11372 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.04 |    95.71 |   93.33 |   97.04 |                   
  filesystem.ts    |   97.04 |    95.71 |   93.33 |   97.04 | ...21-122,238-239 
 ...ration/session |   91.65 |    86.59 |   96.24 |   91.65 |                   
  Session.ts       |   91.25 |    85.47 |   95.67 |   91.25 | ...9412,9439-9443 
  ...entTracker.ts |   91.87 |    89.47 |      90 |   91.87 | ...43,207,286-295 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |    93.1 |    90.72 |     100 |    93.1 | 71,82-85,111-121  
  ...y-replayer.ts |   98.53 |    95.52 |     100 |   98.53 | 238-240           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  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.79 |    93.43 |   96.66 |   95.79 |                   
  ...ageEmitter.ts |   95.34 |    94.11 |     100 |   95.34 | 52-59             
  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.42 |     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      |   89.07 |    72.41 |   64.51 |   89.07 |                   
  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.5 |      100 |      50 |    98.5 | 78                
  serve.ts         |   86.68 |    66.66 |     100 |   86.68 | ...70-673,687-691 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   88.29 |    87.65 |    90.3 |   88.29 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |      80 |    84.61 |      80 |      80 | 37-40,49-52,63-66 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.87 |    96.35 |     100 |   95.87 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.89 |    85.39 |   94.11 |   93.89 | ...1209,1216-1217 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.49 |    96.51 |     100 |   98.49 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |   72.85 |      100 |      50 |   72.85 | 22-28,57-68       
  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.82 |    87.64 |   87.09 |   88.82 |                   
  consent.ts       |   72.53 |       90 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |      75 |    53.84 |     100 |      75 | ...27-131,133-137 
 ...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.17 |    84.39 |   83.33 |   90.17 |                   
  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          |   92.59 |    83.87 |      80 |   92.59 | ...62-164,180-181 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   85.92 |    87.31 |   87.02 |   85.92 |                   
  agent-prompt.ts  |   90.89 |    92.78 |      96 |   90.89 | ...1311,1781-1850 
  base-tree.ts     |   74.87 |    79.16 |   77.77 |   74.87 | ...29-350,352-365 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   48.38 |    14.28 |   66.66 |   48.38 | ...21-226,239-249 
  cleanup.ts       |   89.12 |    82.22 |   83.33 |   89.12 | ...99-504,506-507 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   95.77 |    91.19 |   95.65 |   95.77 | ...1615,1643-1665 
  drive.ts         |   72.22 |    88.88 |   72.72 |   72.22 | ...34-469,473-487 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-pr.ts      |    76.7 |    68.75 |   63.63 |    76.7 | ...95,417,450-455 
  findings.ts      |   88.41 |    87.69 |   95.45 |   88.41 | ...00-903,912-913 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.32 |    96.42 |     100 |   99.32 | 400,473           
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   81.77 |    80.86 |   92.85 |   81.77 | ...1043,1072-1074 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ish-assets.ts |   76.72 |    81.92 |   71.42 |   76.72 | ...76-522,524-535 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  run.ts           |   82.16 |    87.12 |   91.66 |   82.16 | ...52,468-516,529 
  script-lint.ts   |   81.14 |    79.23 |   88.88 |   81.14 | ...59-773,775-797 
  submit.ts        |   80.82 |    81.96 |      80 |   80.82 | ...14-550,552-553 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  test-efficacy.ts |   88.01 |    84.12 |   95.45 |   88.01 | ...2598,2606-2626 
  test-plan.ts     |    90.9 |       92 |   89.47 |    90.9 | ...88-789,853-870 
 ...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 |   96.11 |     93.9 |   96.27 |   96.11 |                   
  agent-briefs.ts  |    98.8 |      100 |       0 |    98.8 | 653-654           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  authorization.ts |    92.4 |    92.59 |     100 |    92.4 | 127-133           
  budget.ts        |     100 |      100 |     100 |     100 |                   
  coverage.ts      |   95.47 |    94.28 |   95.45 |   95.47 | ...98,335,433-450 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  effort.ts        |     100 |      100 |     100 |     100 |                   
  gh.ts            |   85.92 |    91.11 |   73.33 |   85.92 | ...32,269-270,297 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |     87.5 |     100 |     100 | 84                
  prompt-record.ts |   94.73 |    88.23 |     100 |   94.73 | ...28,151-152,156 
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  report.ts        |   94.68 |    93.75 |     100 |   94.68 | 187-191           
  roster.ts        |     100 |    94.23 |     100 |     100 | 143,161,206       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.27 |    93.18 |     100 |   96.27 | ...83,269-270,294 
  workspaces.ts    |   98.88 |    92.39 |     100 |   98.88 | 212-213           
  worktree.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.37 |    88.93 |   95.63 |   94.37 |                   
  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        |   88.91 |    88.72 |   83.78 |   88.91 | ...2445,2447-2455 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.04 |    88.28 |     100 |   83.04 | ...39,253,352-353 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   94.33 |    89.61 |   94.73 |   94.33 | ...35-639,655-656 
  ...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.43 |       50 |     100 |   97.43 | 236-239           
  ...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 |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  ...ings-cache.ts |   98.26 |    97.14 |     100 |   98.26 | 201-202           
  settings.ts      |   90.99 |     92.3 |      90 |   90.99 | ...1006,1008-1009 
  ...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 
  ...tedFolders.ts |   93.35 |    94.11 |     100 |   93.35 | ...90-391,427-438 
 ...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    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...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 |    76.31 |   81.35 |      80 |                   
  session.ts       |   84.08 |    75.27 |   93.61 |   84.08 | ...1007,1016-1026 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...24-625,628-629 
 ...active/control |   75.63 |    89.09 |      80 |   75.63 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.79 |    92.45 |   88.88 |   91.79 | ...49-367,387,390 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |   42.27 |    64.66 |   48.64 |   42.27 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   53.96 |    65.71 |   58.33 |   53.96 | ...37-642,644-649 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.07 |    94.07 |   95.23 |   98.07 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1415,1431-1432 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 84-85,125-126     
  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         |   87.13 |    83.38 |   90.83 |   87.13 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |    93.4 |    92.95 |     100 |    93.4 | ...19-320,323-325 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    97.95 |     100 |     100 | 650               
  ...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 |   93.89 |    86.61 |     100 |   93.89 | ...66-468,475,477 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   86.06 |     92.2 |   95.83 |   86.06 | ...94-206,372-375 
  ...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 
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.41 |    84.44 |    97.1 |   92.41 | ...1460,1514-1518 
  ...e-grouping.ts |     100 |    94.11 |     100 |     100 | 69,132            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |   92.19 |    78.31 |     100 |   92.19 | ...60-469,494,532 
  daemon-logger.ts |    82.2 |    77.26 |   91.76 |    82.2 | ...1720,1747-1753 
  ...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.47 |    90.59 |     100 |   98.47 | ...1197,1199-1200 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.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 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.41 |    88.75 |     100 |   94.41 | ...24,702,718,728 
  fast-path.ts     |   90.61 |    81.25 |   95.45 |   90.61 | ...02-511,577-578 
  ...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-143             
  ...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 | ...27-128,139-140 
  ...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.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   82.84 |    79.62 |   74.25 |   82.84 | ...6821,6826-6827 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.19 |     87.5 |     100 |   94.19 | ...26,530-531,571 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   93.57 |    93.29 |   74.02 |   93.57 | ...2148,2169-2173 
  ...on-helpers.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.3 |    76.83 |     100 |    93.3 | ...13,816,829-831 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |    86.66 |     100 |   91.07 | ...79-182,216-219 
  ...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.51 |     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.6 |     83.9 |     100 |    91.6 | ...70-272,305-306 
 ...serve/acp-http |   77.04 |    78.33 |   93.26 |   77.04 |                   
  ...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 |    98.2 |    88.62 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   71.44 |    73.89 |   95.34 |   71.44 | ...4733,4781-4787 
  index.ts         |   81.93 |    79.92 |    90.9 |   81.93 | ...2291,2375-2376 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 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 |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...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 |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |    86.4 |    80.74 |     100 |    86.4 |                   
  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 |     73.8 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.42 |    89.18 |     100 |   90.42 | 161-169           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   86.17 |    79.55 |     100 |   86.17 | ...2506,2516-2517 
 src/serve/routes  |   85.54 |    79.53 |   95.47 |   85.54 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   85.22 |       88 |     100 |   85.22 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.45 |    83.33 |     100 |   85.45 | 98-105            
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   94.73 |     86.2 |     100 |   94.73 | 62-66,154         
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.12 |    82.73 |   92.59 |   87.12 | ...1263,1306-1307 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.17 |     81.7 |   95.16 |   85.17 | ...4633,4635-4636 
  sse-events.ts    |   84.45 |     87.5 |   77.77 |   84.45 | ...36,453-456,485 
  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.19 |    77.68 |     100 |   90.19 | ...47-448,467-468 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.09 |       79 |      90 |   83.09 | ...1032,1038,1041 
  ...extensions.ts |   87.23 |    72.76 |   94.11 |   87.23 | ...1826,1871-1872 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   84.44 |    64.51 |     100 |   84.44 | ...73-275,355-357 
  ...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 |   88.22 |    85.29 |     100 |   88.22 | ...1546,1566-1571 
  ...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 |    74.9 |    70.31 |     100 |    74.9 | ...49-660,666-667 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |   69.87 |    78.12 |     100 |   69.87 | ...59-284,290-324 
  ...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.42 |    64.78 |      80 |   78.42 | ...31-336,344-345 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   90.71 |    89.17 |   96.55 |   90.71 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...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 |   85.66 |    76.83 |     100 |   85.66 | ...02,719,782-791 
  fs-factory.ts    |     100 |    92.59 |     100 |     100 | 34,42,103,159     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...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.11 |    95.19 |     100 |   95.11 | ...65-167,422-427 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   94.81 |    90.32 |     100 |   94.81 | 175-181           
  ...on-archive.ts |   89.55 |    87.78 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   99.02 |    97.44 |     100 |   99.02 | ...25,639,781-783 
 src/serve/voice   |   83.35 |    92.22 |   90.47 |   83.35 |                   
  ...ice-config.ts |   84.61 |       30 |     100 |   84.61 | 90-99,103-104     
  voice-ws.ts      |   77.16 |    94.73 |   83.33 |   77.16 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   89.11 |    86.15 |   90.69 |   89.11 |                   
  index.ts         |   88.66 |    85.77 |   89.47 |   88.66 | ...1286-1290,1293 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.31 |    88.46 |   97.84 |   92.31 |                   
  ...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 |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...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.29 |    86.48 |     100 |   88.29 | ...91-196,229-230 
  ...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.83 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   90.37 |    87.87 |     100 |   90.37 | ...80,287,352-357 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   90.46 |    82.19 |      96 |   90.46 | ...66-668,671-673 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |    86.29 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.24 |   94.73 |   88.28 | ...1352,1356-1363 
  ...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 | 95-98             
  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    |   93.26 |       75 |   83.33 |   93.26 |                   
  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 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |    72.7 |     75.2 |    65.9 |    72.7 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   73.91 |    72.08 |   70.58 |   73.91 | ...4096,4212-4218 
  ...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 |   68.12 |    64.86 |   33.33 |   68.12 | ...98,321,341-346 
  ...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.53 |    66.18 |   51.06 |   58.53 |                   
  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.6 |    73.52 |     100 |    94.6 | ...21-222,241-247 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   82.68 |     82.8 |   89.12 |   82.68 |                   
  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 | ...24-125,133-142 
  ...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 |   68.28 |    70.14 |   84.61 |   68.28 | ...66-599,610-611 
  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 |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   82.97 |    78.57 |     100 |   82.97 | 47-52,67-70,91-96 
  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   |   79.86 |    85.71 |   66.66 |   79.86 | ...63-168,277-280 
  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 |   93.45 |    89.06 |     100 |   93.45 | ...68-169,196-206 
  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  |   84.78 |    82.47 |     100 |   84.78 | ...1071,1105-1110 
  ...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.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  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 |   91.86 |    78.87 |   66.66 |   91.86 | ...60-161,170-175 
 src/ui/components |   71.28 |    78.65 |   79.62 |   71.28 |                   
  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 | ...-72,84,139,153 
  ...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       |   74.09 |     61.4 |      50 |   74.09 | ...55-260,278-282 
  ...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.06 |    66.33 |     100 |   79.06 | ...04,507,510-516 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |    83.1 |    81.95 |      80 |    83.1 | ...2199,2225,2299 
  ...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.9 |    92.53 |      50 |    95.9 | ...99,445-449,452 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   81.95 |    71.27 |     100 |   81.95 | ...1045,1050-1066 
  ...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.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   92.97 |    83.87 |     100 |   92.97 | ...45,248,275-277 
  ...inalImage.tsx |     100 |     90.9 |     100 |     100 | 75,93             
  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 |   82.95 |    81.71 |   92.72 |   82.95 |                   
  ...sksDialog.tsx |   78.73 |    77.65 |   84.61 |   78.73 | ...1809,1833-1839 
  ...TasksPill.tsx |   67.74 |    86.66 |     100 |   67.74 | ...04-124,132-140 
  ...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.97 |    52.38 |   20.83 |   50.97 |                   
  ...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.56 |      100 |       0 |    9.56 | 40-67,70-158      
 ...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.04 |    61.53 |   70.58 |   40.04 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...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 |   89.93 |    86.42 |   85.29 |   89.93 |                   
  ...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 |   93.46 |      100 |   76.92 |   93.46 | ...90-292,295-298 
  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.38 |    81.02 |     100 |   91.38 | ...33-635,642-644 
  ...upMessage.tsx |   98.32 |    95.16 |     100 |   98.32 | 184-187,414       
  ToolMessage.tsx  |   92.62 |    85.29 |   93.33 |   92.62 | ...-982,1009-1011 
 ...ponents/shared |   85.79 |    81.95 |   94.11 |   85.79 |                   
  ...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.95 |      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 |   72.72 |      100 |     100 |   72.72 | 31-33             
  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 |   88.51 |    83.75 |   81.81 |   88.51 | ...51-779,792,887 
  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 |   69.81 |    72.64 |   61.11 |   69.81 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  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   |   83.96 |    81.62 |    86.3 |   83.96 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   92.45 |    62.79 |      50 |   92.45 | ...69-270,272-276 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 235-236           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   84.84 |    82.63 |   87.75 |   84.84 |                   
  ...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 | ...86-287,292-293 
  ...dProcessor.ts |   85.63 |    68.16 |   81.81 |   85.63 | ...1452,1473-1477 
  ...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.81 |    76.59 |     100 |   94.81 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.23 |    82.69 |     100 |   95.23 | ...53-154,277-280 
  ...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 |   83.08 |    80.25 |   74.35 |   83.08 | ...4907-4909,4911 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.01 |    98.36 |     100 |   98.01 | 139-142           
  ...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  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...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 |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   88.95 |    86.95 |     100 |   88.95 | ...37-439,471-481 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.18 |    76.47 |     100 |   95.18 | 118-119,220-225   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     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.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...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 |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  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.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...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  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 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      |   86.74 |    84.95 |   95.48 |   86.74 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   79.84 |     75.6 |     100 |   79.84 | ...66,270,328-329 
  ...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 |   92.38 |    81.91 |   95.23 |   92.38 | ...43-746,799-804 
  ...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.52 |    73.25 |   91.66 |   52.52 | ...23,626-635,638 
  commandUtils.ts  |   96.17 |    88.88 |     100 |   96.17 | ...77,179-180,323 
  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.18 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.17 |    94.73 |     100 |   91.17 | 31-33             
  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           
  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          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |     97.1 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   79.42 |    78.08 |     100 |   79.42 | ...50-572,703-704 
  ...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 |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   89.19 |    79.54 |     100 |   89.19 | ...14,316-318,434 
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.94 |    95.45 |   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       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |    59.89 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    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      |   80.94 |    72.69 |   80.55 |   80.94 |                   
  ...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 |   89.72 |    65.33 |   93.75 |   89.72 | ...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 |    68.42 |     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.47 |    86.98 |   92.54 |   81.47 |                   
  ...p-profiler.ts |   98.39 |    90.56 |     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 |       95 |     100 |     100 | 72                
  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 |       90 |     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 
  jsonc-editor.ts  |   93.18 |    92.66 |     100 |   93.18 | ...80-381,384-385 
  languageUtils.ts |   98.88 |    97.05 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   89.05 |    76.38 |     100 |   89.05 | ...86,302-303,340 
  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.67 |    56.93 |   76.92 |   45.67 | ...1034,1046-1069 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.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 |     87.5 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...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 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   91.63 |    91.02 |      95 |   91.63 |                   
  cleanup.ts       |   95.77 |    95.83 |     100 |   95.77 | 70-72             
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   91.91 |    90.47 |    87.5 |   91.91 | 58-62,73,131-135  
  throttledOnce.ts |   86.66 |     86.2 |     100 |   86.66 | ...99,105,137-138 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.61 |    86.24 |   89.22 |   87.61 |                   
 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.46 |    84.13 |   95.65 |   90.46 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.59 |    77.55 |   83.33 |   85.59 | ...1793-1797,1800 
  ...ound-tasks.ts |   96.15 |    90.13 |   98.76 |   96.15 | ...1732,1752-1755 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |    93.3 |    86.11 |     100 |    93.3 | ...85-991,996-998 
  ...w-snapshot.ts |   91.86 |    75.75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...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 |   90.55 |    86.13 |   87.64 |   90.55 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |    76.73 |   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.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.86 |    88.71 |   82.35 |   91.86 | ...1782,1831-1834 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |    94.3 |    87.17 |   91.66 |    94.3 | ...74,222,242-245 
  ...ow-sandbox.ts |   96.87 |    94.64 |     100 |   96.87 | ...24-325,330-331 
  ...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   |   81.81 |    83.99 |    87.5 |   81.81 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  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.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.96 |    87.06 |   75.48 |   84.96 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.27 |    86.78 |   73.91 |   84.27 | ...8316,8320-8321 
  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.08 |    88.44 |   93.32 |   92.08 |                   
  baseLlmClient.ts |   88.37 |    83.68 |   81.81 |   88.37 | ...51,664,670-672 
  client.ts        |   91.92 |    87.39 |   91.56 |   91.92 | ...3915,4009-4010 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...81-482,527-533 
  ...lScheduler.ts |   90.11 |       86 |      96 |   90.11 | ...5647,5675-5686 
  geminiChat.ts    |   93.03 |    89.89 |   96.29 |   93.03 | ...4931,4977-4978 
  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 |   95.19 |    89.47 |     100 |   95.19 | ...44-245,290-291 
  prompts.ts       |   93.57 |    91.42 |   83.33 |   93.57 | ...1188,1391-1392 
  ...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 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |     100 |      100 |     100 |     100 |                   
  ...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          |   98.52 |    91.74 |     100 |   98.52 | ...17,645-646,693 
  ...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 | ...1429,1458,1469 
  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 |    95.6 |    88.74 |    92.3 |    95.6 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.52 |    87.88 |   91.89 |   95.52 | ...1195-1196,1224 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.68 |    90.24 |   95.28 |   91.68 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   96.63 |    90.94 |     100 |   96.63 | ...1100,1108,1203 
  ...ix-caching.ts |     100 |      100 |     100 |     100 |                   
  ...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 |   96.73 |    89.79 |   98.27 |   96.73 |                   
  dashscope.ts     |   97.48 |    91.97 |      95 |   97.48 | ...85-386,528-529 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  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     |    86.2 |    83.24 |   92.33 |    86.2 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   78.32 |    71.83 |     100 |   78.32 | ...1122,1168-1169 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |   80.39 |     87.5 |     100 |   80.39 | 50-59             
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.82 |    86.35 |   97.82 |   90.82 | ...1215-1221,1265 
  ...ionManager.ts |   81.06 |    78.78 |   81.52 |   81.06 | ...2705,2727-2728 
  ...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 |    84.61 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   88.58 |    82.13 |     100 |   88.58 | ...62,952-953,963 
  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       
  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 |    83.78 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |    80.61 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |   79.86 |    80.36 |    90.9 |   79.86 |                   
  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.45 |    66.01 |   71.42 |   71.45 | ...49-650,657-658 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 97                
  ...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         |   94.23 |    88.89 |   95.93 |   94.23 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  goal-evidence.ts |   87.59 |     85.1 |   95.65 |   87.59 | ...12-613,636-639 
  ...projection.ts |   89.41 |    72.22 |   66.66 |   89.41 | ...28,131,135-137 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |    91.3 |       90 |     100 |    91.3 | 107-108           
  goal-reducer.ts  |   92.28 |    85.48 |     100 |   92.28 | ...74-375,388,443 
  goal-runtime.ts  |   99.05 |     93.6 |     100 |   99.05 | ...17-718,741-742 
  goal-tools.ts    |   98.32 |    93.18 |   95.23 |   98.32 | ...46-147,254-255 
  ...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-27              
  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.11 |    86.29 |   88.62 |   88.11 |                   
  ...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 |    87.91 |     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.12 |   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.58 |    83.46 |    90.5 |   87.58 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.11 |    95.72 |   96.29 |   97.11 | ...85-287,361-362 
  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 |    81.81 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   91.48 |    75.75 |     100 |   91.48 | ...99,118-121,189 
  ...entPlanner.ts |   91.59 |    76.19 |     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.95 |    82.52 |   86.36 |   86.95 | ...68,388,395-401 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   95.29 |    96.59 |     100 |   95.29 | ...80-381,402-403 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   89.85 |    82.92 |     100 |   89.85 | ...54-155,162-163 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    89.79 |     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.03 |    73.41 |   72.22 |   77.03 | ...47-451,454,460 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |     82.6 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.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.77 |    91.28 |   71.07 |   83.77 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |    84.61 |     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.54 |    89.63 |      80 |   86.54 | ...1096,1202-1206 
  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.5 |   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 |    73.84 |   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 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.49 |    84.32 |   96.84 |   89.49 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.68 |    85.71 |     100 |   97.68 | ...96,119,490-491 
  ...ionService.ts |    97.3 |    95.09 |     100 |    97.3 | ...,870,1013-1021 
  ...ingService.ts |   90.91 |    84.17 |   95.45 |   90.91 | ...2058,2085-2086 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    93.93 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   95.49 |    90.82 |     100 |   95.49 | ...37,346-347,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 |     100 |      100 |     100 |     100 |                   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...41,467-474,519 
  ...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.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.22 |    97.34 |     100 |   98.22 | ...75-676,723-724 
  ...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.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |    90.85 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |   98.38 |    93.75 |   88.88 |   98.38 | 63-64             
  ...ipt-reader.ts |   93.69 |    89.22 |   96.07 |   93.69 | ...1094-1095,1158 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |    82.1 |     73.7 |    97.5 |    82.1 | ...2364,2376-2379 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.94 |    83.69 |   97.14 |   88.94 | ...2450,2520-2540 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |   84.35 |    78.37 |   97.14 |   84.35 | ...2472,2478-2483 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...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 |   87.98 |    86.84 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.58 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.58 |     100 |   99.41 | 244-245,677       
 ...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.21 |    85.66 |   93.54 |   89.21 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.52 |    80.95 |     100 |   89.52 | ...95-896,898-901 
  skill-load.ts    |   94.84 |     87.5 |     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 |     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     |   81.16 |    83.99 |   84.57 |   81.16 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.07 |    80.95 |     100 |   99.07 | 183,197           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...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.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   56.85 |    74.35 |   64.81 |   56.85 | ...1397,1414-1434 
  metrics.ts       |   79.63 |    81.98 |   79.66 |   79.63 | ...1082,1085-1096 
  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      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,478-479,495 
  sdk.ts           |   79.22 |    89.18 |   63.63 |   79.22 | ...57-161,199-221 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.83 |    90.05 |   96.77 |   90.83 | ...1667,1698-1701 
  ...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         |   82.45 |    94.77 |   86.04 |   82.45 | ...1369,1373-1380 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.17 |    80.35 |      70 |   74.17 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.17 |    80.18 |   69.49 |   74.17 | ...1120,1158-1159 
 src/test-utils    |      94 |    98.24 |   78.94 |      94 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   92.57 |      100 |   75.75 |   92.57 | ...63,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.01 |     84.8 |   88.36 |   86.01 |                   
  ...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.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...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 |   81.49 |     80.1 |   85.71 |   81.49 | ...3217,3219-3220 
  mcp-client.ts    |   79.87 |    85.58 |   89.47 |   79.87 | ...2259,2263-2266 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |    97.2 |    93.47 |     100 |    97.2 | ...00-801,856-857 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...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.74 |    84.28 |   88.46 |   91.74 | ...93,606,804-809 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    90.24 |     100 |   82.57 | 174-185,234-247   
  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 |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   78.67 |    84.04 |   91.91 |   78.67 | ...5019,5082-5083 
  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     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,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.53 |    83.57 |      80 |   90.53 | ...1007,1065-1068 
  write-file.ts    |    86.7 |    84.92 |   88.88 |    86.7 | ...24-827,864-899 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.22 |    87.68 |   88.69 |   87.22 |                   
  agent.ts         |   85.84 |    86.59 |   86.31 |   85.84 | ...4315,4337-4347 
  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.24 |    84.81 |      75 |   86.24 |                   
  workflow.ts      |   86.24 |    84.81 |      75 |   86.24 | ...61,506,508-509 
 src/utils         |   92.84 |    89.61 |   96.84 |   92.84 |                   
  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 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.81 |    93.95 |      95 |   95.81 | ...91-492,504-517 
  ...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        |   82.62 |    94.32 |    61.9 |   82.62 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  fileUtils.ts     |   94.87 |    92.95 |   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 
  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.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  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.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...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.27 |     93.1 |     100 |   95.27 | ...16-317,359-362 
  ...-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         |   93.99 |    92.85 |     100 |   93.99 | ...88-489,491-493 
  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.9 |    86.85 |     100 |    96.9 | ...59-660,735-736 
  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.02 |     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.61 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  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 |   95.98 |    83.96 |     100 |   95.98 | ...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.07 |    88.33 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.16 |    91.91 |     100 |   98.16 | ...1244-1246,1256 
  ...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   
  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 |   85.85 |    83.78 |     100 |   85.85 | ...90-394,424-439 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  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.

@wenshao
wenshao requested a review from Copilot August 2, 2026 11:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Both findings are real and both are fixed in bee7ccb.

The unreadable-measurement guarantee. You are right, and right about why the tests did not catch it: the junk-input case calls sharedFailingFilesOf directly and never goes through readJson, so it pinned the shape tolerance and left the read untested. That is the same hollow-assertion shape this pipeline keeps finding in its own work — a pure function tested without the wiring that actually runs.

Fixed at the command rather than by weakening the claim. A cross-check that cannot read its input should not take the findings down with it: the findings are the deliverable, this is a check on them. The read is caught, no holds are applied, and stderr says so and why — the absence of a hold because the file was unreadable is exactly what a reader needs told. The two new cases drive a nonexistent path and a syntactically invalid file through the handler, and removing the try/catch reddens both:

× still writes the findings when --test-delta is a path that does not exist
× still writes the findings when --test-delta is a file that is not valid JSON
Tests  2 failed | 47 passed (49)

The trailing boundary. Also right, and it is not only cosmetic — src/a.test.ts and src/a.test.tsx are a real pair in this repo (.ts and .tsx collocated tests sit side by side across packages/cli/src/ui), so the probe could pick up its neighbour. namesPath now requires a non-name character on both ends. Dropping the trailing half reddens the new case and nothing else.

Thanks for the [].entries observation — that one was load-bearing and I had not thought it through explicitly when writing the guard.

中文说明

两条 finding 都成立,均已在 bee7ccb 修复。

「读不出的测量」这条保证。 你是对的,并且对「为什么测试没抓到」的判断也对:垃圾输入用例直接调用 sharedFailingFilesOf,从未经过 readJson,因此它锁住的是形状容忍度,而读取本身没有被测。这正是本流水线不断在自己身上发现的那种空洞断言 —— 脱离真实接线去测一个纯函数。

修的是命令路径,而不是把声明改弱。一个读不出输入的交叉检查,不该把 findings 一起拖垮:findings 才是交付物,它只是对其的一次检查。读取被捕获、不施加任何降级,并在 stderr 说明发生了什么以及原因 —— 「因为文件读不出所以没有降级」恰恰是读者需要被告知的。两条新用例让「不存在的路径」和「语法非法的文件」经由 handler 走完整条路径;去掉 try/catch 会让两条同时转红。

匹配后的边界。 同样成立,而且不只是打磨:src/a.test.tssrc/a.test.tsx 在本仓库是真实存在的成对文件(packages/cli/src/ui.ts.tsx 的 collocated 测试比邻而居),探针可能取到邻居。namesPath 现在要求两端都是非名称字符。去掉后半边界会让新用例转红,且只让它转红。

另外感谢关于 [].entries 的观察 —— 那一点是承重的,我写这个守卫时并没有显式想清楚。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review

What it does. qwen review findings gains an optional --test-delta. When the artifact names a test file as shared (failing on the merge base too), any Critical whose own text names that file is lowered to Suggestion, keeps its original scenario, gains the measurement that demoted it, and is announced on stderr. Never raises, never drops, no-ops when the flag is absent or the artifact will not read. SKILL.md passes the flag on both review findings invocations.

The shape is right: downgrade-not-delete, fail-open on an unreadable measurement, and loud on stderr for both the holds and the failed read. holdCriticalsFailingOnBase / sharedFailingFilesOf are exported and pinned at the unit level and through the command handler, and the mutation evidence in the description shows the wiring is what's pinned, not just the function. The boundary check on both ends (findings.ts:329) is correct — src/a.test.ts no longer matches inside src/a.test.tsx.

Two issues below are worth fixing before merge; the rest are small.


1. Cross-workspace path collapse can demote a genuine Critical

shared entries are the path exactly as the runner printed it. For npm test --workspace="packages/cli" — one of the two grammars build-test emits and test-delta reruns — vitest prints package-relative paths, so shared holds src/utils/errors.test.ts with no package qualifier. namesPath then matches that substring on a / boundary anywhere inside a repo-relative finding path.

This monorepo has six test paths that are ambiguous under that key — each exists in both packages/cli/src and packages/core/src:

config/config.test.ts   utils/envVarResolver.test.ts   utils/errors.test.ts
utils/gitUtils.test.ts  utils/memoryDiagnostics.test.ts  utils/paths.test.ts

Failure scenario: the PR genuinely breaks packages/core/src/utils/errors.test.ts (→ netNew from the core command) while packages/cli/src/utils/errors.test.ts was already red (→ shared from the cli command). sharedFailingFilesOf unions across entries, so src/utils/errors.test.ts is in the shared list; the Critical about core names packages/core/src/utils/errors.test.ts; the char before the match is /, the char after is end-of-token → hit. The real Critical is demoted, and the stderr line points at a file the finding is not about.

This is the direction test-delta itself calls the worse one — from failingFilesOf: "dropping it collapsed same-named files across workspaces, suppressing a real Critical as a 'measurement' — the worse of the two failure directions." The producer keeps a project token in the identity precisely to avoid this; the consumer discards the distinction by matching on a bare suffix.

Either fix closes it, and they compose:

  • Subtract netNew from shared before matching. A file measured net-new anywhere in the run is not a safe hold. One line in sharedFailingFilesOf's caller, and it needs no knowledge of workspaces.
  • Qualify per entry. entries[].command carries --workspace="packages/cli", so an entry's shared can be lifted to packages/cli/src/utils/errors.test.ts and matched as the full repo-relative path. Keep the bare form only for the unqualified npm test entry.

2. sharedFailingFilesOf does not understand the project::path key, so the hold silently never fires there

failingFilesOf keys by vitest project when the runner prints FAIL |@qwen-code/qwen-code| src/commands/x.test.ts, and test-delta.test.ts pins exactly that: '@qwen-code/qwen-code::src/commands/x.test.ts'. Those strings flow verbatim into entries[].shared and the top-level shared.

A finding never writes @qwen-code/qwen-code::, so namesPath cannot match a keyed entry, and the guard no-ops — with no stderr line, because nothing was held and nothing failed to read. The one input shape that reaches this code from a real vitest projects run is the one it cannot read.

Split on :: and probe the path half (the project half is exactly the qualifier issue 1 wants). Worth a sharedFailingFilesOf case too — the junk test covers shapes the producer never emits, but not the keyed shape it documents and tests.

3. suggestedFix in the haystack widens the false-positive surface (findings.ts:381)

A suggested fix routinely names a test file — "add a case in src/x.test.ts" — for a defect that has nothing to do with that file being red. summary, failureScenario and locations[].file are where the finding asserts its claim; suggestedFix is where it proposes work. Dropping it from the haystack narrows the match to the text the description's risk analysis is actually reasoning about.

4. A fixed finding can still be held (nit)

The hold runs after applyOutcomes, so on the --fix invocation a finding recorded fixed can come out as a Suggestion carrying "so this is not a passing test the PR turns red" — while the outcome ledger says the tree was edited for it. The two statements read as contradicting each other. Consider skipping findings whose outcome is fixed.

5. Orphaned doc comment (nit, findings.ts:320)

The insert landed between /** Most severe first, then high-confidence before low, then file and line. */ and sortFindings. That line now sits directly above namesPath (which has its own block immediately after it), and sortFindings at :421 has no doc. Move it back down.


Smaller notes

  • sharedFailingFilesOf reading both the top-level shared and every entries[].shared is redundant — test-delta already writes the top level as the union of the entries. Harmless as defensiveness against a partial artifact; worth a word in the comment saying that's the intent, since the duplication otherwise reads as uncertainty about the shape.
  • --test-delta is skill-internal, so no user docs are strictly owed, but docs/users/features/code-review.md describes the findings command's contract and mentions --outcomes; a sentence there would keep the two in step.
  • A later round that runs without test-delta (medium effort, no merge base) re-reports the carried-forward finding at whatever severity the ledger holds — correct, and the description already scopes this, but it means the hold is per-round, not sticky. Fine as designed; just not a permanent verdict.

Tests

Good coverage for what it claims: both directions of the boundary rule, non-Critical untouched, both artifact shapes, junk input, and the flag end-to-end through the handler. The two gaps mirror the findings above — no case for a project::path entry, and none for a shared/netNew collision across workspaces. Both are cheap to add and would have caught 1 and 2.

Verdict

The mechanism and its defaults are right, and the failure it closes is real and measured. Issues 1 and 2 are both in the guard's matching layer and both fail quietly — one demotes a finding it should not, the other never fires when it should. Worth resolving before merge; 3–5 are optional.

中文说明

做了什么review findings 新增可选 --test-delta。当该产物把某测试文件判为 shared(merge base 上也失败)时,凡自身文本点到该文件的 Critical 降为 Suggestion,保留原有 scenario、附上让它降级的测量,并在 stderr 播报。只降不升、不删,未传参或产物读不出时完全不动作。整体形态是对的:降级而非删除、读不出即放行、两条 stderr 都不静默;导出函数在单测与 command handler 两层都被锁住,变异证据表明锁住的是接线。

建议合并前解决的两点

  1. 跨 workspace 路径塌缩,会误降真 Criticalnpm test --workspace="packages/cli"shared 里是 src/utils/errors.test.ts 这种不带包名的路径,而本仓库有 6 个同名相对路径同时存在于 packages/cli/srcpackages/core/srcconfig/config.test.tsutils/errors.test.ts 等)。于是 core 侧真被本 PR 打红的 packages/core/src/utils/errors.test.ts(属 netNew),会被 cli 侧本就红的同名文件(属 shared)匹配到并降级,stderr 还会指向一个该 finding 并不涉及的文件。这正是 failingFilesOf 注释里点名的“更坏的那个方向”——生产方特意在身份里保留 project token,消费方却用裸后缀匹配把它丢了。两个修法任一即可,且可叠加:匹配前从 shared减去 netNew;或用 entries[].command 里的 --workspace= 把路径补全为仓库相对路径再精确匹配。

  2. sharedFailingFilesOf 不认 project::path 键,导致该场景下守卫静默失效failingFilesOf 在 vitest 打印 FAIL |@qwen-code/qwen-code| src/... 时会产出 @qwen-code/qwen-code::src/commands/x.test.tstest-delta.test.ts 明确 pin 了这个形状;而 finding 文本永远不含 ::namesPath 必然匹配不上,且因为“没有 hold、也没有读失败”,一行 stderr 都不会有。应按 :: 切分、用路径那半去匹配(project 那半正好可以服务于第 1 点)。

次要项suggestedFix 纳入 haystack 会放大误判(修复建议常顺带点名测试文件,与该文件是否发红无关,建议移出,findings.ts:381);hold 跑在 applyOutcomes 之后,fixed 的 finding 也会被降级并附上“并非本 PR 把通过的测试弄红”,与 outcome 账本自相矛盾,建议跳过 fixedfindings.ts:320/** Most severe first... */ 被新插入的代码挤成孤儿注释,sortFindings(:421)反而没有文档,建议移回。

测试:覆盖到位(边界规则两个方向、非 Critical 不受影响、产物两种形状、垃圾输入、经 handler 的端到端)。缺口恰好对应上面两条:没有 project::path 用例,也没有跨 workspace 的 shared/netNew 撞名用例——补上即可拦住 1 和 2。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

中文说明

已审查。 建议见行内评论。

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

Comment thread packages/cli/src/commands/review/findings.ts Outdated
Comment thread packages/cli/src/commands/review/findings.ts Outdated
Comment thread packages/cli/src/commands/review/findings.test.ts
Comment thread packages/cli/src/commands/review/findings.ts
Comment thread packages/cli/src/commands/review/findings.ts
@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

All five fixed in 511d1b9. Issues 1 and 2 were real bugs in the guard's matching layer, and both were the quiet kind — I verified each against the repo before changing anything.

1. Cross-workspace collapse. Confirmed: five of the six paths you list exist under both packages/cli/src and packages/core/src (utils/paths.test.ts is core-only, so five). Paths are now qualified from the entry's own --workspace= before matching, and a file any command measured netNew is dropped from the shared set even where another called it shared. Both fixes, since they close different halves — qualification handles the two-workspace case, subtraction covers a bare npm test entry that has no workspace to qualify with.

2. project::path. Confirmed at test-delta.ts:107, which writes ${project}::${path} whenever the runner prints a project tag. The key is stripped before matching. You were right that this was the worst kind of failure to leave in: no hold, no read error, no stderr — the one input shape a real projects run emits, silently doing nothing.

3–5. suggestedFix out of the haystack, a fixed finding not held (it would print "not a passing test the PR turns red" beside a ledger entry saying the tree was edited for it), sort doc comment moved back.

The two test gaps you named are both filled, and both would indeed have caught the bugs — the cross-workspace case asserts that the core Critical stays Critical and that the cli one is still held, so it pins the discrimination rather than just the absence of a match.

One more, found by the mutation pass rather than by reading. The trailing-boundary check I added for your last round's nit rejected a probe followed by . — so an ordinary sentence ending "...it goes red in src/a.test.ts." stopped matching, a false negative I introduced while fixing a false positive. My first suggestedFix test hid it by ending its sentence the same way: putting suggestedFix back in the haystack left all 56 green. A dot now extends the name only when something alphanumeric follows it, and both directions are pinned — sentence-final matches, .tsx and .snap do not.

Six mutations, each reddening only its own case:

no workspace qualification      → 3 failed
project:: key not stripped      → 1 failed
netNew not subtracted           → 1 failed
a fixed finding held            → 1 failed
suggestedFix back in haystack   → 1 failed
sentence-final dot as name char → 1 failed

58 tests pass. On the smaller notes: the comment now states that reading entries first is the point rather than defensiveness — only an entry carries the workspace its paths are relative to, so the top level is a fallback for a partial artifact, not a second source of truth. I have left the user docs alone: --test-delta is passed by the skill, never by a user, and docs/users/features/code-review.md documents the user-facing surface. Say the word if you would rather it were mentioned there anyway.

中文说明

五条全部在 511d1b9 修复。第 1、2 条是守卫匹配层的真实缺陷,而且都属于「静默」那一类;我在动手前逐条对着仓库核实过。

1. 跨 workspace 塌缩。 已确认:你列出的六个路径中有五个同时存在于 packages/cli/srcpackages/core/srcutils/paths.test.ts 只在 core,故为五个)。匹配前先用条目自身的 --workspace= 把路径补全为仓库相对路径;并且任一命令测为 netNew 的文件,即使另一命令称其 shared 也会从集合中剔除。两个修法都采用,因为它们封的是不同的一半:补全处理双 workspace 情形,剔除覆盖没有 workspace 可补的裸 npm test 条目。

2. project::path 已在 test-delta.ts:107 确认,凡运行器打印 project 标签即写成 ${project}::${path}。现已在匹配前剥离该键。你指出的性质是对的:没有降级、没有读取错误、没有 stderr —— 真实 projects 运行唯一会产出的形状,却什么都不做。

3–5. suggestedFix 移出 haystack;fixed 的 finding 不再降级(否则会在「账本说为它改了代码」旁边打印「本 PR 并没有把通过的测试弄红」);排序的文档注释移回原位。

你点出的两处测试缺口都已补上,并且确实能拦住这两个 bug —— 跨 workspace 那条同时断言 core 的 Critical 保持 Critical cli 的仍被降级,锁住的是「区分能力」,而不只是「没有匹配」。

还有一条,是变异检查而非阅读发现的。 我上一轮按你的 nit 加的尾边界检查,会拒绝后面跟着 . 的探针 —— 于是「…它在 src/a.test.ts。」这种以句号收尾的普通写法不再匹配,我在修一个假阳性时引入了一个假阴性。我最初那条 suggestedFix 测试正好也以句号收尾,把这个问题掩盖了:把 suggestedFix 放回 haystack,56 条依然全绿。现在只有当点号后面跟着字母数字时才算名称延续,两个方向都已锁定:句尾可匹配,.tsx.snap 不匹配。

六次变异,各自只打红自己的用例(见上表)。58 条测试通过。

次要项:注释现在写明「优先读 entries 是要点而非防御」—— 只有条目携带其路径所相对的 workspace,顶层因此是残缺产物的兜底,而不是第二个事实来源。用户文档我没有动:--test-delta 由 skill 传入、用户永远不会传,而 docs/users/features/code-review.md 记录的是面向用户的表面。你若认为仍应提一句,说一声我就加。

@wenshao
wenshao requested a review from Copilot August 2, 2026 12:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review: fix(review): hold a Critical the base tree already fails

What it does. Adds --test-delta to qwen review findings. When passed, any Critical whose own text names a test file that test-delta measured as failing on the merge base too is demoted to Suggestion, keeps its original evidence, gains the measurement that demoted it, and is announced on stderr. Two helpers carry it: sharedFailingFilesOf (normalizes the artifact's paths to repo-relative, qualifying each entry by the --workspace= its command names, and dropping anything measured netNew anywhere), and holdCriticalsFailingOnBase (the name-boundary match and the rewrite). SKILL.md wires the flag into both findings invocations.

Overall: the design is right and the conservative directions are all chosen correctly. Worth calling out explicitly, because they're the parts that would be dangerous to get wrong and they aren't:

  • Downgrade, never drop; Critical only; never raised.
  • Idempotent by construction — a held finding is already Suggestion, so re-running the command over the round-tripped artifact can't append the measurement twice.
  • outcome === 'fixed' is exempt, which avoids printing "not a passing test the PR turns red" beside a ledger entry saying the tree was edited for it.
  • An unreadable/malformed artifact is non-fatal and non-silent.
  • The consumer inherits the producer's safe directions: test-delta already zeroes shared when the base rerun is unusable (base.timedOut, or non-zero exit with no parsed failing file), and prTruncated can only understate shared. So neither an unbuilt base tree nor a trimmed PR-side output can manufacture a hold.

Comments below, none blocking.


1. The workspace qualification opens a false-negative on the exact prose form the runner prints

sharedFailingFilesOf now qualifies every path to repo-relative, so the probe is packages/cli/src/ui/auth/AuthDialog.test.tsx. But namesPath requires a name-boundary match of the whole probe, so a finding that quotes the failure the way vitest printed it does not match:

namesPath('src/ui/auth/AuthDialog.test.tsx is red',
          'packages/cli/src/ui/auth/AuthDialog.test.tsx')  // => false

That's the form Agent 7 is reading: npm test --workspace="packages/cli" runs vitest with root packages/cli, so the captured output — the text a finder quotes into failureScenario — says src/…. A finding anchored at the source file (locations[].file = packages/cli/src/ui/auth/AuthDialog.tsx, which is the natural anchor for "pagination breaks this test") and quoting the runner's line verbatim gets no hold, which is close to the shape of the #8368 finding this PR exists to catch.

The cross-workspace protection commit 511d1b9 added is real and shouldn't be given back — five test paths in this repo live under both packages/cli/src and packages/core/src (config/config.test.ts, utils/{envVarResolver,errors,gitUtils,memoryDiagnostics}.test.ts; the comment at findings.ts:420 says six). But it can be kept while restoring the common case: also accept the bare path when exactly one workspace in the artifact claims that suffix. errors.test.ts measured in both workspaces stays ambiguous and holds nothing; AuthDialog.test.tsx measured only under packages/cli matches either spelling.

2. locations[].file in the haystack demotes test-quality Criticals that never claimed the test was the PR's fault

findings.ts:390-393 — the haystack is summary + failureScenario + locations[].file. suggestedFix is deliberately excluded, with a good reason. locations[].file deserves the same scrutiny: it's the finding's address, not its claim.

Agent 5's brief files Criticals anchored inside a test file — a test that "asserts the opposite behaviour" or "was weakened in-diff". If that file happens to be in shared, such a finding is demoted and stamped:

X failed there too, so this is not a passing test the PR turns red.

which is a non-sequitur against a finding that never said the PR turned it red. That's a stronger false-positive vector than the one the PR body acknowledges ("merely mentions a shared test file in passing"), because the anchor is always present.

Dropping locations from the haystack is cheap to try: every test in this PR still passes (the motivating fixture and all nine unit cases name the file in summary/failureScenario). The trade-off is a Source: [test] finding that names the file only in its locations — worth deciding deliberately either way, but right now the behavior isn't pinned by a test in either direction.

3. namesPath enforces a name boundary, not a path boundary

findings.ts:326 and :345/ is not in the name class, so the leading check treats any / as a boundary:

namesPath('third_party/packages/cli/src/a.test.ts',
          'packages/cli/src/a.test.ts')  // => true

The vendor/other-src/… test passes only because the extra text attaches to a name (other-src), not because a path segment boundary is checked. Not reachable with this repo's layout, and the trailing-boundary logic is genuinely careful — but the doc comment claims a path boundary that isn't quite what's implemented. Either require the preceding char to be start-of-token (whitespace, quote, backtick, () or soften the comment.

4. The demotion is prose-only, so nothing downstream can join on it

holdCriticalsFailingOnBase returns held to the handler for stderr, but the artifact itself records the demotion only as appended text in failureScenario. compose-review, submit and the cross-round ledger can find it only by substring-matching Held back from Critical by measurement.

This is the shape test-delta itself rules out one file over — TestDeltaReport.skippedForBudget is a structured field precisely because "an equivalent discoverable only by substring-matching note is the silent cap the same brief rules out." A heldBy?: { file: string } on Finding (validated through validateFindings so it round-trips) would make the same guarantee here, and would also let a later round see that this finding was measured rather than judged.

5. Producer and consumer name the artifact differently

SKILL.md:772,798 passes .qwen/tmp/qwen-review-{target}-test-delta.json. Agent 7's brief (lib/agent-briefs.ts:453) writes <plan dir>/qwen-review-pr-<n>-test-delta.json. Those coincide only when plan dir resolves to .qwen/tmp and {target} is pr-<n>. For a local/branch review — where {target} is the captured filename per SKILL.md:165 — the names diverge, the read fails, and the flag silently no-ops. Since the whole point is that the two artifacts finally meet, it's worth having one canonical name on both sides.

Related: the guidance sentence says "Pass --test-delta whenever that artifact exists", but the bash block passes it unconditionally. On any run where test-delta didn't execute (low effort, green tests, no merge base), the command now prints

findings: no holds applied — Could not read the test-delta file at "…": ENOENT…

which reads like a failure in a run where nothing went wrong. Either guard the flag in the snippet ([ -f … ] && …) or say in the prose that this line is the expected, benign shape.


Testing

Good coverage of the interesting boundaries, and the mutation evidence in the description is the right kind — reddening the command-boundary case as well as the unit case is what makes the wiring pinned rather than just the function. Gaps worth one case each:

  • Idempotency across the two documented invocations. SKILL.md now tells the run to pass --test-delta twice; that this can't double-append the measurement rests entirely on the severity !== 'Critical' early return. It holds, but it's load-bearing and unpinned — feed the produced artifact back through --input with --test-delta and assert exactly one occurrence of failed there too.
  • A finding matched only via locations[].file (see Where is the config saved? #2) — currently unspecified in either direction.
  • A root-level npm test entry with no --workspace= token alongside a workspace entry, so repoRelative's pass-through branch is exercised with real mixed input.

Security / performance

Nothing of concern. namesPath is indexOf plus single-character class tests — no user text reaches a regex constructor, no backtracking exposure. WORKSPACE_IN_COMMAND_RE is a literal, and unlike test-delta nothing here re-executes what it reads. Cost is O(findings × sharedFiles × textLength) over sets that are single-digit in practice.

@wenshao
wenshao requested a review from Copilot August 2, 2026 12:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Three of the five are fixed or already were; two do not hold against the current tree. I checked each rather than taking the verdict.

Fixed — the two stderr gaps (c284546). Both real, both the same root: the command writes stderr that no test reads back.

Deleting the announcement loop left every test green, so a demotion could have stopped being reported while still happening. That is the worse half of it — an unannounced demotion reads as the reviewer's own judgement, which is the one thing the measurement is not. And nothing distinguished "the flag was not passed" from "the guard ran and its read failed", exactly as your if (true) mutant shows: reading undefined throws, the catch produces the same no-op, and severities are untouched either way. Both tests now capture stderr through the handler, and they redden on all three mutations — the loop deleted, its id and file dropped, and if (true).

Already fixed in 511d1b9, before these comments landed.

  • The orphaned sortFindings doc comment was anchored to bee7ccb33; it now sits directly above sortFindings at :486.
  • suggestedFix is already out of the haystack. The comment is anchored to 511d1b909, and at that commit the haystack is summary, failureScenario, locations[].file — your suggestion block is character-for-character what the code already says. Worth knowing as a false positive: the reasoning is sound and the diff it was computed against was not the one it was anchored to.

Does not hold — the top-level shared test. sharedFailingFilesOf was rewritten in 511d1b9 so the top level is a genuine fallback, read only when entries is empty. The test passes {shared: ['src/a.test.ts']} with no entries at all, so it exercises that branch exclusively. Removing the top-level read reddens it:

× sharedFailingFilesOf — cross-workspace identity > falls back to the top level only when there are no entries
Tests  1 failed | 57 passed (58)

The mutation you describe — a file present at both levels, so dropping take(top) survives — was true of the earlier version where both were read unconditionally. It is not reachable now, because a file at the top level is only ever read when there are no entries to shadow it.

60 tests pass.

中文说明

五条里三条已修或早已修好,两条对当前树不成立。我逐条核对过,没有直接采信结论。

已修 —— 两处 stderr 缺口(c2845466f)。 都是真的,且同一个根源:命令写了 stderr,却没有任何测试读回来。

删掉播报循环后所有测试依然全绿,意味着降级可能停止被报告却依然在发生。这是更糟的那一半 —— 未被播报的降级会被读成评审者自己的判断,而这恰恰是那次测量所不是的东西。另外,此前没有任何东西能区分「没传这个 flag」与「守卫跑了但读取失败」,正如你的 if (true) 变异体所示:读 undefined 会抛,catch 产出同样的空操作,两条路径下严重级别都不变。现在两条测试都经由 handler 捕获 stderr,并对三次变异全部转红 —— 删掉循环、去掉消息里的 id 与文件名、以及 if (true)

在这些评论落地之前就已在 511d1b9 修好。 sortFindings 的孤儿注释锚定在 bee7ccb33,现已位于 :486 紧邻 sortFindings 上方;suggestedFix 也早已移出 haystack —— 该评论锚定在 511d1b909,而在该 commit 上 haystack 就是 summaryfailureScenariolocations[].file,你给出的 suggestion 块与现有代码逐字相同。作为误报值得记一笔:推理本身没问题,但它据以计算的 diff 与它锚定的 commit 不是同一个。

不成立 —— 顶层 shared 那条测试。 sharedFailingFilesOf 已在 511d1b9 重写,顶层成为真正的兜底,仅当 entries 为空时才读取。该测试传入的是完全没有 entries 的 {shared: ['src/a.test.ts']},因此独占地覆盖该分支;移除顶层读取会让它转红(输出见上)。你描述的那个变异 —— 同一文件同时出现在两层,导致删掉 take(top) 仍能存活 —— 在两层都无条件读取的旧版本上确实成立,但现在已不可达,因为顶层文件只有在没有条目可以遮蔽它时才会被读到。

60 条测试通过。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Overview

Closes the loop between two artifacts the same review already produces: test-delta measures which failing test files also fail on the merge base, and findings now reads that split back to hold a Critical that blames the PR for one of them down to Suggestion, appending the measurement to failureScenario and naming the finding + file on stderr. Three files: the guard and its wiring in findings.ts, seven-plus cases in findings.test.ts, and two --test-delta lines in the review SKILL.

The shape of the change is right, and the three design calls are the right ones: downgrade rather than delete (a test can be red for two reasons), only ever lower (nothing is promoted), and an unreadable measurement holds nothing back and takes nothing down (the readJson throw is caught, the shape tolerance lives in sharedFailingFilesOf). buildReport re-sorts, so a demoted finding lands in severity order rather than keeping its old slot.

What I ran

Fresh worktree at c284546, packages/cli node_modules linked in:

  • npx vitest run --root packages/cli src/commands/review/findings.test.ts60 passed (the PR body says 46; the branch has grown since).
  • npx eslint on both changed source files → clean.
  • Mutation, namesPath body replaced with return text.includes(probe)3 failed: does not match a longer extension on the same stem, requires a boundary after the match, not only before it, requires a path boundary…. The boundary rules are load-bearing, not decorative.
  • Four probe tests written against the PR's own exported functions, for the two findings below.

Findings

1. The project:: key is stripped but can never be re-qualified — the cross-project protection the comment claims is inoperative

findings.ts · repoRelative / sharedFailingFilesOf

repoRelative does two things: strip a project:: prefix, and re-qualify a workspace-relative path with the dir parsed out of --workspace="…". The doc comment presents these as one mechanism — "failingFilesOf keeps the project token in its identity for exactly this reason; discarding it here would reopen from the consumer side what the producer closed." But the two shapes are mutually exclusive in practice, so the stripping half runs without the qualifying half ever covering for it:

  • failingFilesOf only emits a project:: key when the runner prints a project tag (FAIL |proj| src/x.test.ts).
  • build-test emits bare npm test only in the singleRoot branch (build-test.ts:67, :405) — a repo with no workspace globs — and neither packages/cli/vitest.config.ts nor packages/core/vitest.config.ts declares a project name, so the --workspace="…" commands this repo actually produces never carry a tag.

So a keyed path always arrives with workspace === undefined and degrades to a bare, project-relative path. namesPath treats / as a boundary, so that bare path then matches as a suffix of any directory. Confirmed by running the PR's exports:

sharedFailingFilesOf({
  entries: [{ command: 'npm test', netNew: [],
              shared: ['@qwen-code/qwen-code::src/utils/errors.test.ts'] }],
})
// => ['src/utils/errors.test.ts']    ← identity gone

holdCriticalsFailingOnBase([criticalAbout('packages/core/src/utils/errors.test.ts')], shared)
// => severity 'Suggestion', held [{ id: 'f1', file: 'src/utils/errors.test.ts' }]

That is exactly what failingFilesOf's own comment says the key exists to prevent: "dropping it collapsed same-named files across workspaces, suppressing a real Critical as a 'measurement' — the worse of the two failure directions." The netNew subtraction rescues the sub-case where the other project's copy is also currently failing; it does nothing when the other copy is green and the finding is about it.

The test meant to pin this — reads the vitest-project key the producer documents — pairs a :: key with command: 'npm test --workspace="packages/cli"'. That combination cannot occur, which is why the test passes while the real shape does not qualify.

The same unqualified reach applies to the else branch (top-level shared with no entries).

Reachability is narrow — it needs a single-root repo whose runner prints project tags, with a test path repeated across projects — so this is not a blocker. But it is the one direction the PR itself names as the worse one to get wrong, and it is asserted in a comment rather than held by a test.

Suggested: resolve the project token to a directory (readWorkspacePackages in lib/workspaces.ts already maps name → dir), or — cheaper, and consistent with "an unreadable measurement holds nothing back" — refuse to hold on a path that arrived keyed and could not be qualified. Either way, replace that test's impossible input with the real one (command: 'npm test').


2. The outcome: 'fixed' exemption makes the two invocations SKILL.md prescribes disagree about the same finding, silently

findings.ts:517 · SKILL.md steps 8 and 9

The SKILL now passes --test-delta on both runs, both reading the same findings-in.json. The exemption means the second run reaches a different answer. Reproduced through the command handler:

run 1 (no --outcomes):
  findings: 1 total — 0 Critical, 1 Suggestion, …
  findings: R1-1 held back from Critical — test-delta measured … as failing on the merge base too

run 2 (--outcomes [{id: R1-1, outcome: fixed}]):
  findings: 1 total — 1 Critical, 0 Suggestion, …
  (no line about R1-1)

Same finding, same input, same measurement: Suggestion in the artifact the fixer read, Critical in the final one — and the Held back from Critical by measurement: paragraph is gone from failureScenario too, so nothing in the final artifact records that a measurement ever contradicted it. This file's own header names that failure: "a Critical that changed severity between two sections of one review."

The exemption's rationale is sound (demoting something the tree was edited for reads oddly beside the ledger), but silent re-promotion is the worse of the two. Minimum fix: emit a stderr line for the exemption, so the second run is not quieter than the first. Better: keep the demotion and let outcome: fixed carry the "code was changed for it" claim — that is what the outcome field is for, and the two statements are about different things.


3. The hold reaches the artifact as prose only — no structured field

findings.ts:529-533

The only machine-readable trace of a hold is the stderr line, which no downstream consumer reads. In the artifact, the hold is an English paragraph appended to failureScenario; compose-review and the cross-round ledger can see only that the severity is Suggestion, with no way to know why.

test-delta.ts in this same directory argues the other side of exactly this, about skippedForBudget:

A STRUCTURED field, not prose only: … an equivalent discoverable only by substring-matching note is the silent cap the same brief rules out.

The concrete cost is in the round ledger, which the PR description names as the door this closes: a finding carried into round N+1 arrives as a Suggestion with no machine-readable reason, so nothing stops that round re-filing it as Critical — and round N+1's test-delta may not have rerun that command at all.

Suggested: heldByMeasurement?: { file: string } on Finding, plus a counts.held. The prose paragraph is still worth keeping for the human.


4. SKILL.md's fenced blocks contradict its own bolded caveat

SKILL.md:772, :798

The prose says "Pass --test-delta whenever that artifact exists", but both copy-paste blocks pass it unconditionally. test-delta only runs when a test command failed and a base tree is available, so on the common review — tests green — the artifact does not exist, and an agent following the block verbatim gets:

findings: no holds applied — Could not read the test-delta file at "…": ENOENT: no such file or directory

on every such run. That reads as a failure and it is the normal path.

Suggested: either mark the flag optional in the blocks the way conditional flags are marked elsewhere in this SKILL, or treat ENOENT as "no measurement was taken" quietly and reserve the loud line for a file that exists but will not parse — those are genuinely different facts, and only the second is worth alarming about.


Nits

  • shortSummary is not touched by the hold. A list UI still shows pagination breaks a test next to Suggestion. Low stakes, but the whole point of shortSummary is that it is what gets read.
  • namesPath's comment says "name boundary"; the behaviour is "path-suffix boundary". / is not in isNameChar, so probe packages/cli/src/a.test.ts is satisfied by vendor/packages/cli/src/a.test.ts. Deliberate and almost certainly harmless — but the comment should say so, since finding 1 is downstream of that same property.
  • The entries.length > 0 / else split is unreachable for a real TestDeltaReport. runTestDelta always emits entries (possibly []), and when it is empty the top-level shared is its union and therefore also empty. The fallback only serves a hand-written artifact; the comment ("the fallback for a partial artifact") reads as if test-delta produces that shape.
  • suggestedFix excluded from the haystack with a comment saying why, and a test pinning it — good. Same for the f.outcome === 'fixed' reasoning; my objection in finding 2 is to the silence, not the decision.

Verdict

Correct, well-scoped, genuinely tested (the mutations prove it), and the error handling is right in the direction that matters. Nothing here blocks merge. Finding 2 is the one I would fix before merging — it is a one-line stderr addition and it removes a severity flip between two artifacts of one review. Findings 1 and 3 are worth an issue if not this PR; 1 in particular because its comment currently claims a guarantee the code does not deliver.

@wenshao
wenshao requested a review from Copilot August 2, 2026 14:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

All four fixed in b38a841. Finding 1 is the cross-project collapse arriving through the door the last round left open, and finding 2 is a defect the last round's fix introduced — both worth stating plainly.

1. The two halves of repoRelative never met. Verified before changing anything: neither packages/cli/vitest.config.ts nor packages/core/vitest.config.ts declares a project name, so a --workspace= command in this repo never prints a tag, and a project:: key therefore always arrives with nothing to re-qualify it. My test paired the two anyway — a combination that cannot occur, which is why it passed while the real shape degraded to a bare project-relative path that matches as a suffix of any directory.

I took the refuse option rather than resolving the token through readWorkspacePackages. It keeps the guarantee whole — a measurement whose subject cannot be established licenses nothing — without putting a filesystem read inside a pure function, and it is the same rule as the unreadable artifact. The path is named on stderr, so it is set aside visibly rather than dropped:

findings: ignored the measured file @qwen-code/qwen-code::src/utils/errors.test.ts — it carries a
vitest project key and no workspace to resolve it against, so which project it names cannot be established

Resolving name → dir is the better answer the day a repo actually produces that shape; refusing is correct until then and cannot suppress anything.

2. The fixed exemption is gone, and you are right that silent re-promotion is worse. I added it last round on a reviewer's suggestion, and neither of us traced it through the two invocations the skill prescribes. Your reproduction is exact: one input, one measurement, Suggestion in the artifact the fixer reads and Critical in the final one, with the paragraph recording the contradiction gone too. This file's header names that failure by name. The two statements were never in conflict — the measurement says the base was already red, the outcome says the tree was edited for it — so both are kept now. The invariant is pinned end to end: the same finding through both invocations must come out at the same severity.

3. heldByMeasurement: { file } on the finding, counts.held beside it. You are right that test-delta argues the other side of exactly this about skippedForBudget, and that the round ledger is the consumer that made it matter — a Suggestion carrying no machine-readable reason is one the next round can re-file at will. The prose paragraph stays for the human.

4. Absent is no longer an alarm. Split as you suggested: a file that is not there is no measurement taken and says nothing; a file that exists and will not parse still speaks. That is what let the SKILL blocks stay unconditional, and the caveat above them now says so instead of contradicting them.

Four mutations, each reddening only its own cases:

strip the key and use it anyway    → 2 failed
fixed exemption restored           → 2 failed
structured field dropped           → 2 failed
alarm on a missing file            → 1 failed

65 tests pass. On your note that the body says 46 — it is stale again and I will refresh it with the final numbers once this settles rather than chase it each round.

中文说明

四条全部在 b38a841 修复。第 1 条是跨项目塌缩从上一轮留下的门里绕了回来,第 2 条则是上一轮的修复本身引入的缺陷 —— 两点都值得直说。

1. repoRelative 的两半从未相遇。 动手前已核实:packages/cli/vitest.config.tspackages/core/vitest.config.ts 都没有声明 project name,因此本仓库的 --workspace= 命令永远不会打印 tag,project:: 键也就永远在「无处可补全」的情况下到达。而我的测试偏偏把两者配在一起 —— 一个不可能出现的组合,这正是它通过、而真实形状退化为「可匹配任意目录后缀的项目相对路径」的原因。

我选择了「拒绝」而不是通过 readWorkspacePackages 解析 token:它完整保住了那条保证 —— 主体无法确定的测量不授权任何动作 —— 又不必把文件系统读取塞进一个纯函数,且与「读不出的产物」是同一条规则。该路径会在 stderr 上被点名,是显式搁置而非静默丢弃。等到真有仓库产出这种形状时,name → dir 的解析才是更好的答案;在那之前,拒绝是正确的,且不会抑制任何东西。

2. fixed 豁免已移除,你说得对:静默重新提级更糟。 那是我上一轮按另一位评审的建议加的,我们都没有把它沿着 skill 规定的两次调用走一遍。你的复现完全准确:同一输入、同一测量,fixer 读到的产物里是 Suggestion,最终产物里却是 Critical,连记录这一矛盾的那段文字也一并消失。本文件的头部正是以此命名它要防止的失败。这两个陈述从来就不冲突 —— 测量说的是「base 本来就红」,outcome 说的是「为它改了代码」—— 现在两者都保留。该不变量已被端到端锁定:同一 finding 经两次调用必须得到同一严重级别。

3. heldByMeasurement: { file }counts.held 你指出 test-delta 对自己的 skippedForBudget 恰好论证了相反的一面,这是对的;而让它真正要紧的消费者正是往轮 ledger —— 一条不带机器可读理由的 Suggestion,下一轮可以随意把它重新定为 Critical。给人读的那段文字保留。

4. 缺失不再是警报。 按你的建议拆开:文件不存在即「未做测量」,保持安静;文件存在但无法解析仍然发声。这也正是 SKILL 里的代码块可以保持无条件传参的原因,其上方的说明现在与之一致,而不再自相矛盾。

四次变异,各自只打红自己的用例(见上表)。65 条测试通过。关于你提到正文写的是 46 —— 它又过期了,我会在这一轮稳定后一次性刷新为最终数字,而不是每轮去追。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review — fix(review): hold a Critical the base tree already fails

Overview

Adds a cross-check between two artifacts the review already produces: holdCriticalsFailingOnBase demotes a Critical to Suggestion when its text names a test file that test-delta measured as failing on the merge base too, and sharedFailingFilesOf re-qualifies test-delta's workspace-relative paths back to repo-relative before the match. Wired into qwen review findings behind a new optional --test-delta, plus SKILL.md instructions to pass it on both invocations.

The direction is right and the conservatism is right — downgrade never delete, Critical only, never raise, unreadable measurement ⇒ no holds. The path-matching work in particular is careful: namesPath checks the boundary on both ends (src/a.test.ts is not satisfied by src/a.test.tsx), the sentence-final . is handled, and repoRelative refuses a project::path it cannot place rather than stripping the key into a bare suffix. Test coverage is genuinely good — 65 pass locally on b38a841, and the "same severity with and without --outcomes" case is the right invariant to pin.

Five things below, one of which I think blocks.


1. The hold lands downstream of the verdict it exists to correct — Critical

As SKILL.md is sequenced, ### Verdict (compose-review) runs before ### The findings, as data (the findings command this PR adds the flag to). So by the time a Critical is held back:

  • compose-review has already counted it out of the hand-written compose.json / comments.json and printed Verdict: Request changes;
  • the drafted inline comment still opens with **[Critical]**, and Step 7's submit recounts from that payload.

The demotion reaches findings.json — which drives the Step 8 report and the numbers quoted in the Summary — and nothing else. The motivating incident in the PR body is a Critical that reached the composed review; this fix does not close that path. (It escaped posting because head had moved, not because of anything here.)

SKILL.md already has the mechanism — "If the comment set changes after composing … update the comments file (and the state), and run compose-review again" — but nothing in the new prose tells the orchestrator that a hold is such a change. Cheapest fix: add one sentence to the new --test-delta paragraph saying that any hold requires re-drafting the comment marker and re-running compose-review. Better: move the findings invocation above ### Verdict so the canonical severities exist before the verdict is computed.

2. heldByMeasurement does not round-trip through --input — Suggestion

The field's own doc comment is the justification for making it structured:

A later round reads the artifact, not the paragraph, so a hold discoverable only by substring-matching failureScenario is a hold the round ledger cannot see.

But validateFindings builds its result from a whitelist and never copies heldByMeasurement, so feeding findings.json back through --input drops it — and counts.held recomputes to 0. Verified:

× round-trip of heldByMeasurement > survives --input
  → expected undefined to deeply equal { file: 'packages/cli/src/a.test.ts' }

This is exactly the invariant outcomeNote was explicitly added to satisfy a few lines above ("an artifact fed back through --input that kept its outcomes but silently dropped their reasons…"), and the file already has a validateFindings — the canonical artifact round-trips describe block. Fix is three lines in the return object, plus a case in that block.

3. locations[].file over-matches — a Critical about an already-red test gets demoted — Suggestion

suggestedFix is deliberately excluded because a test file named there is proposed work, not a claim of redness. locations[].file has the same problem in a sharper form: for a finding about a test file's content, the location is the test file. Verified:

{
  summary: 'The new assertion in AuthDialog.test.tsx asserts the wrong thing',
  failureScenario: 'The test asserts `visible` where the contract is `enabled`, ' +
                   'so a regression that flips enabled ships green.',
  locations: [{ file: 'packages/cli/src/ui/auth/AuthDialog.test.tsx', line: 40 }],
}
// shared: ['packages/cli/src/ui/auth/AuthDialog.test.tsx'] → Suggestion

Nothing in that finding blames the PR for a failing test, and "the PR touches a test file that was already red" is precisely the situation where a review is most likely to file a Critical about that file. The measurement contradicts nothing here. Worth considering: match only summary + failureScenario, or require the matched location to differ from the finding's own subject.

4. The no-entries fallback reopens the cross-workspace collapse — Nice to have

sharedFailingFilesOf falls back to top-level shared with workspace: undefined, so paths stay workspace-relative — and namesPath's leading boundary is satisfied by /, so an unqualified src/utils/errors.test.ts matches inside packages/core/src/utils/errors.test.ts:

sharedFailingFilesOf({ shared: ['src/utils/errors.test.ts'] })
// → a Critical naming packages/core/src/utils/errors.test.ts is demoted

That is the exact collapse repoRelative and the does not hold a Critical about the OTHER workspace test exist to prevent, reintroduced by the fallback. Latent rather than live — runTestDelta derives top-level shared as the union of entries, so a real artifact never has one without the other — but the branch is reachable from any hand-written or future producer, and it currently contradicts the function's own stated rationale. Consider dropping the fallback (an artifact with no entries measured nothing) or documenting that its paths are unqualified by design.

5. unidentifiable fires for netNew-only keyed paths — Nice to have

take() funnels unplaceable paths into unidentifiable from both the shared and netNew lists, and the handler prints a line per entry: "ignored the measured file X … coverage the command chose not to use". A netNew file was never eligible to hold anything back, so nothing was set aside — and for a plain npm test with vitest projects (the shape that always produces the :: key) most entries land in netNew. Scoping the set to shared keeps the disclosure honest.


Nits

  • PR body's test plan says "46 pass … seven new cases"; the branch is now at 65 after the three follow-up commits. Worth refreshing, since the body is the reviewer's entry point.
  • Comment-to-code ratio in the new block is high even for this file — the handler's if (testDelta !== undefined) body carries 14 lines of rationale over 12 lines of code, and the feat(auth): add Kimi and Xiaomi MiMo providers #8368 narrative appears three times (doc comment, SKILL.md, PR body). Not a blocker; the repo does favour rationale comments.

Verified locally

  • npx vitest run --root packages/cli src/commands/review/findings.test.ts65 passed on b38a841.
  • Findings 2–4 reproduced with throwaway cases against the PR's own exports (removed afterwards).
  • Confirmed the producer path: runTestDelta writes entries[] with --workspace="…" commands and workspace-relative paths, and agent-briefs.ts:453 writes <plan dir>/qwen-review-pr-<n>-test-delta.json — which does match the SKILL's .qwen/tmp/qwen-review-{target}-test-delta.json for a PR review, so the flag is not a no-op by filename.
中文说明

总览

把两份评审已经产出的产物对上了:holdCriticalsFailingOnBase 在 finding 文本点到 test-delta 测得"merge base 上同样失败"的测试文件时,把 Critical 降为 Suggestion;sharedFailingFilesOf 先把 test-delta 的 workspace 相对路径还原成仓库相对路径再匹配。方向和保守程度都对——降级不删除、只碰 Critical、从不提升、测量读不出就不扣人。路径匹配这块尤其扎实:namesPath 两端都查边界,句末 . 有处理,repoRelative 对无法定位的 project::path 选择拒绝而不是剥掉 key。本地 65 条测试全过。

下面五点,第一点我认为应当阻塞。

1(Critical)降级发生在它要纠正的 verdict 之后。 按 SKILL.md 的顺序,### Verdict(compose-review)在 ### The findings, as data(本 PR 加旗标的 findings 命令)之前。等到 Critical 被扣下时,compose-review 已经从手写的 compose.json / comments.json 算出了 Request changes,草拟的 inline comment 仍以 **[Critical]** 开头,Step 7 的 submit 也按这个 payload 重新计数。降级只到达 findings.json。PR 描述里 #8368 的那条 Critical 正是进了 composed 评审——这条路径没有被堵上。SKILL.md 已有机制("comment 集合变了就重跑 compose-review"),但新段落没告诉编排者"一次 hold 就是这种变化"。最省事:在新段落补一句;更好:把 findings 调用挪到 ### Verdict 之前。

2(Suggestion)heldByMeasurement 过不了 --input 往返。 该字段的注释正是以"下一轮读的是产物不是段落"为理由才做成结构化的,但 validateFindings 是白名单构造,没有拷贝它——把 findings.json 回喂 --input 就丢了,counts.held 也回到 0(已实测)。这恰恰是上面几行 outcomeNote 明确为之补上的那条不变量,本文件也已有 canonical artifact round-trips 的 describe 块。改动约三行。

3(Suggestion)locations[].file 匹配过宽。 suggestedFix 被刻意排除,因为那里的测试文件是"待办"而非"红了"的断言;locations[].file 有同样的问题且更尖锐:一条关于测试文件内容的 finding,它的 location 就是那个测试文件。实测:一条说"新断言断错了对象"的 Critical,只因该文件在 base 上也红,就被降级。而"PR 动了一个本来就红的测试文件"恰恰是最容易产生这类 finding 的场景。建议只匹配 summary + failureScenario

4(Nice to have)无 entries 的兜底分支重新打开了跨 workspace 塌缩。 兜底时 workspaceundefined,路径保持 workspace 相对,而 namesPath 的前置边界被 / 满足,于是 src/utils/errors.test.ts 会在 packages/core/src/utils/errors.test.ts 里命中——正是 repoRelative 与那条 "OTHER workspace" 用例要防的塌缩。真实产物不会走到(顶层 sharedentries 求并集),属潜在而非现行缺陷,但与函数自己写的理由相矛盾。

5(Nice to have)netNew 里的 keyed 路径也会被播报为"被忽略"。 take()sharednetNew 一视同仁地灌入 unidentifiable,而 netNew 文件本来就没资格扣任何东西,"被搁置的覆盖"这个说法不成立。把该集合限定到 shared 更诚实。

小项: PR 描述写"46 条通过 / 七条新用例",分支现在是 65 条,建议更新;新增块的注释密度偏高(handler 里 12 行代码配 14 行说明,#8368 的叙述出现三处)。

@wenshao
wenshao requested a review from Copilot August 2, 2026 14:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

All five fixed in f3e6e03. Finding 1 is correct and it is the one that mattered: the change did not close the door it was opened to close.

1. The hold landed downstream of the verdict. Verified in the tree — ### Verdict at :734, ### The findings, as data at :763. So compose-review had already counted the Critical, printed Request changes, and the drafted marker still read **[Critical]** when the measurement was finally consulted. The demotion reached findings.json and nothing a reader sees. The #8368 Critical went out through exactly that path, and my description claimed the door was shut.

I took the structural option rather than the sentence: the findings artifact is now written before ### Verdict, so the canonical severities exist when the verdict is computed from them — which is what the Verdict section already says it does. The one-sentence version is there too, for a hold that arrives after composing (a later round, a re-verified finding): it is a comment-set change, and the skill's existing rule for those applies.

2. heldByMeasurement did not survive --input. Right, and the irony is that the paragraph justifying the field is directly below the one outcomeNote was added for. Fixed the same way, with a case in the round-trip describe block; counts.held no longer resets to zero on the way back in.

3. locations[].file is the sharper version of the suggestedFix problem. Agreed, and your example is the one that convinced me: a finding whose subject is a test's content carries that test as its location, and a PR touching an already-red test is precisely when such a finding gets written. The measurement says nothing about whether the assertion checks the right property. The haystack is now summary + failureScenario only — where a finding states its claim.

4. The fallback qualified nothing, so it may hold nothing. Dropped rather than documented. An artifact with no entries has lost the workspace context, and honouring it puts back the bare path that matches inside any package — the collapse, through the one door left open. A real artifact always has entries.

5. unidentifiable scoped to shared. A netNew path was never eligible to hold anything back, so nothing was set aside by dropping it, and on the very shape that produces most keyed entries the line would have been pure noise.

Four mutations, each reddening only its own case:

heldByMeasurement dropped on round-trip  → 1 failed
locations back in the haystack           → 1 failed
unqualified fallback restored            → 1 failed
netNew reported as set aside             → 1 failed

68 tests pass, and the PR body is refreshed with that number.

On the comment density: fair. The #8368 narrative is now in one place — the holdCriticalsFailingOnBase doc — and the handler block keeps only what is not inferable from the code beside it.

中文说明

五条全部在 f3e6e03 修复。第 1 条是对的,也是真正要紧的那条:这个改动没有堵上它开出来要堵的那扇门。

1. 降级发生在 verdict 下游。 已在代码树中核实 —— ### Verdict 在 :734,### The findings, as data 在 :763。因此当测量终于被查阅时,compose-review 早已把这条 Critical 计入、打印了 Request changes,草拟的标记也仍是 **[Critical]**。降级只到达 findings.json,读者能看到的东西一概没变。#8368 那条 Critical 正是从这条路径出去的,而我的描述却宣称这扇门已经关上。

我选择了结构性的做法而非补一句话:findings 产物现在写在 ### Verdict 之前,于是计算 verdict 时规范化的严重级别已经存在 —— 这正是 Verdict 一节自己声称的做法。那一句也保留了,用于降级在 composing 之后才到达的情形(后续轮次、重新验证的 finding):那是一次 comment 集合变更,skill 既有的规则适用。

2. heldByMeasurement 过不了 --input 属实,而讽刺之处在于,论证该字段的那段话就紧挨着当初为 outcomeNote 补上同一条不变量的那段。已用同样方式修复,并在 round-trip 的 describe 块里加了用例;counts.held 不再在回喂时归零。

3. locations[].filesuggestedFix 问题更尖锐的版本。 同意,说服我的正是你给的例子:一条主体就是测试内容的 finding,其 location 就是那个测试文件,而「PR 动了一个本来就红的测试」恰恰是写出这类 finding 的时刻。测量对「该断言是否检查了正确的属性」一无所言。haystack 现在只有 summary + failureScenario —— finding 陈述其主张的地方。

4. 兜底分支什么都补全不了,因此什么都不该扣。 直接删除而非加注说明。没有 entries 的产物已经丢失 workspace 上下文,采纳它就会把「可匹配任意包内部」的裸路径放回来 —— 正是那个塌缩,从最后一扇没关的门进来。真实产物永远带 entries。

5. unidentifiable 限定到 shared netNew 路径本来就没资格扣下任何东西,丢弃它并未搁置什么;而在产出多数 keyed 条目的那种形状下,这行提示纯属噪音。

四次变异,各自只打红自己的用例(见上表)。68 条测试通过,PR 正文已同步该数字。

关于注释密度:说得对。#8368 的叙述现在只保留在一处(holdCriticalsFailingOnBase 的文档),handler 那段只留下无法从旁边代码推断出的内容。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Overview

qwen review findings gains --test-delta. A Critical whose summary/failureScenario names a test file that test-delta measured as failing on the merge base is held back to Suggestion, gains a heldByMeasurement: {file} field and an appended paragraph carrying the measurement, is counted in a new counts.held, and is announced on stderr. Supporting work: sharedFailingFilesOf qualifies each entry's workspace-relative paths back to repo-relative using the --workspace="…" in the entry's command, refuses a project::path key it cannot place, and drops any file some other command measured as netNew. SKILL.md wires the flag into both findings invocations and moves "The findings, as data" above the Verdict section.

The direction is right and the design decisions are the conservative ones throughout: only Critical is touched, severity is only ever lowered, nothing is deleted, and an absent or unparseable artifact yields zero holds rather than an exception.

What I verified

Ran the PR's findings.ts + findings.test.ts in an isolated copy against this checkout: 68 passed (the Test Plan says 46 — stale, worth updating). Cross-checked against the producer: test-delta populates entries[].shared only when baseUnusable is false, so consuming shared never reads a timed-out or unbuilt base as green — the consumer inherits that guarantee correctly. failingFilesOf does emit workspace-relative paths for --workspace= commands, so the repoRelative qualification is necessary and correct, and the artifact path in SKILL.md (.qwen/tmp/qwen-review-{target}-test-delta.json) matches what Agent 7's brief writes — a mismatch there would have made the guard a permanent silent no-op. The SKILL.md section move stays inside ## Step 6, so extract-step boundaries are unaffected. counts.held becoming required on FindingsReport['counts'] breaks nothing: buildReport is the only producer in-tree.

Findings

1. The documented way to restore a held Critical cannot work (design gap)

Both SKILL.md and the paragraph appended to the finding tell the reader to restore it by "naming which test fails for a new reason and quoting both sides". But naming the test file in summary/failureScenario is the match condition, so a re-raised Critical is demoted again, and there is no override — no flag, no heldByMeasurement short-circuit. Verified: feeding the held finding back at Critical re-demotes it and appends the same paragraph a second time (appends=2), so the text also accumulates once per round.

The escape hatch as written is only reachable by not naming the test — the opposite of what the instruction asks for.

Cheapest fix that keeps the guard honest: skip a finding that already carries heldByMeasurement.file === hit. A finding that was measured, demoted, and then deliberately re-filed as Critical has had the measurement weighed against it already; re-applying the same measurement to the same finding adds no information and silently overrides the decision. As a floor, at least don't re-append when the marker is already present.

2. sharedFailingFilesOf's JSDoc contradicts its own code

the top-level shared is the union of the same files with that context already lost, and is the fallback for a partial artifact rather than a second source of truth

There is no fallback — after the if (rows.length > 0) block there is no else, so the top-level list is never read on any path. Verified: {entries: [], shared: ['src/a.test.ts']}shared: []. The inline comment ~20 lines below states the correct (opposite) policy and explains why. The JSDoc should say the top level is never honoured, not that it is a fallback.

3. A test's name asserts behaviour the code does not have

describe('sharedFailingFilesOf') > 'takes the shared list from the top level and from every entry' passes unchanged when the top-level shared key is deleted (verified by mutation) — src/a.test.ts also appears in an entry, so the top-level half of the assertion is vacuous. Given #2, rename it to entries-only and drop the key, otherwise it reads as coverage for a code path that does not exist.

4. namesPath's leading boundary lets a nested copy match

isNameChar excludes /, so a repo-relative probe matches at any path depth: probe packages/cli/src/a.test.ts is satisfied by third_party/packages/cli/src/a.test.ts and the Critical is demoted (verified). The function's own doc claims the boundary rule prevents exactly this class (vendor/other-src/a.test.ts) — and it does when the extra text ends in a name char, but not when it ends in /. Low real-world exposure (vendored copies of the repo's own tree), but the trailing side got both-ends treatment and the leading side did not. Anchoring the leading side on start-of-text / whitespace / quote / backtick would close it.

5. Minor

  • existsSync + readJson: a small TOCTOU, and resolve() runs twice on the same path. A single try/catch that distinguishes ENOENT from a parse error gives the same two-facts-two-treatments behaviour without the race.
  • User docs: docs/users/features/code-review.md documents review findings --outcomes but not --test-delta. A mechanism that can lower a severity — and therefore change what the verdict is computed from — deserves a line there, not only in SKILL.md.
  • Test Plan: says 46 tests; the branch has 68 in that file.

Correctness / performance / security

No performance concern — the match is O(findings × sharedFiles) over two short strings. No security surface beyond reading a caller-supplied JSON path, and the failure mode is fail-open by design and correctly so. Test coverage of the new logic is genuinely good: the cross-workspace collapse, the project-key refusal, the netNew-anywhere drop, both boundary directions, junk input, and the command-boundary wiring are each pinned by their own case.

Verdict: the behaviour change is sound and well-tested. #1 is worth resolving before merge — the guard currently has no exit, and the docs promise one. #2#4 are cheap corrections to comments, a test name, and one boundary check.

@wenshao
wenshao requested a review from Copilot August 2, 2026 15:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Ran four rounds of self-review over the whole diff. Three found something; the fourth came back clean.

Round 1 — the hold was not idempotent. A finding a later round re-files as Critical was held again and gained a second, identical paragraph. Two explanations under one finding read as two measurements, and a held finding carried forward is precisely the case heldByMeasurement was made structured for — the state to decide on was already in the artifact and unused. Measured before and after:

after 1 hold : 1 paragraph
after re-file: 2 paragraphs   →   1 paragraph

It still lowers the severity on the second pass; it just stops narrating.

Round 2 — moving the section was necessary and not sufficient. compose-review reads comments.json and compose.json, both hand-written, so a severity lowered in findings.json still ships as **[Critical]** if the marker was copied from the draft rather than the artifact. Ordering alone only makes the canonical severity available. The skill now says to read severity out of findings.json for every marker and body Critical, which is the sentence that actually closes the path #8368 took.

Round 3 — two of the change's own claims were wrong, which matters more here than it usually would:

  • "Pass --test-delta unconditionally — the blocks above already do" named one block, with the other still below it in Step 6B. It now names both.
  • "Six test paths in this repo exist under BOTH packages/cli/src and packages/core/src" is five. I carried the number over from a review comment without counting, and had already noted in my reply that one of the six listed there is core-only. Counted:
src/config/config.test.ts          src/utils/gitUtils.test.ts
src/utils/envVarResolver.test.ts   src/utils/memoryDiagnostics.test.ts
src/utils/errors.test.ts

Round 4 — checked what the code does against what it says. WORKSPACE_IN_COMMAND_RE has no g flag, so .exec is not stateful across entries; build-test only ever emits the quoted --workspace="<dir>" form the regex matches, and test-delta's own rerun filter requires the same shape; the artifact name the brief writes matches the one the skill reads for a PR target. Nothing new.

49 files, 1527 tests, tsc --build --force clean.

中文说明

对整份 diff 做了四轮自审,前三轮各有发现,第四轮干净。

第 1 轮 —— hold 不幂等。 被后续轮次重新定为 Critical 的 finding 会再次被扣下,并追加第二段完全相同的说明。一条 finding 下有两段解释,读起来像做过两次测量;而"被结转的已扣下 finding"恰恰是把 heldByMeasurement 做成结构化字段的理由 —— 可据以判断的状态早已在产物里,却没被用上(前后对比见上)。第二次仍会降级,只是不再复述。

第 2 轮 —— 移动章节是必要但不充分的。 compose-review 读的是手写的 comments.jsoncompose.json,因此在 findings.json 里被降下来的严重级别,如果标记是从草稿而非产物抄的,仍会以 **[Critical]** 出货。仅靠顺序只是让规范化的严重级别可得。skill 现在明确要求:每个标记与正文 Critical 的 severity 都从 findings.json 读取 —— 这才是真正堵住 #8368 那条路径的一句话。

第 3 轮 —— 本次改动自己的两处主张是错的,在这个 PR 上这比通常更要紧:「--test-delta 上面的代码块都已经这样做了」实际只点到一个块,另一个仍在下方的 Step 6B;「六个测试路径同时存在于两个包」实际是五个 —— 我把评审评论里的数字直接搬了过来而没有去数,而我在回复里明明指出过其中一个只在 core(清单见上)。

第 4 轮 —— 拿代码行为核对它自己的说法。 WORKSPACE_IN_COMMAND_RE 没有 g 标志,.exec 不会跨条目保持状态;build-test 只会产出该正则匹配的带引号 --workspace="<dir>" 形式,而 test-delta 自己的重跑过滤器要求同一形状;brief 写出的产物名与 skill 在 PR 目标下读取的名字一致。无新发现。

49 个文件、1527 条测试通过,tsc --build --force 无错误。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Local verification on a real build — merge reference

Built both sides for real and ran the actual pipeline, not just the unit suite.

PR head f3e6e0385 (6 commits)
Merge base 4379755
Environment macOS 26.6 (Darwin 25.6.0, arm64), Node v24.18.1
Both trees npm cinpm run buildnpm run bundle, giving two real dist/cli.js binaries

The merge-base binary is what "before" means everywhere below: the same command, one commit earlier.


1. The real pipeline, end to end, on a measurement this machine actually took

The interesting question is not whether the helper downgrades — it is whether the guard can tell a pre-existing failure from one the PR really caused, on an artifact test-delta really wrote. So I built that situation instead of hand-writing the artifact:

  • packages/channels/base/src/sanitize.ts broken identically on both treessanitize.test.ts is red on the PR side and on the merge base.
  • packages/channels/base/src/paths.ts broken on the PR tree onlypaths.test.ts is red only there.

Then the real chain: qwen review capture-localqwen review build-test (really compiles, really runs the suite) → qwen review test-delta (really reruns the failed command on the built base tree) → qwen review findings --test-delta.

test-delta measured, with no help from me:

netNew : ['src/paths.test.ts']
shared : ['src/ChannelBase.test.ts', 'src/sanitize.test.ts']

ChannelBase.test.ts is a failure I did not plant — it is genuinely red on both trees on macOS, which makes it a free extra sample of the case this PR exists for.

Two Criticals, one blaming each file, through both binaries:

finding blames merge-base build this PR's build
R1-1 sanitize.test.ts (measured shared) Critical Suggestion, heldByMeasurement set
R1-2 paths.test.ts (measured netNew) Critical Critical — untouched

That second row is the one that matters most: the guard does not suppress a real breakage just because it lives next door to a held one.

end-to-end run

2. The same guard against an artifact from a genuine /review run

.qwen/tmp/qwen-review-pr-8351-test-delta.json is still on this machine from a real review of #8351. Its shared list includes src/config/config.test.ts, measured under the packages/core command — and config/config.test.ts is one of the paths that exists under both packages/cli/src and packages/core/src. So this artifact tests the workspace-qualification claim on data nobody wrote for the purpose:

finding blames result
R1-1 packages/core/src/config/config.test.ts Suggestion — held
R1-2 packages/cli/src/config/config.test.ts (same relative path, other package) Critical — left alone
R1-3 packages/core/src/core/logger.test.ts (red on base only, never in prFailingFiles) Critical — left alone

real artifact

3. Twenty-six boundary assertions through the built CLI

Every one goes through node dist/cli.js review findings, not the exported function — the wiring is what a review run depends on.

Covered: cross-package collision both directions · artifact absent (silent, exit 0) · artifact unparseable (loud, exit 0, findings still written) · vitest project key with no workspace to resolve it (refused and disclosed) · file named only in suggestedFix · file that is the finding's location · the SKILL's two invocations agreeing with and without --outcomes · heldByMeasurement surviving a round-trip back through --input · top-level shared with no entries · netNew anywhere beating shared elsewhere · non-Critical severities untouched · .tsx not satisfying .ts · a path ending a sentence.

26 passed, 0 failed.

boundary cases

4. Nine mutations, nine caught

One load-bearing line broken at a time, then the suite run. A mutation nothing reddens is a guarantee nothing pins.

mutation reddened
guard neutered — never hold anything back 7 tests
path boundary dropped — plain substring match 3
workspace qualification dropped — bare suffix 3
heldByMeasurement dropped on re-read 1
unreadable-measurement try/catch removed 2
existsSync guard removed 1
suggestedFix + locations folded into the haystack 2
netNew no longer overrides shared 1
unidentifiable path passed through instead of refused 3

The first one reddening the command-boundary cases alongside the unit cases confirms the description's claim: the wiring is pinned, not just the function.

mutations

5. Suites, types, lint

findings.test.ts 68 passed · whole src/commands/review/ surface 1521 passed in 48 files · npm run typecheck exit 0 · eslint clean · prettier clean. No pre-existing failure anywhere in the review surface on this machine.

suites


Notes for the record — none of them blockers

  1. The Test Plan numbers are stale. It says "46 pass" and "Seven new cases"; the branch now has 68 in that file, against 38 at the merge base — +30, not +7. Five more commits landed after the description was written. Worth refreshing, since the Test Plan is what a reviewer reruns.

  2. "Six test paths … under BOTH packages/cli/src and packages/core/src" — I measure five at f3e6e0385: config/config.test.ts, utils/envVarResolver.test.ts, utils/errors.test.ts, utils/gitUtils.test.ts, utils/memoryDiagnostics.test.ts. The argument the comment makes is exactly right and §2 above confirms it on real data; only the count is off by one.

  3. Version skew is a hard failure, not a degradation. Handing --test-delta to a binary that predates it exits 1 with Unknown arguments: test-delta, testDelta and writes no findings artifact. SKILL.md ships inside the same bundle as the CLI, so they move together and this cannot bite a normal install — it only surfaces if QWEN_CODE_CLI points at an older binary than the skill in use. Recording it because "pass --test-delta unconditionally" makes the coupling load-bearing.

  4. namesPath's left boundary is a name-char boundary, not a path-segment one. A shared packages/cli/src/utils/errors.test.ts is also matched by a finding writing third_party/packages/cli/src/utils/errors.test.ts (verified — it gets held). That looks deliberate: it is what lets ./-prefixed and repo-root-prefixed spellings match, and no such nesting exists in this repo. Noting the asymmetry with the right-hand side, which is segment-strict.

  5. The Tested on table can gain macOS — everything above ran there.

Summary

The behaviour the PR claims is the behaviour the built CLI has, including on an artifact a real review wrote months before this change existed. The two directions that matter are both correct: a Critical against an already-red test is held and carries its measurement; a Critical against a test the PR genuinely broke is untouched. Failure modes are conservative in the right direction — an unreadable, absent, partial, or unplaceable measurement holds nothing back and never takes the findings down. No blocking issue found. LGTM from this side, with the description refresh in note 1 the only thing I would do before merging.

中文版本

本地真实构建验证 —— 合并参考

两侧都做了真实构建,跑的是真实流水线,不只是单测。

PR head f3e6e0385(6 个 commit)
Merge base 4379755
环境 macOS 26.6(Darwin 25.6.0, arm64),Node v24.18.1
两棵树 npm cinpm run buildnpm run bundle,得到两个真实的 dist/cli.js

下文所有「之前」都指 merge base 那个二进制:同一条命令,早一个 commit。


1. 端到端跑真实流水线,用这台机器真实测出来的测量

真正要问的不是"辅助函数会不会降级",而是test-delta 真实写出的产物上,这个守卫能不能分清既有失败和 PR 自己造成的失败。所以我没有手写产物,而是把那个局面造出来:

  • packages/channels/base/src/sanitize.ts两棵树上做完全相同的破坏sanitize.test.ts 在 PR 侧和 merge base 上都红。
  • packages/channels/base/src/paths.ts 只在 PR 树上破坏paths.test.ts 只在那边红。

然后跑真实链路:qwen review capture-localqwen review build-test(真编译、真跑套件)→ qwen review test-delta(真的在已构建的 base 树上重跑失败命令)→ qwen review findings --test-delta

test-delta 自己测出来的结果:

netNew : ['src/paths.test.ts']
shared : ['src/ChannelBase.test.ts', 'src/sanitize.test.ts']

ChannelBase.test.ts 不是我植入的 —— 它在 macOS 上两棵树都天然是红的,等于白送一个本 PR 正要处理的样本。

两条 Critical 各指一个文件,分别过两个二进制:

finding 指控 merge base 构建 本 PR 构建
R1-1 sanitize.test.ts(测为 shared Critical Suggestion,带 heldByMeasurement
R1-2 paths.test.ts(测为 netNew Critical Critical —— 不动

第二行最关键:守卫不会因为一条真实破坏"住在被降级的那条隔壁"就把它一起压掉。

2. 同一个守卫,喂一份真实 /review 跑出来的产物

这台机器上还留着真实评审 #8351 时写下的 .qwen/tmp/qwen-review-pr-8351-test-delta.json。它的 shared 里有 src/config/config.test.ts,是在 packages/core 那条命令下测出来的 —— 而 config/config.test.ts 恰好是同时存在于 packages/cli/srcpackages/core/src 的那批路径之一。于是这份产物正好在没人为此准备过的数据上检验 workspace 限定这条主张:

finding 指控 结果
R1-1 packages/core/src/config/config.test.ts Suggestion —— 降级
R1-2 packages/cli/src/config/config.test.ts(同相对路径,另一个包) Critical —— 不动
R1-3 packages/core/src/core/logger.test.ts(只在 base 红,从不在 prFailingFiles 里) Critical —— 不动

3. 26 条边界断言,全部走已构建的 CLI

每一条都走 node dist/cli.js review findings,而不是导出的函数 —— 评审运行依赖的是接线。

覆盖:跨包同名冲突(两个方向)· 产物不存在(静默,exit 0)· 产物存在但解析不了(出声,exit 0,findings 照写)· 带 vitest project key 且无 workspace 可解析(拒绝并且披露)· 文件只出现在 suggestedFix · 文件就是 finding 的 location · SKILL 的两次调用在有无 --outcomes 下答案一致 · heldByMeasurement--input 回灌后存活 · 只有顶层 shared 没有 entries · 某处 netNew 压过别处 shared · 非 Critical 不受影响 · .tsx 不满足 .ts · 路径位于句末。

26 通过,0 失败。

4. 9 次变异,9 次被捕获

一次只破坏一条承重语句,然后跑套件。变异不打红任何用例,说明那条保证没有被任何用例锁住。

变异 打红
守卫失效 —— 永不降级 7 条
去掉路径边界 —— 纯子串匹配 3
去掉 workspace 限定 —— 裸后缀 3
回读时丢弃 heldByMeasurement 1
去掉"读不出的测量"的 try/catch 2
去掉 existsSync 判断 1
suggestedFix + locations 并入匹配文本 2
netNew 不再压过 shared 1
无法定位的路径放行而非拒绝 3

第一次变异同时打红 command-boundary 用例和单元用例,印证了描述里的说法:被锁住的是接线,不只是函数。

5. 套件、类型、lint

findings.test.ts 68 通过 · 整个 src/commands/review/48 文件 1521 通过 · npm run typecheck exit 0 · eslint 干净 · prettier 干净。这台机器上 review 这一面没有任何既有失败。


记录几点 —— 都不构成阻塞

  1. 测试计划里的数字过期了。 描述写的是「46 pass」「Seven new cases」;现在这个文件是 68 条,merge base 上是 38 条 —— 是 +30 而不是 +7。描述写完之后又落了 5 个 commit。建议刷新,因为测试计划正是评审者会照着重跑的东西。

  2. 「Six test paths … under BOTH packages/cli/src and packages/core/src —— 我在 f3e6e0385 上测到的是 5 个:config/config.test.tsutils/envVarResolver.test.tsutils/errors.test.tsutils/gitUtils.test.tsutils/memoryDiagnostics.test.ts。注释论证的内容完全成立,上面第 2 节还在真实数据上印证了它;只是数字差一。

  3. 版本错配是硬失败,不是降级。--test-delta 交给早于它的二进制会以 exit 1 结束,报 Unknown arguments: test-delta, testDelta,并且不写 findings 产物。SKILL.md 与 CLI 打在同一个 bundle 里同进同退,正常安装碰不到;只有 QWEN_CODE_CLI 指向比所用 skill 更旧的二进制时才会浮现。记下来,是因为「无条件传 --test-delta」让这层耦合变成了承重的。

  4. namesPath 左边界是"名字字符"边界,不是"路径段"边界。 shared 为 packages/cli/src/utils/errors.test.ts 时,写成 third_party/packages/cli/src/utils/errors.test.ts 的 finding 同样会命中(已实测,会被降级)。这看起来是刻意的:正是它让 ./ 前缀和仓库根前缀的写法能匹配上,而且本仓库不存在这种嵌套。只是记一下它与右边界(段级严格)的不对称。

  5. Tested on 表格可以加上 macOS —— 上面这些都是在 macOS 上跑的。

结论

PR 声称的行为,就是已构建 CLI 的真实行为 —— 包括在一份早于本改动、由真实评审写下的产物上。两个关键方向都正确:对着已经红了的测试的 Critical 被扣下并带上测量;对着 PR 真正弄坏的测试的 Critical 原样保留。失败模式的保守方向也是对的 —— 读不出、不存在、不完整、无法定位的测量都不会扣下任何东西,也不会拖垮 findings。未发现阻塞问题。从这一侧 LGTM,合并前唯一想做的只有第 1 条的描述刷新。

@wenshao
wenshao force-pushed the fix/hold-criticals-failing-on-base branch from b3ced09 to 403da1f Compare August 2, 2026 15:55
@wenshao
wenshao requested a review from Copilot August 2, 2026 15:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Aug 2, 2026

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)为单个提交。

wenshao added 8 commits August 3, 2026 00:09
`test-delta` reruns the PR side's failed test commands on the merge base and
splits the failures into the PR's own (`netNew`) and pre-existing (`shared`).
Nothing then read that split back. A Critical asserting "this PR breaks test X"
could name a file the same run had just measured as failing without the PR, and
the two artifacts never met.

Measured on #8368: `AuthDialog.test.tsx` came back `shared` in two independent
runs, and the merge base e967cc9 fails the very same test --
`drives API key provider steps from endpoint options metadata`. A Critical
reading "height-based pagination breaks the pre-existing test" was carried
across four rounds into the composed review anyway. It only escaped posting
because the PR's head had moved. The path rule this misattribution used to come
through was closed inside `test-delta`; the round ledger is the other door.

`findings --test-delta` now holds such a Critical back to Suggestion and names
the finding and the file on stderr. Downgrade, never drop: the measurement
contradicts the severity, not necessarily the observation, since a test can be
red for two reasons at once. The finding keeps its own evidence, gains the
measurement that demoted it, and stays in front of a human who can restore it
by naming which test fails for a new reason and quoting both sides.

Both `review findings` invocations in the skill pass the flag. The second one
rebuilds the artifact from the same input, so leaving it off there would have
restored every Critical the first had just held back.
…mmand

Two defects the review found, both real.

The docstring and the PR both promised that a test-delta artifact which will
not read holds nothing back and does not take the review down. That held for
`sharedFailingFilesOf`, which tolerates any parsed-but-unrecognized shape, and
not for the command around it: `readJson` throws on a missing file and on
invalid JSON, so those two exited non-zero -- the exact outcome the promise
ruled out. The junk-input test gave false confidence by calling the helper
directly and never going through the read, which is the same shape of hollow
assertion this pipeline keeps finding in its own work. The read is now caught,
says on stderr that no holds were applied and why, and the new cases drive it
through the command, where the guarantee actually lives.

`namesPath` checked the boundary before a match but not after, so a probe of
`src/a.test.ts` was satisfied by `src/a.test.tsx` -- both are preceded by `/`,
and the leading check cannot see the difference.
The guard matched `test-delta`'s paths as written. Two ways that was wrong,
both silent.

A per-workspace command prints paths relative to that workspace, so `shared`
holds `src/utils/errors.test.ts` with no package on it -- and six test paths in
this repo exist under both packages/cli/src and packages/core/src. A Critical
about core's copy could therefore be held by cli's copy being red: a real
finding demoted on a measurement that was never about it, which is the worse of
the two directions to get wrong. `failingFilesOf` keeps a project token in its
identity for exactly this reason; matching on a bare suffix discarded the
distinction the producer had preserved. Paths are now qualified from the
entry's own `--workspace=`, and a file measured net-new by any command is
dropped from the shared set even if another called it shared.

`failingFilesOf` also keys a file by its vitest project when the runner prints
one (`@qwen-code/qwen-code::src/x.test.ts`), which `test-delta.test.ts` pins.
No finding ever writes `::`, so a keyed entry could never match and the guard
no-opped on the one shape a real projects run emits -- with no stderr line,
because nothing was held and nothing failed to read. The key is stripped.

Also from the review: `suggestedFix` leaves the haystack, since naming a test
file as proposed work is not a claim that the file is red; a finding the fixer
recorded `fixed` is not held, because demoting it would contradict its own
ledger entry; and the sort doc comment goes back above `sortFindings`.

The mutation pass caught one more, in the trailing-boundary rule added last
round: a probe followed by `.` was rejected, so an ordinary sentence ending
"...in src/a.test.ts." stopped matching. A dot extends the name only when
something alphanumeric follows it.
Two gaps the efficacy probe found, both in the same place: the command's
stderr was written but never read back by a test.

Deleting the announcement loop left every test green, so a demotion could
have stopped being reported while still happening -- and an unannounced
demotion reads as the reviewer's own judgement, which is the one thing the
measurement is not. And nothing distinguished "the flag was not passed" from
"the guard ran and its read failed": both leave severities untouched, so
forcing the guard true survived, with the throw from reading `undefined`
landing in the catch that produces the same no-op.

Both tests capture stderr through the handler. They redden on deleting the
loop, on dropping the id and file from its message, and on the `if (true)`
mutant the probe reported.
Four from review, and the first is the cross-project collapse arriving by the
door the last round left open.

`repoRelative` stripped a `project::` key and re-qualified from
`--workspace=`, and the comment presented those as one mechanism. They are
mutually exclusive: a key comes from a runner printing a project tag, and
neither vitest config here names a project, so a `--workspace=` command never
carries one. A keyed path therefore always arrived unqualifiable and degraded
to a bare project-relative path -- which matches as a suffix of ANY directory,
suppressing a real Critical about another project's copy. The test meant to pin
this paired a key with a workspace command, a combination that cannot occur,
so it passed while the real shape did not. Such a path is now refused and named
on stderr: a measurement whose subject cannot be established licenses nothing,
and a missed hold costs less than a demoted Critical.

The `outcome: 'fixed'` exemption is gone. The skill runs this command twice
over one input, and the exemption made run 2 answer Critical where run 1
answered Suggestion -- one finding at two severities inside one review, which
this file's header names as the failure it exists to prevent, and silent
re-promotion is worse than the oddity it was added to avoid. The measurement
says the base was already red; the outcome says the tree was edited. Different
claims, both kept.

A hold is now a field, `heldByMeasurement`, with a `counts.held` beside it --
prose alone is invisible to the round ledger this PR exists to close, and
`test-delta` makes the same argument about its own budget skips.

A measurement file that is absent is no longer an alarm. `test-delta` runs only
when a test command failed and a base tree built, so on a green review it does
not exist and the loud line fired on the normal path. A file that exists and
will not parse still speaks.
… them

The hold landed downstream of the thing it exists to correct. In the skill's
order `compose-review` ran first, so a Critical held back afterwards reached
only the Step 8 report: the verdict line, the drafted `**[Critical]**` marker
and the payload `submit` recounts were all fixed before the measurement was
consulted. That is the exact path the #8368 misattribution took into a composed
review, and this change had not closed it. The findings artifact is now written
before the verdict, and a hold arriving later is named as the comment-set
change it is.

`heldByMeasurement` did not survive `--input`. `validateFindings` builds from a
whitelist and never copied it, so the field a later round was supposed to read
lasted exactly one command and `counts.held` fell back to zero -- the same
invariant `outcomeNote` was added a few lines above to satisfy.

`locations[].file` left the haystack, for a sharper version of the reason
`suggestedFix` did. A finding ABOUT a test's content carries that test as its
location, and a PR touching an already-red test is precisely when such a
finding is written; demoting it uses the measurement against a claim the
measurement does not address.

The no-`entries` fallback is gone. It qualified nothing, so it put back the
bare workspace-relative path that matches inside any package -- the collapse
`repoRelative` exists to stop, through the one door left open. And only a
`shared` path is reported as set aside: a `netNew` path was never eligible to
hold anything back, so calling it ignored coverage was noise on the very shape
that produces most keyed entries.
…holds

Three rounds of self-review over the diff.

A finding a later round re-files as Critical was held again and gained a
second, identical explanation -- two paragraphs under one finding read as two
measurements, and the round ledger carrying a held finding forward is exactly
the path the structured field was added for. `heldByMeasurement` round-trips
now, so the state to decide this on is already there: lower it again, append
nothing.

Moving this section ahead of the verdict was necessary and not sufficient.
`compose-review` reads `comments.json` and `compose.json`, both hand-written,
so a severity lowered here still ships as `**[Critical]**` if the marker was
copied from the draft rather than the artifact. The skill now says to read
`severity` out of `findings.json` for every marker and body Critical, which is
what actually closes the path #8368 took.

And two of its own claims were wrong: "the blocks above already do" named one
block with the other still below it in Step 6B, and "Six test paths ... exist
under BOTH packages" is five -- a number carried over from a review comment
without being counted, in a change about not stating what nothing checked.
…tching

The escape the report offers -- "say which test fails for a NEW reason" --
names the test file, and naming the test file IS the match condition, so a
Critical re-filed after reading the measurement was demoted again and the
promised door could not be opened at all. A finding that already carries
`heldByMeasurement` for the same file is now left where it was put, and the
decision this command declined to overrule is announced like the ones it makes.
The paragraph also stopped stacking, one copy per round.

`namesPath` treated `/` as a leading boundary, so a repo-relative probe matched
at any depth: `third_party/packages/cli/src/a.test.ts` demoted a Critical about
`packages/cli/src/a.test.ts`. The trailing side already required both ends;
this is the same rule on the side that was left open. The helper's fixtures
were bare workspace-relative paths, which is not what it is handed --
`sharedFailingFilesOf` qualifies every probe before this runs -- so they are
repo-relative now and the boundary cases say what they test.

And the JSDoc still described the top-level `shared` as "the fallback for a
partial artifact" after the fallback was removed; it is never honoured.
@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@wenshao
wenshao force-pushed the fix/hold-criticals-failing-on-base branch from 403da1f to f04f847 Compare August 2, 2026 16:11
@wenshao
wenshao requested a review from Copilot August 2, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

⚠️ Downgraded from Approve to Comment: CI failing: Post Coverage Comment (ubuntu-latest, 22.x), review-pr, Test (ubuntu-latest, Node 22.x). Reviewed.

— qwen3.7-max via Qwen Code /review

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Sandboxed verification: ❌ not passed — findings reported (agent verdict) - workflow run

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

Scripted assertions: 70 passed · 0 failed · 70 total

中文 — 判定:❌ 不通过 · 报告了发现(agent 判定)

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

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

Verification report

Verify — PR #8380 fix(review): hold a Critical the base tree already fails

Verdict: findings — assertions 70 pass / 0 fail / 70 total (mock-free harness); verified head f04f8479c29a6ee44b75a2c3737185bac0c150ec (base 783787c8ad2f4279f7e02e2ef0eff6bbe834cb3d). The central claim is proven load-bearing and correct: against identical input the PR build demotes the misattributed Critical to Suggestion while the pre-PR build leaves it Critical (01-ab-central-head-vs-base.png). The findings verdict is not a defect in that claim — every executed assertion passed and no regression reproduced — but one non-blocking, safe-direction observation the sibling-sweep surfaced: the hold silently no-ops when a reviewer names the red test in the form vitest actually prints (workspace-relative / bare basename), and the skill never documents that the match needs the repo-relative path. Details and the measured bound are in Finding 1.

中文摘要

结论:findings(70 条脚本断言全过,0 失败;已验证 head f04f8479c)。

  • 中心主张已证 load-bearing 且正确:同一份输入,PR 构建把那条误判的 Critical 降为 Suggestion(heldByMeasurement 写入、counts.held=1、stderr 播报),而 PR 之前的构建原样保留为 Critical、无任何 hold 行。见 A/B 表与 01-ab-central-head-vs-base.png
  • 变异矩阵 0 幸存:5 个新守卫各被精确打红自己的用例(M1 永不降级打红 8 条,含 command-boundary 接线用例,作为正对照证明 harness 是活的;M2 边界 2、M3 读不出 2、M4 重提豁免 1、M5 stderr 播报 1)。见 03-mutation-matrix-no-survivors.png
  • 门控findings.test.ts 77/77;兄弟 test-delta.test.ts 27/27、compose-review.test.ts 151/151 全绿。
  • 唯一 finding(Suggestion,安全方向):hold 只在 finding 文本以仓库相对路径点名红测试时才命中;若按 vitest 实际打印的工作区相对路径裸文件名写,hold 静默不触发——而 SKILL.md 从未写明"必须写仓库相对路径"这一契约。方向是欠扣(该降没降,Critical 仍送达人类,比误降安全)。已测修复空间:16 个测试 basename 在 cli/core 两包重名,任何"放宽匹配"的纯字符串修法都会重新打开本 PR 刚堵上的跨包误降。故唯一安全缓解是文档,而非改 matcher。见 Finding 1 与 04-sibling-sweep-path-forms.png
  • 未覆盖:见 Not covered 表。

数字以正文各表为准,此处不重复。

Central claim + A/B

Central claim. When --test-delta records that a test a Critical blames the PR for was already failing on the merge base (shared), the findings command lowers that Critical to Suggestion, records the demotion as a structured field (heldByMeasurement) plus counts.held, appends the measurement to failureScenario, and announces the finding + file on stderr — never dropping, never raising.

A/B control. Base arm = faithful esbuild type-strip transpile of the base findings.ts (HEAD^1, zero mentions of test-delta/holdCriticals/heldByMeasurement, handler destructures no testDelta); head arm = the PR's compiled dist. Both modules are self-contained (imports only node:fs, node:path, and an import-free stdioHelpers.js; grep -c qwen-code-core == 0), so the internal-workspace-symlink confound cannot reach the unit under test — the core symlink's realpath (packages/core, the head tree) is quoted here only to record that the check was made and is moot. The harness drives the real command handler in a child node process per cell (real fs reads/writes, real stderr capture — no stub of the unit).

cell input observable oracle result
head / S01 Critical naming packages/cli/src/ui/auth/AuthDialog.test.tsx; entries[0].shared=[src/ui/auth/AuthDialog.test.tsx] severity, heldByMeasurement.file, counts.held, stderr hold line Suggestion, packages/cli/src/ui/auth/AuthDialog.test.tsx, 1, R1-1 held back from Critical — …
base / S01 identical input same oracle Critical, no field, 0, no hold line

Witness: 01-ab-central-head-vs-base.png (the two cells side by side, colour-coded). The pair separates exactly as the claim predicts — the demotion is the change under test, not noise. Full 18-scenario matrix (head + base cells): 02-harness-matrix-70-assertions.png.

The matrix also pins every matching rule the PR introduced, each as its own scripted cell (head arm): netNew never holds (S02); locations[].file is not the haystack (S03); non-Critical untouched (S04); .tsx not matched by a .ts probe (S05); vendored copy under third_party/ not matched — leading / is not a boundary (S06); a cli-shared does not hold a core finding (S07); a sentence-ending . still matches (S08); .snap extends the name, not matched (S09); a project:: key with no --workspace= is refused and named on stderr (S10); a file measured netNew anywhere is dropped from shared (S11); a top-level shared with no entries is not honoured (S12); junk JSON does not throw and says no holds applied + why (S13); a missing file is quiet, not alarmed (S14); a re-filed Critical that already carries the measurement is left at Critical, announced as left at Critical, paragraph does not stack (S15); heldByMeasurement round-trips through --input and counts.held reads it back (S16); junk shapes (string, non-array entries) tolerated (S17/S18).

Corrections

  • Test count in the PR body is stale, not a code defect. The body's Reviewer Test Plan says "69 pass" and "2 failed | 44 passed (46)" for the mutations. At the verified head the suite is 77 tests, all passing (the count grew across the 8 commits as cases were added), and the mutation counts I measured are M1 = 8 failed / 69 passed, M2 = 2/75, M3 = 2/75, M4 = 1/76, M5 = 1/76 (see the matrix below). The body's numbers describe an earlier commit in the same branch; the behaviour they describe (each mutation reddens only its own test, the command-boundary case included) still holds and is re-confirmed here. This is a description staleness, not a request to change code.

Findings

F1 (Suggestion, safe direction) — the hold matches only the repo-relative prose form; the form vitest prints silently no-ops, and the skill never documents the contract

What the sibling-sweep found. The hold's match condition is a substring test of the repo-relative qualified shared path against the finding's summary+failureScenario (namesPath, path-boundary on both ends). The producer qualifies test-delta's workspace-relative paths to repo-relative, so the shared set is always repo-relative — but the finding prose is whatever the reviewing agent wrote. The PR's own unit fixtures write the repo-relative form in failureScenario (the test comment at findings.test.ts:760-761 states the contract: "test-delta writes workspace-relative paths, while a finding names the repo-relative one"), so the suite is green by construction on the one form it tests. Driving the real compiled matcher with the other realistic prose forms gives:

prose path form (in failureScenario) severity after hold held
packages/cli/src/ui/auth/AuthDialog.test.tsx … (repo-relative — the contract) Suggestion 1
src/ui/auth/AuthDialog.test.tsx … (workspace-relative — as vitest prints it) Critical 0
AuthDialog.test.tsx … (bare basename) Critical 0
./src/ui/auth/AuthDialog.test.tsx … Critical 0

Witness: 04-sibling-sweep-path-forms.png; raw run logs/probe-pathforms.txt.

So a reviewer who transcribes the failing test straight from the vitest run they are looking at — FAIL src/ui/auth/AuthDialog.test.tsx, or just the file's basename — produces a Critical that the measurement would have held, but the matcher never sees, and (correctly, given its design) says nothing on stderr. The misattribution this PR exists to close survives on that input shape.

Direction is safe (under-hold, not over-hold). A missed hold leaves the finding at Critical, still in front of a human — the expensive error (demoting a real Critical on a measurement that was never about it) does not occur. This is the same asymmetry the PR itself engineered on the other side, and it is the right one. So this is a Suggestion, not a blocker, and it does not touch the proven-correct central claim.

Why no code fix is safe here — the bound, measured. The natural fix is "also match the basename / the workspace-relative suffix." I measured why that reopens the door this PR spent three commits shutting. The cross-workspace test (findings.test.ts:1011, "does not hold a Critical about the OTHER workspace of the same path") pins, with shared = ['packages/cli/src/utils/errors.test.ts'], that a Critical naming packages/core/src/utils/errors.test.ts must stay Critical while the cli-path one demotes. Those two prose paths share (a) the basename errors.test.ts and (b) the suffix src/utils/errors.test.ts on a / boundary. So:

  • a basename match collapses on every duplicated name;
  • a suffix match broad enough to admit the workspace-relative form src/utils/errors.test.ts also matches the core prose path's identical trailing src/utils/errors.test.ts, collapsing the same way.

And the duplication is not a corner case — I counted 16 test basenames present under both packages/cli/src and packages/core/src (errors.test.ts, config.test.ts, paths.test.ts, settings.test.ts, index.test.ts, …; full list in logs/path-basename-collisions.txt). No string-only broadening of namesPath closes the under-hold without re-admitting the cross-project over-hold. The matcher's repo-relative requirement is therefore load-bearing for correctness, not an oversight — which is exactly why the gap is a documentation gap rather than a code bug.

Measured-safe mitigation (documentation only — no matcher change)

The fix that does not touch the correctness invariant is to make the contract explicit where the reviewing agent reads it: in the bundled review SKILL.md, in the new "The findings, as data" section, state that when a finding names a red test in summary/failureScenario, write the repo-relative path (e.g. packages/cli/src/ui/auth/AuthDialog.test.tsx), because that is the form --test-delta's hold matches against, and the workspace-relative / basename form vitest prints will not be held. One sentence closes the only door left open without weakening the cross-workspace guard.

This is a doc change, so it has no matcher surface to drive: its verification is that the matcher's behaviour is unchanged — re-running the 70-assertion harness and the 77-test suite after such an edit stays green (the matcher code is untouched), and the gap is closed by the instruction reaching the agent, not by code. I did not implement it in this round (the verify job does not edit the PR); I report it as the measured-safe path. The alternative — consumer-side normalization of the prose to repo-relative — is the thing the cross-workspace test forbids, and I measured that bound above, so I do not recommend it.

Not covered

  • Per-commit attribution. The checkout is depth 2 (only the merge commit, HEAD^1, HEAD^2 are reachable; git rev-list HEAD^1..HEAD^2 returns the single head commit, not the 8 in the metadata). I verified the aggregate HEAD^1..HEAD diff and exercised it as a whole; I did not attribute behaviour to individual commits.
  • The end-to-end /review skill run (the agent writing the findings JSON, then this command consuming it). I drove the compiled command handler directly over synthesized artifacts whose shape I validated against the real producer (test-delta.ts DeltaEntry { command, shared, netNew }, npm test --workspace="<dir>" commands, project::path keying, workspace-relative paths). This reproduces the command's handling of every artifact shape the producer emits; it does not reproduce the agent-side choice of which path form to write into the prose — which is precisely the gap in F1.
  • The packages/core failure the PR body names (skill-curator.test.ts > reports skippedErrors when rename fails transiently) did not reproduce in this environment: it passed 36/36 on both head and base. The body describes it as transient/timing-sensitive and unrelated to this diff (which touches packages/core only in the SKILL.md markdown), and that is consistent with what I measured — but I cannot confirm the failure on a clean tree from here, only that it is absent on both arms and outside the diff's surface.
  • Windows / macOS path handling in namesPath/repoRelative (the producer strips ANSI and handles C:\ paths in failingFilesOf, but the consumer's boundary class is POSIX-oriented). Not exercised; the verify lane is Linux.
  • Real compose-review consuming a held severity end-to-end. I ran compose-review.test.ts (151/151 green) as a regression gate and confirmed the SKILL.md now instructs drafting markers from findings.json's severity, but I did not stand up a full compose run over a held artifact.

Methodology

Environment: the CI verify container (node v22.23.2, no zstd, no GitHub token), merge-ref checkout (HEAD = merge, HEAD^1 = base 783787c8a, HEAD^2 = head f04f8479c). The head tree was already built (packages/cli/dist/src/commands/review/findings.js); I did not redo npm ci/npm run build. The base control is a faithful esbuild type-strip transpile of the base findings.ts + stdioHelpers.ts into base-dist/ (no logic rewrite), confirmed to contain zero testDelta references and the same self-contained import surface as head. Every harness cell spawns a child node process that imports the compiled module and calls the real findingsCommand.handler over fixture files on disk, capturing its exit code, stdout, and stderr — no stub of the unit under test. The mutation matrix (mutate.mjs) edits the head source one guard at a time, runs the PR's own vitest suite, records the reddened test names (extracted by vitest's × marker), and restores via git checkout after each (verified clean). Targeted gates ran the affected workspace's vitest only (findings.test.ts, plus siblings test-delta.test.ts and compose-review.test.ts, plus the named core test on both arms). Evidence PNGs were rasterised from live command output via scripts/verify-capture.mjs (@xterm/headless + sharp, no browser). Raw per-cell logs, per-mutation vitest output, and the harness row data live under logs/; harness scripts (harness.mjs, run-cell.mjs, ab-central.mjs, mutate.mjs, probe-pathforms.mjs) are in the artifact dir for re-run.

Evidence images

01-ab-central-head-vs-base

02-harness-matrix-70-assertions

03-mutation-matrix-no-survivors

04-sibling-sweep-path-forms

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 f04f8479c29a6ee44b75a2c3737185bac0c150ec — 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.

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

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

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

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM — sound design. The downgrade-only invariant is correct (measurement contradicts severity, not necessarily the observation), the boundary matching in namesPath is careful (leading / exclusion, trailing extension check, sentence-ending dot handling), cross-workspace qualification closes the suffix-collapse risk, and error handling is exactly right (missing file → silent, corrupt → loud, unrecognized shape → empty). The readjudication escape hatch works and is tested.

Non-blocking:

  1. (P2) counts.held conflates readjudicated findings (Critical + stale heldByMeasurement) with actual holds — filter to severity !== 'Critical' or subtract readjudicated.length so the count matches the prose
  2. (P2) WORKSPACE_IN_COMMAND_RE only matches double-quoted workspace values — broaden to handle unquoted/single-quoted, or add a test asserting the expected format so a producer change breaks loudly
  3. (P3) sharedFailingFiles.find() records only the first matching shared file — document that first-match is intentional, or record all matched files

@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 2, 2026
Merged via the queue into main with commit e1e5b42 Aug 2, 2026
56 of 57 checks passed
@wenshao
wenshao deleted the fix/hold-criticals-failing-on-base branch August 2, 2026 16:30
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.4.

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