Skip to content

fix(review): read why the collocated test was not green, do not assert it - #8374

Merged
wenshao merged 7 commits into
mainfrom
fix/efficacy-baseline-reason
Aug 2, 2026
Merged

fix(review): read why the collocated test was not green, do not assert it#8374
wenshao merged 7 commits into
mainfrom
fix/efficacy-baseline-reason

Conversation

@wenshao

@wenshao wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

When a mutant or hunk is set aside because the test collocated with the code it touches was not green to begin with, the report now says which of the two things went wrong — the test ran and failed, or it never produced any tests at all — instead of naming one of them as though it had been measured. Both places that make this judgement now produce their sentence through a single function that reads the answer off the baseline run it already has.

Why it's needed

Setting the mutant aside is right: when the one test most likely to catch a change never ran green, the other tests passing shows only that they do not cover it, not that nothing does. What did not hold up was the explanation attached to it — every such case was reported as likely a compile or import error in the probe tree, a cause nothing had checked.

The two ways a probe is not green are different failures with different fixes, and telling them apart is the whole value of the message. Measured on #8368: AuthDialog.test.tsx compiled fine, collected 26 tests and failed exactly one, and all three mutants in its source carried the import-error wording — sending a reader after a problem that was never there. The baseline had already classified that file gated, meaning a real assertion failure, rather than inconclusive, meaning it collected nothing. The information was sitting one lookup away and neither guard used it.

Reviewer Test Plan

How to verify

npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts128 pass, plus 28 in the integration suite. The new cases split in two: five assert that classifyProbeRun emits the right reason for each way a probe fails to be green (and none for a decided verdict), and the rest assert the sentence each reason produces, the not-measured default, and the shared hold decision both loops now call.

That the tests are load-bearing is the part worth confirming. Restoring the old flat wording reddens eight cases and nothing else:

Tests  8 failed | 116 passed (124)

Deleting a single reason tag is now caught twice — once by tsc, because ProbeResult's inconclusive arm requires one, and once by the assertion on that branch:

$ # delete `reason: 'no-tests' as const,` from classifyProbeRun
tsc: 1 error
× classifyProbeRun > tags a file that collected nothing as no-tests
Tests  1 failed | 123 passed (124)

The behaviour under discussion came from running /review against #8368 on two binaries, one predating #8345 and one after it. The guard from #8345 fired correctly on the second run; its explanation is what this PR replaces. Its input, measured directly:

$ npx vitest run src/ui/auth/AuthDialog.test.tsx
Test Files  1 failed (1)
     Tests  1 failed | 25 passed (26)

Evidence (Before & After)

N/A — the change is to a string inside a JSON report, not to anything a user sees.

Tested on

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

Environment (optional)

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

Risk & Scope

  • Main risk or tradeoff: ProbeResult becomes a discriminated union, so reason is no longer readable without narrowing on verdict. That is the point — an untagged inconclusive was invisible before, and the two explanation helpers take a narrower ProbeOutcome because a union does not survive Pick.
  • Report schema: probed serialises ProbeResult, so every inconclusive probe entry in the artifact now carries a reason key. Additive, and a consumer can act on it where it cannot act on prose. Two conventions live in the artifact and only one is new: mutants.probed and hunks.probed entries stay untagged, because a mutant's inconclusive answers a different question — why the candidate was not scored (budget, cap, control, the collocated-test hold) — whose answers do not overlap ProbeReason.
  • Not validated / out of scope: which mutants and hunks are held inconclusive does not change — that rule is fix(review): a mutant whose own test was red is not a survivor either #8345's and the condition is unchanged. Only the explanation moves.
  • One default is unreachable through the pipeline and is labelled as such rather than counted as covered: the not-measured wording, since every probe own is drawn from is one classifyProbeRun mapped over. Its test pins a hand-built caller, not a path a run can take. The untagged-inconclusive wording is gone — a distributive omit keeps ProbeResult's discrimination through ProbeOutcome, so the case cannot be constructed.
  • Breaking changes / migration notes: none. detail is prose for a human; nothing parses it.

Linked Issues

None. Found while dogfooding /review against #8368.

中文说明

这个 PR 做了什么

当一个 mutant 或 hunk 因为「与被改代码同处一处的测试本来就不绿」而被搁置时,报告现在会说明是两种情况中的哪一种 —— 测试跑了但失败,还是它压根没产出任何测试 —— 而不是把其中一种当作已经测量过的事实说出来。做这个判断的两个地方,现在都通过同一个函数生成那句话,该函数从它手上已有的基线运行结果里读出答案。

为什么需要

搁置这个 mutant 本身是对的:当最可能捕获该改动的那个测试从一开始就没绿过,其余测试通过只能说明它们没覆盖到,不能说明没有任何测试覆盖。站不住的是附在结论上的解释 —— 所有这类情形一律被报告为 likely a compile or import error in the probe tree,而这个原因没有任何环节核实过。

探针不绿的两种方式是不同的故障、需要不同的修法,而分辨它们正是这条消息的全部价值所在。在 #8368 上实测:AuthDialog.test.tsx 编译正常、收集到 26 个测试、恰好失败 1 个,而其源文件里三个 mutant 全部带着「编译或导入错误」的措辞 —— 让读者去找一个根本不存在的问题。基线其实早已把该文件判为 gated,即真实的断言失败,而不是 inconclusive,即什么都没收集到。答案就在一次查表之外,两处 guard 都没有去用。

评审者测试计划

如何验证

npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts —— 128 条通过,另有集成测试 28 条。新用例分为两类:五条断言 classifyProbeRun 针对每一种「探针未变绿」的方式发出正确的 reason(并且对已判定的 verdict 不带 reason);其余断言每个 reason 产出的句子、「未被测量」这一默认值,以及两个循环现在共同调用的那个 hold 决策。

更值得确认的是这些测试确实承重:把旧的写死措辞恢复回去会让 8 条转红、其余不受影响(8 failed | 113 passed)。而删掉任意一个 reason 标记现在会被拦两次 —— 一次是 tsc,因为 ProbeResultinconclusive 分支要求它;一次是该分支上的断言。

上述行为来自对 #8368 用两个二进制各跑一轮 /review,一个早于 #8345、一个在其之后。#8345 的 guard 在第二轮正确触发;本 PR 替换的是它给出的解释。它的输入实测为该测试文件 26 条中失败 1 条。

证据(前后对比)

N/A —— 本次改动落在一个 JSON 报告内部的字符串上,用户看不到任何界面变化。

测试环境

见上表:仅在 Linux 上验证。

运行环境(可选)

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

风险与影响范围

  • 主要风险或权衡:ProbeResult 改为判别联合,因此不先按 verdict 窄化就读不到 reason。这正是要点 —— 此前「未打标记的 inconclusive」是不可见的;两个解释助手改用更窄的 ProbeOutcome,因为联合类型无法通过 Pick
  • 报告结构:probed 序列化 ProbeResult,因此产物中每个 inconclusive 的探针条目现在都带有 reason 键。这是增量的,且消费方可以据此行动,而散文无法被据以行动。产物中存在两种约定,新增的只有一种:mutants.probedhunks.probed 的条目保持不带标记,因为 mutant 的 inconclusive 回答的是另一个问题 —— 该候选为何未被评分(预算、上限、对照、collocated 测试的 hold)—— 其答案与 ProbeReason 毫无交集。
  • 未验证 / 不在范围内:哪些 mutant 与 hunk 被判为 inconclusive 并未改变 —— 那条规则属于 fix(review): a mutant whose own test was red is not a survivor either #8345,判定条件原样未动,改变的只有解释。
  • 有一个默认值在真实流水线中不可达,已如实标注而非计入覆盖:「未被测量」措辞,因为 own 所来自的每个探针都在 classifyProbeRun 遍历过的列表里;其测试锁定的是手工构造的调用方,而非某次运行可以走到的路径。「未打标记的 inconclusive」措辞已被删除 —— 分布式 omit 让 ProbeResult 的判别性穿过 ProbeOutcome,该情形无法被构造出来。
  • 破坏性变更 / 迁移说明:无。detail 是给人读的散文,没有任何代码解析它。

关联 Issue

无。发现于对 #8368/review dogfooding。

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

Thanks for the PR, @wenshao — the fix itself looks well-motivated, but the PR body does not follow the PR template. The required sections (What this PR does, Why it is needed, Reviewer Test Plan with How to verify / Evidence / Tested on, Risk & Scope, Linked Issues) are all missing.

Could you restructure the body using the template? The content you have written maps naturally onto the sections — the problem description fits Why it is needed, the verification output fits How to verify, and so on.

中文说明

感谢贡献,@wenshao!修复本身的动机很清晰,但 PR 正文没有按照 PR 模板 填写。缺少所有必需的章节(What this PR does、Why it is needed、Reviewer Test Plan(含 How to verify / Evidence / Tested on)、Risk & Scope、Linked Issues)。

能否按模板重新组织正文?你已经写好的内容可以很自然地对应到各个章节——问题描述对应 Why it is needed,验证输出对应 How to verify,以此类推。

Qwen Code · qwen3.8-max-preview

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.56% 83.56% 89.38% 82.74%
Core 87.62% 87.62% 89.21% 86.24%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.56 |    82.74 |   89.38 |   83.56 |                   
 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.04 |    72.41 |   64.51 |   89.04 |                   
  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.46 |      100 |      50 |   98.46 | 76                
  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.64 |    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.33 |   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 |   86.07 |    87.09 |   87.03 |   86.07 |                   
  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      |   86.73 |    83.53 |   92.85 |   86.73 | ...12-531,563-564 
  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.36 |     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 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  run.ts           |   81.14 |    86.17 |    90.9 |   81.14 | ...13,429-477,490 
  script-lint.ts   |   83.67 |    78.41 |   88.88 |   83.67 | ...59-773,775-797 
  submit.ts        |   77.59 |    82.05 |   81.81 |   77.59 | ...20-656,658-659 
  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.09 |    93.63 |   96.02 |   96.09 |                   
  agent-briefs.ts  |    98.8 |      100 |       0 |    98.8 | 653-654           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  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.6 |    88.37 |   71.42 |    85.6 | ...20,257-258,285 
  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.87 |     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.05 |   95.23 |   98.07 |                   
  ...putAdapter.ts |   97.98 |     93.2 |   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.12 |    83.38 |   90.83 |   87.12 |                   
  ...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 |   85.85 |    91.78 |   95.83 |   85.85 | ...94-206,366-369 
  ...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 |    88.57 |     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.14 |     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.45 |     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.44 |   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.71 |     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.17 |    65.9 |    72.7 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   73.91 |    72.03 |   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.45 |   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.29 |     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.94 |   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.86 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |   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.37 |    86.98 |   92.54 |   81.37 |                   
  ...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.72 |     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 |   86.32 |    76.05 |     100 |   86.32 | ...02-303,331-341 
  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.62 |    86.24 |   89.21 |   87.62 |                   
 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.04 |    88.37 |   93.25 |   92.04 |                   
  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    |   92.88 |    89.63 |   96.11 |   92.88 | ...4636,4684-4685 
  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.66 |     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.38 |   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 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.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.45 |    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 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.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.27 |   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.07 |   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.57 |    84.35 |   96.84 |   89.57 |                   
  ...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.81 |    74.08 |    97.5 |   82.81 | ...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.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.55 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.55 |     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.53 |      70 |   74.17 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.17 |    80.35 |   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.36 |     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 commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Restructured onto the template — What this PR does / Why it's needed / Reviewer Test Plan (How to verify, Evidence, Tested on, Environment) / Risk & Scope / Linked Issues, with the Chinese fold translating each section.

The verification section now leads with the part that matters: reverting the fix to the old flat wording reddens exactly the four new cases and nothing else, so the tests are load-bearing rather than decorative.

中文说明

已按模板重排 —— What this PR does / Why it's needed / Reviewer Test Plan(含 How to verify、Evidence、Tested on、Environment)/ Risk & Scope / Linked Issues,中文折叠逐节对译。

验证一节现在把最要紧的部分放在前面:把修复回退为原先写死的措辞后,恰好那四条新用例转红、其余不受影响,说明这些测试是承重的,而不是装饰性的。

…t it

A mutant or hunk whose own collocated test was not green in the unmutated
baseline is held `inconclusive` -- correctly, since the other probes passing
shows only that THEY do not cover it. But both guards then named a cause they
had not measured: "likely a compile or import error in the probe tree".

There are two ways a probe is not green and they are different failures with
different fixes. Measured on PR #8368: `AuthDialog.test.tsx` compiled fine,
collected 26 tests and failed exactly one, and all three mutants in its source
were held with the import-error wording -- sending a reader after a problem
that was never there. The baseline had already classified it `gated` (a real
assertion failure) rather than `inconclusive` (collected nothing); the guards
just did not look.

Both now build their detail from one exported function that reads the verdict
off the baseline, so the two sentences cannot drift apart again and what the
tests pin is the string the report carries. A probe with no baseline entry
takes the collected-nothing wording: absent is an evidentiary hole, never the
claim that its tests failed.
@wenshao
wenshao force-pushed the fix/efficacy-baseline-reason branch from b7d8ba4 to 7908854 Compare August 2, 2026 10:07
@wenshao
wenshao requested a review from Copilot August 2, 2026 10:07

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

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 27 passed · 0 failed · 27 total

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

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

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

Verification report

PR #8374 — Deep Verification

Verdict: merge-ready — 27/27 scripted assertions passed (A/B 16, mutation matrix 11), 0 fail. Collocated suite 110/110 at head. ESLint clean on both changed files (gate proven live). No blocking findings.
Verified head: 7908854077b09a301d1503433c4d745aadcb54ed (HEAD^2); base tip: 437975547407645c69ec29ad3e5845f2073c857f (HEAD^1). First round (no previous-report.md).

中文摘要
  • 结论merge-ready。全部脚本化断言通过(计数见下方 A/B 表与变异矩阵表),无阻塞性问题。
  • A/B 结论:中心改动承重。对基线判为 gated(测试跑了且失败)的探针,措辞从 base 一律的「compile or import error」翻转为 head 的「it was RED there」;对 inconclusive 与「基线无条目」两种情形则给出「collected no tests there」措辞。base 措辞对判定完全盲(无判定入参,arity 2),head 随判定变化。查表键在生产中确实匹配(见下)。
  • findings:无阻塞项。仅一条非阻塞的覆盖性观察(变异 M4 存活:collected-nothing 句尾括号注释未被任何测试锁定;承重分支 gated→RED 已被 test 4 的 .toBe 完整锁定)。
  • 未覆盖范围:未端到端跑真实 /review(作者已在 feat(auth): add Kimi and Xiaomi MiMo providers #8368 上跑过两轮);仅在 Linux 验证;未跑全仓测试/全仓 typecheck(只跑受影响文件的套件与定向 ESLint)。

Central claim + A/B

Central claim. When a mutant/hunk is held inconclusive because its collocated test was not green in the unmutated baseline, the report's detail now reads the reason off the baseline run — gated ⇒ "it was RED there", otherwise ⇒ "it collected no tests there (…)" — via one shared exported function collocatedNotGreenDetail, instead of flatly asserting "likely a compile or import error in the probe tree" for every case.

The load-bearing risk for a lookup-based fix is whether the lookup key matches in production. It does, proven two ways:

  1. By construction (code read). classifyProbeRun returns probes.map((file) => ({ file, … })) — the file field is the exact probe string passed in (the absolute vitest testResults[].name is used only internally to find the matching result). collocatedProbe(c.file, probes) returns an element of that same probes array via .find. So own and perFile[].file are byte-identical strings. The pre-existing fix(review): a mutant whose own test was red is not a survivor either #8345 gate greenProbes.includes(own) (where greenProbes = baseline.perFile.filter(r => r.verdict === 'inert').map(r => r.file)) already relies on this exact equality and is the established working behaviour — the new .find((p) => p.file === probe) reuses the same match.
  2. Behaviourally. The A/B harness builds perFile in the production shape (file = repo-relative probe string) and the gated branch fires.

Secondary claims, verified: both call sites converted (mutant notGreen('mutant', own), hunk notGreen('hunk', own); the only surviving old wording is inside the new function's collected-nothing branch — no third site); a probe with no baseline entry takes the collected-nothing wording; and the selection of which probes are held inconclusive is provably unchanged — the guard predicate if (own && !greenProbes.includes(own)) is byte-identical to base (no +/- line touches it), only the detail: expression changed.

cell oracle base (HEAD^1 literal) head (collocatedNotGreenDetail from dist)
gated probe (ran, failed 1 — the #8368 AuthDialog.test.tsx shape) reason wording "…(likely a compile or import error in the probe tree)…" ❌ wrong "…it was RED there…" ✅
inconclusive probe (collected nothing) reason wording "…compile or import error…" "…collected no tests there…"
absent probe (no baseline entry) reason wording "…compile or import error…" "…collected no tests there…"
verdict sensitivity (same probe, vary verdict) output varies? no — arity 2, no verdict input (verdict-blind by construction) yesgated ≠ inconclusive; absent == inconclusive
exact gated-mutant sentence .toBe(…) n/a matches the test's expected string exactly

16/16 A/B assertions passed. The gated case flips base→head; base is verdict-blind, head is verdict-sensitive. Witness: 01-ab-gated-flips-base-vs-head.png.

The base cell is the verbatim inline literal extracted from HEAD^1 (git show HEAD^1:…test-efficacy.ts, lines 2022/2067), reconstructed as a function of own. At base the wording is a static template inside runTestEfficacy, not reachable as a callable unit; the literal is the whole base behaviour and is invariant by construction (one ${own} interpolation, no verdict input).

Vacuity / mutation matrix

The collocated suite is 110/110 at head (02-collocated-suite-110-pass.png). To prove the four new collocatedNotGreenDetail tests are load-bearing — not green-for-the-wrong-reason — I mutated the source (single unique-line replacements, restored byte-for-byte; vitest transforms TS on the fly so dist was untouched) and re-ran the full file via vitest's JSON reporter (03-mutation-matrix.png):

mutation failed which tests went red
unmutated (positive control) 0 — (110 green; proves the harness can pass)
M1 return the old flat base wording for every verdict (the PR's own revert) 4 exactly the 4 new tests, nothing else (106 others still passed)
M2 gated branch ⇒ collected-nothing wording (never says RED) 2 "says the test was red…" + "names the probe … per kind"
M3 swap statementhunk 1 "names the probe … per kind"
M4 tweak the collected-nothing parenthetical tail (specificity probe) 0 survivor → benign coverage gap (see Findings)

M1 reproduces the PR's own claim, but more strongly: the PR's focused run reported 4 failed | 106 skipped, whereas this full run reports 4 failed | 106 passed — the other 106 tests actually executed and passed, proving the four are load-bearing and that nothing else regressed. M2/M3 adjudicate each test to the branch it pins (test 1 ⇐ gated→RED; test 4 ⇐ gated→RED and the kind→what map; tests 2/3 ⇐ the collected-nothing wording). Source restored clean (git diff empty) and green again afterward.

Findings

No blocking findings.

Completeness observation (non-blocking). Mutation M4 (see matrix) survived: changing the collected-nothing sentence's parenthetical tail ("…a compile or import error in the probe tree, or every test skipped") turns 0 tests red. This is an ordinary coverage gap, not dead code — the tail is emitted and read by humans; the tests simply pin the collected-nothing sentence by the substring "collected no tests there" rather than in full. The load-bearing distinction is fully pinned regardless: the gated sentence is pinned exactly by test 4's .toBe(…), and M2 (gated⇒collected-nothing) is killed by 2 tests. Not a merge condition; a future test could .toBe the collected-nothing sentence too if the author wants the tail pinned.

Not covered

  • No end-to-end /review run. Verification is at the function level (real dist export) + the collocated suite + the mutation matrix. I did not drive a real baseline/mutant cycle to watch the new detail land in a generated JSON report. The author did run /review against feat(auth): add Kimi and Xiaomi MiMo providers #8368 on two binaries; this round verifies the unit and its wiring instead. The lookup-match claim rests on code construction + a production-shaped harness, not a live mutant run.
  • Linux only. The new function is platform-agnostic (a pure string lookup); all Windows-specific path normalisation lives upstream in classifyProbeRun, which feeds perFile[].file as the original probe string on every platform. macOS/Windows not exercised (the PR itself tested Linux only).
  • Targeted gates only. Ran the affected file's suite (110/110) and ESLint scoped to the two changed files (clean, gate proven live). Did not re-run the repo-wide suite, repo-wide typecheck, or Prettier — typecheck is covered by the HEAD build (dist export confirms tsc compiled the new code), and repo-wide gates are CI's job.
  • Per-commit attribution is moot: single-commit PR; the one commit in $QWEN_VERIFY_CONTEXT matches the locally reachable HEAD^2.

Methodology

Environment: CI verify container (node:22-bookworm, Node v22.23.2), merge-ref checkout at depth 2 (HEAD = merge commit, HEAD^1 = base tip, HEAD^2 = PR head), npm ci + npm run build already complete at HEAD. A/B (01-ab.mjs): imported the real collocatedNotGreenDetail from packages/cli/dist/…/test-efficacy.js and drove {gated, inconclusive, absent} × {mutant, hunk} against a perFile shaped exactly as classifyProbeRun emits it; the base cell is the verbatim HEAD^1 literal. Mutation matrix (03-mutation.mjs): mutated the source (vitest transforms TS on the fly; dist untouched) with single unique-line replacements, restored byte-for-byte after each (verified: git diff clean, post-restore suite green), and parsed results via vitest's JSON reporter. Positive control: unmutated source 110/110. Gates: collocated suite via npx vitest run (110/110); ESLint scoped to both changed files (exit 0) with the gate proven live by a planted any/unused-var that produced 3 errors and exit 1. Raw logs in logs/; harnesses are rerunnable .mjs in this directory. assertions.json (27 = 16 A/B + 11 mutation) counts only the independent oracle assertions authored here; the PR's own 110-test suite is reported as a targeted gate, not double-counted as oracle assertions, since it is the artefact under vacuity analysis.

Evidence images

01-ab-gated-flips-base-vs-head

02-collocated-suite-110-pass

03-mutation-matrix

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Thanks for the PR — and for the thorough iteration across the review rounds.

Template looks good ✓

Problem: observed bug with concrete evidence, found dogfooding /review against #8368AuthDialog.test.tsx compiled, collected 26 tests and failed exactly one, yet all three mutants in its source were held with "likely a compile or import error in the probe tree", a cause nothing had checked. The baseline had already classified that file gated (a real assertion failure). The vitest output and the two /review runs are in the description.

Direction: aligned — this makes the review tool's diagnostic messages accurate. Which mutants/hunks get held is unchanged (that rule is #8345's); only the explanation moves.

Size: not applicable (no core paths touched — all three files are under packages/cli/src/commands/review/).

Approach: the scope grew through the review rounds — from a single shared helper into a discriminated ProbeResult union, a seven-way ProbeReason, and one deduped hold decision (heldForRedCollocatedTest) — but each addition traces to the same defect class the PR set out to fix (an unmeasured cause stated as fact) or to drift the reviewer demonstrated (the hold rule copied by hand, eight survivors shipped through the gap). Nothing here is drive-by.

Risk: no elevated risk signals.

Moving on to code review. 🔍

中文说明

感谢贡献,也感谢在多轮评审中的细致迭代。

模板完整 ✓

问题:已观测到的 bug,有具体证据,发现于对 #8368/review dogfooding —— AuthDialog.test.tsx 编译正常、收集到 26 个测试、恰好失败 1 个,但其源文件里三个 mutant 全部被搁置并标注"可能是探针树的编译或导入错误",而这个原因没有任何环节核实过。基线早已把该文件判为 gated(真实的断言失败)。vitest 输出与两轮 /review 运行见描述。

方向:对齐——让 review 工具的诊断消息准确反映实际。哪些 mutant/hunk 被搁置并未改变(那条规则属于 #8345),改变的只是解释。

规模:不适用(未触及核心路径——三个文件都在 packages/cli/src/commands/review/ 下)。

方案:范围在评审过程中有所扩展——从单个共享辅助函数,发展为判别联合 ProbeResult、七元 ProbeReason、以及一处去重的搁置决策(heldForRedCollocatedTest)——但每一处新增都可追溯到本 PR 立意要修的同一类缺陷(把未被测量的原因当作事实陈述),或评审者实证过的漂移(手工抄写的搁置规则,八个存活者从缝隙漏出)。没有顺手改动。

风险:无升级风险信号。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

Reviewed at 15d1fa78c2629a50e27260410d377d37fef6e2b2 · 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 seven distinct ways a probe lands inconclusive and two guards that flattened all of them into one asserted cause, I would (1) tag each inconclusive probe with a machine-readable reason where it is classified, (2) make ProbeResult a discriminated union so an untagged inconclusive is a compile error rather than a runtime fallback, (3) dedupe the hold rule the two loops had been hand-copying, and (4) read the reason off the baseline the guards already hold instead of asserting one.

Comparison with the diff: the PR matches this and goes further in the right directions. classifyProbeRun tags all four baseline reasons; ProbeResult is a discriminated union and DistributiveOmit keeps the discrimination through ProbeOutcome (a plain Omit would collapse the union and make reason optional again — the comment explains exactly that trap). heldForRedCollocatedTest is the one decision both loops now call.

A few things I verified against the source, not just the diff:

  • runnerFailureReason reads the spawn result's structure (signal / error.code === 'ETIMEDOUT'), not a text match. The JSDoc records that the first version matched /^runner (killed|spawn failed)/ against thrown text the code never emits — so the tag it existed to produce was never produced. Reading structure is the right fix, and the tests drive it through real spawnSync (a timed-out child, an ENOENT binary) rather than hand-written strings.
  • collocatedNotGreenDetail refuses to explain the three reasons a baseline entry cannot carry (control-failed / not-run / runner-died are set on the run-level array, never by classifyProbeRun), and refuses inert (green) — saying "this explanation does not apply" rather than emitting "did not run green … it read green there". That total-contract behaviour is the right response to the function being exported and unit-tested standalone.
  • The control re-classification loop now replaces the entry with a tagged control-failed object instead of mutating verdict in place — the union is what forces that. It operates on the run-level results array, and I confirmed the collocated explanation reads baseline.perFile (only ever the four baseline reasons), so the two never cross.
  • The JSDoc is correctly attached: heldForRedCollocatedTest and collocatedNotGreenDetail each carry their own block, and the stale "takes the collected-nothing wording" sentence the prior review flagged is gone.
  • The integration test now pins the call site end-to-end — it asserts the held mutant's detail contains was RED there and does not contain compile or import error, which is the chain the bug actually shipped on.

One disclosed residual, not a blocker: the reason a thrown ProbeRunFailure carries reaches the run-level results array (so the report artifact is tagged) but not the prose detail in that catch, which still reads e.message. The author names this gap explicitly; it does not touch the collocated explanation this PR is about, and closing it would mean parameterising classifyProbeRun's "with the source reverted" strings — a separate change.

Testing

This change is to strings inside a JSON report artifact — nothing a user sees in the TUI. Real-scenario testing: N/A.

The behavioural claim (the held-candidate explanation now reflects the measured baseline state) is pinned by the PR's own suite: five classifyProbeRun reason-tag cases, the collocatedNotGreenDetail matrix across all four baseline reasons plus the three it must refuse plus inert and absent, and the integration assertion on the end-to-end sentence. CI is green on every completed check for this commit.

Check Conclusion
Test (ubuntu-latest, Node 22.x) ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success
Test (macos-latest, Node 22.x) ⏭️ skipped
Test (windows-latest, Node 22.x) ⏭️ skipped
Integration Tests (CLI, No Sandbox) ⏭️ skipped

All completed checks green on 15d1fa7; the skipped checks are platform/integration variants not triggered for this branch.

中文说明

代码审查

独立方案: 鉴于探针有七种不同方式落入 inconclusive、而两处 guard 把它们全部压成一个被断言的原因,我会(1)在分类处给每个 inconclusive 探针打上机器可读的 reason 标记;(2)把 ProbeResult 改为判别联合,让未打标签的 inconclusive 成为编译错误而非运行时兜底;(3)把两个循环一直手工抄写的搁置规则去重;(4)从 guard 手上已有的基线读出原因,而不是断言一个。

与 diff 的比较: PR 与上述方案一致,并在正确的方向上走得更远。classifyProbeRun 为全部四种基线 reason 打标记;ProbeResult 是判别联合,DistributiveOmit 让判别性穿过 ProbeOutcome 得以保留(普通 Omit 会把联合压平、使 reason 重新变为可选——注释恰好解释了这个陷阱)。heldForRedCollocatedTest 是两个循环现在共同调用的唯一决策。

几处我对照源码(而非仅凭 diff)核实过:

  • runnerFailureReason 读取 spawn 结果的结构signal / error.code === 'ETIMEDOUT'),而非文本匹配。JSDoc 记录了第一版用 /^runner (killed|spawn failed)/ 去匹配代码从不产生的文本——因此它本应产生的标记从未被产生。改读结构是正确的修法,测试也用真实 spawnSync(一个超时的子进程、一个 ENOENT 的二进制)驱动,而非手写字符串。
  • collocatedNotGreenDetail 拒绝解释基线条目不可能携带的三种 reason(control-failed / not-run / runner-died 设在运行级数组上,从不由 classifyProbeRun 设置),也拒绝 inert(绿色)——明说"此解释不适用",而不是输出"did not run green … it read green there"。这种完整契约行为,对于该函数被导出并独立单测的情形,是恰当的回应。
  • 对照检查的重分类循环现在整体替换为一个带 control-failed 标记的条目,而非原地修改 verdict——这正是联合类型所强制的。它作用于运行级 results 数组,我已确认 collocated 解释读取的是 baseline.perFile(永远只含四种基线 reason),两者从不交叉。
  • JSDoc 已正确附着:heldForRedCollocatedTestcollocatedNotGreenDetail 各带自己的注释块,上一轮评审指出的那句陈旧的"takes the collected-nothing wording"已删除。
  • 集成测试现在端到端锁住了调用点——断言被搁置 mutant 的 detailwas RED there 且不含 compile or import error,这正是该 bug 实际赖以漏出的那条链。

一处如实披露的残留,非阻塞: 抛出的 ProbeRunFailure 所携带的 reason 会进入运行级 results 数组(因此报告产物带标记),但进入不了那个 catch 里的散文 detail——后者仍读 e.message。作者明确点出了这个缺口;它不触及本 PR 所针对的 collocated 解释,而要补上它得先把 classifyProbeRun 那些"with the source reverted"字符串参数化——那是另一处改动。

测试

本次改动落在 JSON 报告产物内部的字符串上——用户在 TUI 中看不到任何变化。真实场景测试:N/A。

其行为性主张(被搁置候选的解释现在反映实测的基线状态)由本 PR 自己的测试套件锁定:五条 classifyProbeRun 的 reason 标记用例、collocatedNotGreenDetail 覆盖全部四种基线 reason 外加它必须拒绝的三种、inert 与缺失情形的矩阵,以及集成测试对端到端句子的断言。该提交的 CI 在所有已完成检查上均为绿色。

CI 在 15d1fa7 上所有已完成检查均为绿色;跳过的检查是未针对此分支触发的平台/集成变体。

Qwen Code · qwen3.8-max-preview

Reviewed at 15d1fa78c2629a50e27260410d377d37fef6e2b2 · 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 — a small, observed-bug fix that the review rounds made genuinely better; the invariant is now compile-time and the explanation reads what the run measured.

This PR is a good demonstration of what this review process is for. It started as "replace two hardcoded strings with a helper" and the rounds pushed it into something stronger: a discriminated union that makes an untagged inconclusive a compile error, a deduped hold decision where the duplication had already shipped eight survivors through a gap, and a seven-way reason taxonomy where every explanation reads its answer off the baseline rather than asserting one. My independent proposal landed at the same place the PR did, which is the strongest signal I have that the approach is right.

I verified the load-bearing parts against the source rather than the description: the union reaches the array the report serialises, the control re-classification tags its entries instead of mutating them, runnerFailureReason reads structure not text, and the integration test pins the end-to-end sentence the bug shipped on. CI is green on every completed check for this commit.

The one residual — the thrown ProbeRunFailure's reason reaches the artifact but not the catch's prose — is disclosed honestly, doesn't touch the collocated explanation this PR is about, and the author named the parameterisation it would take to close. That is the right way to leave a known gap.

LGTM, approving. ✅

中文说明

置信度:5/5 —— 一个小巧、针对已观测 bug 的修复,被评审 rounds 真正打磨得更好;不变量现在是编译期保证,解释读取的是运行实测的结果。

这个 PR 很好地展示了这套评审流程的价值。它起初是"用一个辅助函数替换两处硬编码字符串",经多轮评审被推进为更强的形态:一个让未打标签的 inconclusive 成为编译错误的判别联合、一处去重的搁置决策(其重复此前已从缝隙漏出八个存活者)、以及一套七元 reason 分类——每条解释都从基线读出答案,而非断言一个。我的独立方案与 PR 最终落在同一处,这是我对方案正确性最强的信号。

我对照源码(而非描述)核实了承重部分:联合类型抵达了报告所序列化的数组,对照重分类为条目打标记而非原地修改,runnerFailureReason 读取结构而非文本,集成测试锁住了该 bug 实际漏出的端到端句子。该提交的 CI 在所有已完成检查上均为绿色。

唯一残留——抛出的 ProbeRunFailure 的 reason 进入产物却进入不了那个 catch 的散文——被如实披露,不触及本 PR 所针对的 collocated 解释,作者也点明了补上它所需的参数化。这是留下已知缺口的恰当方式。

LGTM,批准。✅

Qwen Code · qwen3.8-max-preview

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@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. Test Plan (not a blocker): src/ui/auth/AuthDialog.test.tsxno such file or directory.

中文说明

已审查。 建议见行内评论。 Test Plan(非阻断):src/ui/auth/AuthDialog.test.tsxno such file or directory

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

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

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review — fix(review): read why the collocated test was not green, do not assert it

Overview

Both collocated-probe guards in runTestEfficacy (the mutant loop and the hunk loop) hard-coded likely a compile or import error in the probe tree as the explanation for holding a candidate inconclusive. The PR routes both through a new exported collocatedNotGreenDetail(kind, probe, perFile) that reads the reason off baseline.perFilegatedit was RED there, anything else → it collected no tests there (…) — plus 4 unit tests.

Small, well-scoped, and the diagnosis in the description holds up.

Verification I ran

On the PR head worktree (790885407):

  • npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts110 passed, as claimed.
  • Load-bearing check: replaced the function body with the old flat wording (void perFile; + the literal (likely a compile or import error in the probe tree)) → exactly 4 failed | 106 passed, all four in collocatedNotGreenDetail. The claim in the PR body reproduces.
  • npx tsc --noEmit -p packages/cli/tsconfig.json → clean.

Correctness — one residual of the same defect

ProbeVerdict is three-valued, but inconclusive covers three distinct sub-causes in classifyProbeRun, and the new else branch collapses them into one asserted cause. Two of the three are still mis-described:

baseline sub-case classifyProbeRun detail new sentence says
!result || assertions.length === 0 collected no tests with the source reverted … ✅ accurate
passed === 0 (all skipped) ${assertions.length} test(s) collected but none executed … (all skipped) ⚠️ "it collected no tests there" — contradicted by the baseline's own count; only the parenthetical rescues it
unparseable JSON (!parsed) runner produced no parseable JSON (exit N): <stderr tail> ⚠️ the parenthetical "a compile or import error in the probe tree, or every test skipped" names two causes, and the measured one is neither — the runner never produced output at all

This is narrower than what the PR fixes, but it is the same shape: a cause stated that nothing measured. Options, in order of how much I'd want them:

  1. Neutral wording for the non-gated branch — e.g. it did not report a passing test there, with no cause enumerated. Cheapest, and it makes the sentence unfalsifiable-by-the-baseline.
  2. Widen the input to { file; verdict; detail } and append the baseline's own detail — the strongest form of "read it off the baseline". Caveat: classifyProbeRun's detail strings are all worded … with the source reverted, which is wrong for a baseline run (unmutated tree, nothing reverted). That would need those strings parameterised first, so it's a bigger change than this PR wants.

Two smaller notes

  • The else branch also swallows inert. In production it can't be reached — the guard only fires when !greenProbes.includes(own) — but the function is exported and unit-tested as a standalone contract, and collocatedNotGreenDetail('mutant', <an inert probe>, perFile) returns a flatly false sentence. A switch on the verdict (or an explicit inert → throw/assert) would make the contract total rather than relying on the caller.

  • The "baseline never reported it" case is unreachable, not just rare. classifyProbeRun probes.map(…)s, so every probe in the array always gets an entry, and runProbeSuite(probeTree, probes, …) at the baseline site is fed the same probes array that collocatedProbe(c.file, probes) selects own from. The test documenting it is fine as a defensive contract, but the PR body presents it as a third real scenario — it isn't one today.

  • Nothing pins the call sites. The 4 tests exercise the exported function; no test asserts that either guard's detail is what the function returns. The guarantee the description claims ("their sentences can't drift") rests on each site being a one-line notGreen(...) call, not on a test. Acceptable at this size — worth knowing it's where the coverage stops.

Style / conventions

  • Placement next to collocatedProbe, the doc-comment-carries-the-measurement house style, the kind: 'mutant' | 'hunk' discriminator, and the local notGreen closure at the one place both loops can see it — all consistent with the file.
  • The doc comment cites the feat(auth): add Kimi and Xiaomi MiMo providers #8368 measurement that motivated the change, which is exactly the convention the rest of this file follows.
  • No perf or security surface: pure string construction on an already-O(probes) path, one find per held candidate.

Verdict

Correct as far as it goes, tested, and a real improvement over asserting a cause. I'd take note 1 (neutral wording for the non-gated branch) before merge — otherwise the sentence still tells a reader "every test skipped or a compile error" in a case where the baseline measured neither. The rest are optional.

中文说明

概述

两处 collocated-probe guard 原先把 likely a compile or import error in the probe tree 写死为解释;本 PR 把两处都改为经由新导出的 collocatedNotGreenDetailbaseline.perFile 读出原因,并补了 4 条单测。范围小、定位准确。

已实测

在 PR head worktree(790885407)上:110 条全通过;把函数体换回旧写死措辞后恰好 4 红 106 绿,与描述一致;tsc --noEmit 干净。

唯一实质问题:同类缺陷仍有残留

inconclusiveclassifyProbeRun 里对应三种子情形,而新的 else 分支把它们压成了一个被断言的原因,其中两种仍被描述错:

  1. 全部 skippassed === 0):基线自己的 detail 是「收集到 N 个测试但一个都没执行」,而新句子说「it collected no tests there」,与基线自己的计数相矛盾,只能靠括号里的补充勉强兜住。
  2. runner 没产出可解析 JSON:括号列举的两个原因(探针树编译/导入错误、全部 skip)都不是实测到的那个 —— runner 根本没有输出。

这比被修的问题窄,但形状相同:说了一个没被测量过的原因。建议(按优先级):

  1. gated 分支改用不列举原因的中性措辞,例如 it did not report a passing test there
  2. 把入参放宽到 { file; verdict; detail } 并直接附上基线自己的 detail —— 这是「从基线读出原因」最彻底的形式。但注意 classifyProbeRun 的 detail 一律写着 … with the source reverted,对基线运行(未变异的树,没有 revert)是错的,得先把这些串参数化,超出本 PR 范围。

两点小注

  • else 分支同样吞掉了 inert。生产路径进不来(guard 只在非 green 时触发),但该函数已导出并按独立契约单测,传入 inert 探针会返回一句彻底错误的话。用 switch 显式覆盖三个 verdict 会让契约完整。
  • 「基线里根本没有该条目」这一情形是不可达,而非罕见:classifyProbeRunprobesmap,每个探针必有条目,而基线运行与 collocatedProbe 用的是同一个 probes 数组。那条测试作为防御性契约没问题,但描述里把它当作第三种真实场景来讲,目前并不成立。
  • 没有测试锁住两个调用点。4 条测试测的是导出函数本身;「两处措辞不会再走偏」这个保证靠的是每处都只有一行 notGreen(...) 调用,而不是测试。以这个体量可以接受,但值得知道覆盖到此为止。

结论

改动正确、有测试、确实优于原先的断言式解释。合并前建议采纳第 1 条(非 gated 分支改中性措辞);其余为可选。

…once

Two findings from review, both landing on this PR's own thesis.

The else branch told every non-`gated` probe the same story -- "collected no
tests there (a compile or import error…)" -- but `classifyProbeRun` reaches
`inconclusive` three different ways, and one of them is the runner producing no
parseable output at all. Nothing is known about collection there, so naming a
compile error is the same invented cause this PR was opened to remove, one
layer down: a reader sent hunting for an import problem while the runner itself
is what fell over. The classifier now tags each branch with a machine-readable
`reason` -- it already had the three cases -- and the explanation reads it. An
entry that names no reason gets the disjunction; a probe with no entry at all
is reported as not measured, which is a different thing from measured-as-empty.

The rule itself was stated twice, once per loop, and the duplication had drifted
twice already: the hunk loop had the guard first and eight mutant survivors
shipped through the gap before it was copied across, then the shared wording was
corrected in one place and hand-copied to the other. Both loops now call one
exported decision, `heldForRedCollocatedTest`, which is where the tests point.

Three mutations, each reddening only its own case: collapsing `no-output` into
the compile-error wording, treating an absent probe as an inconclusive entry,
and a guard that never holds.
@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Both fixed in 50ffbf4 — and both landed on this PR's own thesis, which is the useful part of the review.

The three-causes finding is right, and it is the same defect one layer down. classifyProbeRun reaches inconclusive three ways, and the runner producing no parseable output is not "collected no tests" — nothing at all is known about collection there. Naming a compile error in that case is exactly the invented cause this PR was opened to remove, so I did not take the broadened disjunction: the classifier already branches on all three cases, so each now carries a machine-readable reason and the explanation reads it.

no-output   → the runner produced no parseable output there, so nothing at all is known about it
no-tests    → it collected no tests there — the shape a compile or import error in the probe tree takes
all-skipped → it collected tests there but executed none of them

Your note that "the baseline's per-file detail already names the real cause but is not surfaced here" is what pointed at this, though I did not surface detail itself: every string it builds is phrased "with the source reverted", written for the revert probe, and reusing it verbatim in the baseline context would swap one inaccuracy for another.

Two states I had collapsed also came apart while doing this: a probe the baseline has no entry for now reads "the baseline did not report it", not "collected nothing" — not measured and measured-as-empty are different claims, and the second is one the run never made.

The untested-wiring finding is right, and I want to be precise about what I did and did not fix. The rule was stated twice, once per loop, and that duplication has already drifted twice: the hunk loop had the guard first and eight mutant survivors shipped through the gap before it was copied across, then the shared wording was corrected in one place and hand-copied to the other. Both loops now call one exported decision, heldForRedCollocatedTest, which is what the new tests point at — so the surface that can silently regress is two three-line blocks instead of two duplicated rules.

What that does not do is pin the call sites. The mutant and hunk loops sit inside a handler that creates a git worktree and spawns vitest, so there is no seam a unit test can reach, and reverting either three-line block still leaves the suite green. Your probe is correct about that and it remains correct. I would rather say so than add a source-scanning assertion that pretends otherwise.

Three mutations, each reddening only its own case:

no-output collapsed into the compile-error wording  → 1 failed
absent probe treated as an inconclusive entry       → 1 failed
the shared guard never holds                        → 1 failed

116 tests pass.

中文说明

两条均已在 50ffbf4 修复 —— 而且都正落在本 PR 自己的论点上,这是这次评审最有价值的地方。

三种成因那条是对的,而且它是同一个缺陷的下一层。 classifyProbeRun 有三条路径抵达 inconclusive,而"运行器没有产出可解析输出"并不等于"没有收集到测试"—— 那种情况下关于收集我们一无所知。此时说"编译错误",恰恰就是本 PR 要消除的那种臆造原因。因此我没有采用加宽后的并列措辞:分类器本来就在三个分支上分叉,现在每个分支带上机器可读的 reason,由解释文案去读它(三句话见上)。

你指出"基线的逐文件 detail 已经记录了真实原因却未被利用"正是线索所在;不过我没有直接把 detail 透出来:它构造的每一句都写着*"with the source reverted"*,那是为 revert 探针写的,原样用在基线语境里只是把一种不准确换成另一种。

顺带把我此前合并掉的两个状态也拆开了:基线中根本没有条目的探针现在读作"the baseline did not report it",而不是"什么都没收集到"—— 未测量与测得为空是不同的主张,后者是那次运行从未做出的。

接线未被测试那条也是对的,我想把"修了什么、没修什么"说清楚。 该规则此前分别写在两个循环里,而这份重复已经漂移过两次:hunk 循环先有守卫,mutant 循环在被抄过去之前放出了八个存活者;随后共享的措辞在一处被修正、又被手工抄到另一处。现在两个循环都调用同一个导出决策 heldForRedCollocatedTest,新测试指向的正是它 —— 可能静默退化的面,从两条重复规则缩小为两个三行代码块。

没有做到的是锁住调用点。mutant 与 hunk 两个循环位于一个会创建 git worktree 并派生 vitest 的 handler 内部,单元测试够不到接缝,单独回退任一三行块,测试套件依然全绿。你的探针在这一点上是对的,并且仍然成立。与其加一条扫描源码的断言去假装解决,我更愿意如实说明。

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

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): read why the collocated test was not green, do not assert it

Overview

Two things happen here, and the second is the more valuable one:

  1. classifyProbeRun now tags each inconclusive with why (no-output / no-tests / all-skipped), and a new collocatedNotGreenDetail reads that tag back instead of hard-coding likely a compile or import error in the probe tree. The diagnosis in the PR body is correct — the baseline had already classified the file and both guards threw the answer away.
  2. heldForRedCollocatedTest collapses the mutant loop's and hunk loop's copy of the hold rule into one function. Given that this rule has already drifted twice (the mutant loop shipped eight survivors through the gap in feat(serve): establish workspace runtime ownership #8213, then the wording was hand-copied), this is the right call and is worth more than the message fix.

I verified the hold condition is byte-identical before/after (own && !greenProbes.includes(own)heldForRedCollocatedTest returning a string), so no verdict changes. Confirmed locally on 50ffbf4:

  • npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts116 passed
  • eslint on both changed files → clean
  • tsc -p packages/cli/tsconfig.json → 0 errors in the changed files
  • Both existing integration tests that cover these guards still pass, and the end-to-end string in the report JSON is now:
    this mutant's collocated test packages/lib/src/f.test.ts did not run green in the unmutated
    baseline — it was RED there, so the remaining probes passing cannot show the statement is uncovered
    

Correctness / test coverage

1. The production wiring — the three reason: tags — is completely untestedtest-efficacy.ts:1024,1063,1082

This is the one I'd fix before merge. All ten new cases feed collocatedNotGreenDetail a hand-built perFile fixture; nothing asserts that classifyProbeRun actually emits a reason. Because reason is optional and REASON_PHRASE[entry.reason ?? 'unspecified'] silently absorbs a missing one, dropping a tag is invisible. Reproduced:

$ # delete `reason: 'no-tests' as const,` from classifyProbeRun
$ npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts
Tests  116 passed (116)

Green suite, and every no-tests hold in the report silently degrades from "it collected no tests there — the shape a compile or import error takes" to the vague unspecified disjunction. That is the same class of defect this PR exists to remove, one layer down: the reader is handed a sentence that no longer reflects what was measured, and no test says so.

classifyProbeRun already has fixtures in this file — three assertions of the shape expect(out[0].reason).toBe('no-tests') on the existing vitest-JSON shapes would close it.

2. reason?: leaves the invariant to a runtime fallback rather than the compilertest-efficacy.ts:92-98

The doc says "Set only when verdict is inconclusive", but nothing enforces the converse — that every inconclusive sets one. The unspecified arm exists precisely as the runtime backstop for that. A discriminated union makes the omission a compile error and makes finding 1 mostly moot:

export type ProbeResult =
  | { file: string; verdict: 'gated' | 'inert'; detail: string }
  | { file: string; verdict: 'inconclusive'; detail: string; reason: ProbeReason };

Caveat, so it isn't a surprise: Pick<ProbeResult, 'file' | 'verdict' | 'reason'> doesn't survive the union (reason isn't on every member), so the two helper signatures would need their own narrow param type. If that friction isn't worth it, the tests in finding 1 are the minimum.

3. no-tests still asserts a cause it didn't measuretest-efficacy.ts:1058-1065

The branch is !result || assertions.length === 0, which covers two different things: the file appeared in testResults with zero assertions, and the file never appeared at all. The second also fires on a path-matching miss — the classifier's own comment right above it says a Windows case mismatch "would otherwise miss and read inconclusive — the same wrong-verdict silence". In that case the report now says "it collected no tests there — the shape a compile or import error in the probe tree takes", which is an unmeasured cause pointed at a file that compiled fine. Smaller than the AuthDialog.test.tsx case, and inherited from the pre-existing detail string rather than introduced here, and "the shape … takes" is at least framed as an inference rather than a finding. Still, splitting !result into its own reason (not-in-results) would finish the job the PR started.


Style / maintainability

4. Two stacked JSDoc blocks, and the orphan contradicts the codetest-efficacy.ts:841-868

collocatedNotGreenDetail's doc block sits at 841-856, immediately above heldForRedCollocatedTest's own block at 857-868. Only the second attaches; the first is orphaned, and collocatedNotGreenDetail (line 902) ships with no doc at all. Worse, the orphan is stale:

A probe with no baseline entry at all takes the collected-nothing wording

The code returns NOT_REPORTED = 'the baseline did not report it', and the test at test-efficacy.test.ts:1352 asserts exactly the opposite of what that sentence says. Move the block down to line 902 and rewrite that last paragraph to match NOT_REPORTED.

5. Nit — pointless array copy per candidatetest-efficacy.ts:875

collocatedProbe(file, [...probes]) allocates a copy solely to satisfy testPaths: string[]; the callee only calls .find. Widening it to readonly string[] (line 830) drops the spread and costs nothing — both existing call sites pass string[], which is assignable.


PR description accuracy

Minor, but this file's whole subject is not stating unverified things, so:

  • The Reviewer Test Plan is from an earlier revision. It says "110 pass" and "The four new cases", and quotes four failing test names. The shipped commit has 116 tests and 10 new cases, and two of the four quoted names (says nothing was collected when the baseline collected nothing, takes the collected-nothing wording for a probe the baseline never reported) don't exist in the file. The load-bearing claim itself holds and is stronger than advertised — I ran the mutation (flat wording restored) and got 8 failed | 108 passed, all eight in the two new describes, nothing else red.
  • "Breaking changes: none. The detail field is prose … nothing parses it" is true of detail but understates the change: probed: results (test-efficacy.ts:2360) serialises ProbeResult verbatim, so inconclusive probe entries in the report JSON now carry a new reason key. Additive and safe, but it is a report-schema addition and worth one line in the body — arguably a selling point, since a consumer could act on it where it can't act on prose.
  • NOT_REPORTED and unspecified are unreachable through the real pipeline. classifyProbeRun maps over exactly probes, and own always comes out of probes, so perFile.find never misses and every inconclusive is tagged. Fine as defensive defaults, but "the tests now pin the string the report actually carries" only holds for the gated and three-reason arms.

Verdict

The change is correct, the dedup is the right structural call, and no verdict behaviour moves. Finding 1 is the one I'd want fixed before merge — the tags that make this PR work are the only part of it nothing tests. Finding 4 is a two-minute fix and currently leaves a comment in the tree that states the opposite of what the code does.

The tags this PR turns on were the only part of it nothing tested. `reason`
was optional and the lookup absorbed a missing one, so deleting a tag left all
116 tests green while every hold of that kind silently degraded to a vague
catch-all -- the same defect this PR exists to remove, one layer down.

`ProbeResult` is now a discriminated union: `reason` is mandatory on the
`inconclusive` arm and absent from the others, so an untagged branch does not
compile. Deleting a tag is now caught twice, by tsc and by the new assertions
on `classifyProbeRun` itself, which no fixture stood in for before.

`no-tests` was also two different observations under one name. `!result` means
the run answered and this file was not in the answer -- which a path that
failed to match produces as readily as a compile error, and the boundary and
case rules right above it are why that is not hypothetical -- so it is now
`not-in-results` and says both possibilities instead of picking one.

Also from the review: the `collocatedNotGreenDetail` doc block had been left
above `heldForRedCollocatedTest`, describing neither, and its last paragraph
stated the opposite of what the code returns for an unreported probe. It moves
onto the function it documents and now matches it, including that the case is a
default rather than one the pipeline can reach. `collocatedProbe` takes a
readonly array, dropping a per-candidate copy made only to satisfy the type.
@wenshao
wenshao requested a review from Copilot August 2, 2026 12:43

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 ff6b87d, and the description is corrected. Finding 1 is the one that mattered — I reproduced it before changing anything: deleting reason: 'no-tests' left all 116 green.

1 + 2 together, because the union makes the tests structural rather than a promise to remember. ProbeResult is now discriminated — reason is mandatory on the inconclusive arm and absent from the others — so an untagged branch does not compile. Deleting a tag is caught twice now:

$ # delete `reason: 'no-tests' as const,` from classifyProbeRun
tsc: 1 error
× classifyProbeRun > tags a file that collected nothing as no-tests
Tests  1 failed | 120 passed (121)

Five assertions on classifyProbeRun itself, one per way a probe fails to be green plus one that a decided verdict carries no tag. Your caveat about Pick was exactly right and cost one small type: the two helpers take a ProbeOutcome (file/verdict/reason?). Worth the friction — the union is what turns "remember to tag it" into a compile error, and the tests then confirm the tag is the right one rather than that it exists.

3. no-tests was two observations under one name. Fixed as not-in-results, which says both possibilities instead of picking one: "the run produced results there but none for it — which a compile or import error looks like, and so does a path that did not match". You framed this as finishing the job the PR started, and that is the right reading — the classifier's own boundary and case rules are the reason a path miss is not hypothetical.

4. The orphan was worse than orphaned — it was wrong. It said a probe with no baseline entry "takes the collected-nothing wording" while the code returns NOT_REPORTED and a test asserts the opposite. Moved onto collocatedNotGreenDetail and rewritten to match, including that the case is a default rather than one the pipeline can reach.

5. collocatedProbe takes readonly string[]; the per-candidate spread is gone.

On the description. All three corrections applied. The test plan was indeed from an earlier revision — in a change whose subject is not stating unverified things, that is the one place it should not have been stale. It now carries the real numbers (121 tests, the 8-failure mutation you measured, the tsc-plus-test double catch), the report-schema line for probed carrying reason, and an explicit note that NOT_REPORTED and unspecified are unreachable through the pipeline — their tests pin a hand-built caller, not a path a run can take. Thanks for checking that; "the tests pin the string the report actually carries" was true of the reason arms and overclaimed for those two.

121 tests pass.

中文说明

五条全部在 ff6b87d 修复,PR 正文也已订正。第 1 条是真正要紧的那条,我在动手前先复现了:删掉 reason: 'no-tests',116 条依然全绿。

第 1、2 条合并处理,因为联合类型让测试从「记得要做」变成结构性约束。 ProbeResult 现为判别联合 —— reasoninconclusive 分支上是必填、在其它分支上不存在 —— 因此未打标记的分支根本无法编译。删掉一个标记现在会被拦两次(见上)。另外新增五条针对 classifyProbeRun 本身的断言:每种「探针未变绿」的方式各一条,外加一条断言已判定的 verdict 不带标记。你关于 Pick 的提醒完全正确,代价是一个小类型:两个助手改用 ProbeOutcome。这点摩擦是值得的 —— 联合类型把「记得打标记」变成编译错误,测试随后确认的是标记是否正确,而不是它是否存在。

第 3 条:no-tests 混着两种观察。 已拆出 not-in-results,并同时说出两种可能而不是挑一种。你说这是「把本 PR 开的头做完」,这个判断是对的 —— 分类器自己的边界与大小写规则,正说明路径未匹配并非假想。

第 4 条:那个孤儿注释不只是孤儿,它是错的。 它写着「基线中没有条目的探针取『什么都没收集到』的措辞」,而代码返回的是 NOT_REPORTED,且有一条测试断言的正好相反。已移到 collocatedNotGreenDetail 上方并改写为与代码一致,包括说明该情形是默认值而非流水线可达的分支。

第 5 条: collocatedProbe 改为接收 readonly string[],逐候选的数组拷贝已去掉。

关于 PR 正文。 三处订正全部落实。测试计划确实是旧修订版 —— 在一个主题就是「不陈述未经验证之事」的改动里,这是最不该过期的地方。现在写的是真实数字(121 条测试、你测到的 8 条失败变异、tsc 与测试的双重拦截),补上了 probed 携带 reason 的报告结构说明,并明确标注 NOT_REPORTEDunspecified 在流水线中不可达 —— 它们的测试锁定的是手工构造的调用方,而非某次运行可以走到的路径。感谢你核对这点:「测试锁定的是报告真正携带的字符串」对 reason 各分支成立,对那两个默认值则是我说过头了。

121 条测试通过。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review: fix(review): read why the collocated test was not green, do not assert it

Reviewed the diff at ff6b87d against the head blobs of both changed files, plus test-efficacy.integration.test.ts (untouched here) to check nothing existing moves under the new wording. I did not run the suites — everything below is static, verified against the exact lines at the reviewed commit.

What holds up ✅

  • Collapsing the two guards into one function is the right call, and the boundary is drawn in the correct place: collocatedProbe(file, probes) plus the greenProbes membership test is the whole rule, and the replacement is condition-for-condition identical to what both call sites had. Which mutants and hunks are held does not change, as the PR claims.
  • Splitting !result from assertions.length === 0 closes a real conflation, and it is net-new coverage rather than a rename — at the base commit test-efficacy.test.ts had no case at all for a probe missing from testResults.
  • No existing assertion breaks. The integration suite's probed expectations all use expect.objectContaining (:1418, :1552, :1580), and the two guard cases assert toContain('collocated test') (:479) and toContain('did not run green') (:1051) — both still satisfied. out.mutants.probed / out.hunks.probed entries never gain a reason, so the strict toEqual blocks are unaffected.
  • reason's only read site is collocatedNotGreenDetail; grepped repo-wide including docs/ and .qwen/, nothing else parses the artifact. Not a dead field.

Findings

1. The compiler does not enforce the invariant on the array that reaches the reporttest-efficacy.ts:1881

The stated thesis is that the union means "every inconclusive MUST say which way, and the compiler is what enforces it." That holds for classifyProbeRun's return type, but the array serialised as probed was left on the old shape:

const results: Array<{
  file: string;
  verdict: ProbeVerdict;
  detail: string;
}> = [];

Two paths push into it without a reason, and both compile:

  • :2040 — the worktree-create catch: results.push({ file, verdict: 'inconclusive' as const, detail })
  • :2292 — the probe-run catch: same shape, detail: 'probe could not run: …'

Meanwhile results.push(...revertRun.perFile) at :2283 does carry reason through at runtime (spread of a non-fresh object, so no excess-property check). So probed ends up with reason present on classifier-produced inconclusive entries and absent on catch-produced ones. That makes the risk note — "probed serialises ProbeResult verbatim, so inconclusive entries in the artifact now carry a reason key" — true only for the subset that came from the classifier, which is the weaker guarantee a consumer has to code against.

Declaring const results: ProbeResult[] = [] turns both catches into compile errors, which is exactly the job the union was introduced to do. They would then need a reason of their own; neither is no-output (nothing was spawned, or the spawn threw before any output existed), so a fifth arm — 'not-run' — reads honestly and keeps the rule that a reason is never invented.

Related, worth one sentence in the risk section rather than a change: MutantResult / HunkResult carry verdict + detail and no reason, so mutant-side and hunk-side inconclusive entries stay untagged. Probably deliberate, but the artifact now has two conventions for the same verdict and the description reads as though it has one.

2. ProbeReason's doc comment does not describe ProbeReasontest-efficacy.ts:79-95

It says "Three different things" for a four-member union, never mentions not-in-results, and the definition it gives for no-tests — "a run that produced results without this file, the shape a compile or import error takes" — is the implementation of not-in-results at :1094-1099. The actual no-tests at :1101-1107 is the other thing: the file was in the results and collected zero assertions. A reader who reaches for no-tests from the type doc gets the branch this PR just split away from it.

In a change whose argument is "do not state a cause nothing checked", the type's own doc stating a definition the code does not implement is worth fixing before merge. Four items, and swap the two descriptions.

3. not-in-results is the one reason whose report sentence has no testtest-efficacy.ts:897, test-efficacy.test.ts:1449

The it.each table covers no-output, no-tests, all-skipped. REASON_PHRASE['not-in-results'] — the arm this PR adds — is asserted nowhere. classifyProbeRun tagging it is covered (test-efficacy.test.ts:427), but nothing pins the sentence a mutant held for that reason actually carries, which is the layer the PR is about. One row:

['not-in-results', 'produced results there but none for it', 'a path that did not match'],

Suggestion, not a blocker — but it makes "the rest assert the sentence each reason produces" in the description true as written.

4. An inert entry falls into the "did not come back green" wordingtest-efficacy.ts:938-943

const reason =
  entry === undefined
    ? NOT_REPORTED
    : entry.verdict === 'gated'
      ? 'it was RED there'
      : REASON_PHRASE[entry.reason ?? 'unspecified'];

inert is green — it is precisely what greenProbes is built from at :2083 — yet it lands in the unspecified phrase, which says the opposite. Through heldForRedCollocatedTest it cannot happen (greenProbes.includes(own) returns first), but collocatedNotGreenDetail is exported, takes the wide ProbeOutcome, and is unit-tested directly, so the only thing keeping the false sentence unreachable is caller discipline.

This and the unspecified arm are both symptoms of ProbeOutcome (:115) re-opening the optionality the union just closed. Pick does not distribute, but a distributive omit does, and it preserves the discrimination:

type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
export type ProbeOutcome = DistributiveOmit<ProbeResult, 'detail'>;

With that, entry.reason ?? 'unspecified' stops compiling until the code narrows on verdict === 'inconclusive' — which forces the inert arm to be written out explicitly and makes unspecified unreachable by construction rather than by comment. It would let you delete the unspecified phrase and half of the "two defaults are unreachable" caveat: one of them stops needing to exist.

Verdict

No correctness defect in the shipped behaviour — the hold condition is unchanged, and in every case a real run can reach, the sentence is now drawn from measured state instead of asserted. Finding 1 is the one I would fix before merge: it is the gap between the invariant the PR argues for and the one the compiler actually checks, and it is a two-line change plus one new reason. 2 and 3 are small and mechanical. 4 is optional but collapses two of the caveats in the risk section into nothing.

The invariant was argued for and then not checked where it counts. `probed`
serialises `results`, and `results` was declared as a structural echo of
`ProbeResult` rather than `ProbeResult` itself, so two catch paths pushed an
untagged `inconclusive` and compiled -- and a third assigned `verdict` in
place, which the union cannot see at all. The artifact therefore carried
`reason` on classifier-produced entries and not on the others: two conventions
for one verdict, described in the PR as one.

`results` is now `ProbeResult[]`. That turned all three into compile errors and
they needed reasons of their own, neither of which is `no-output`: `not-run`
for a probe no suite was attempted for, and `control-failed` for one that read
green in a run the positive control had already proved could not go red. The
in-place re-class is a replacement now, since assigning `verdict` alone leaves
the entry untagged.

`ProbeOutcome` was re-opening the optionality one line after the union closed
it -- a plain `Omit` collapses the arms -- which let an `inert` entry reach the
explanation helper and come back described as "did not come back green", the
opposite of what `inert` means. A distributive omit keeps the discrimination,
so the helper cannot read `reason` without narrowing first, the `inert` arm has
to be written out, and the `unspecified` phrase stops existing rather than
being documented as unreachable.

Also: `ProbeReason`'s doc described three members of what is now a five-member
union and gave `no-tests` the definition of `not-in-results` -- the branch this
PR split away from it. And `not-in-results` was the one reason whose report
sentence nothing asserted.
@wenshao
wenshao requested a review from Copilot August 2, 2026 14:37

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 658c278. Finding 1 is the sharpest kind of review note — the invariant was argued for in the description and then not checked at the place that produces the artifact.

1. The union did not reach results, and there were three holes, not two. Declaring const results: ProbeResult[] turned both catch paths into compile errors as you predicted, and surfaced a third the type could not see before: the positive-control re-class at the end assigns verdict = 'inconclusive' in place, which leaves the entry untagged without ever constructing an object. It is a replacement now.

Both new paths needed a reason of their own and neither is no-output, as you said:

  • not-run — no suite was attempted (no worktree, or the spawn threw).
  • control-failed — it read green, in a run the positive control had already proved could not go red.

The isolated mutation, which is the one that matters:

$ # keep `results: ProbeResult[]`, delete `reason: 'not-run'` from the catch push
error TS2345: Argument of type '{ file: string; verdict: "inconclusive"; detail: string; }'
              is not assignable to parameter of type 'ProbeResult'.

On MutantResult / HunkResult staying untagged: that is deliberate, and you are right that the description implied otherwise. A mutant's inconclusive is a different question — why this candidate was not scored, which is budget, cap, control or the collocated-test hold — and its answers do not overlap ProbeReason at all. Sharing the field would put two vocabularies under one name. The risk section now says the artifact has two conventions and why.

2. The doc described three members of a five-member union and swapped two definitions. Correct, and in this PR of all PRs. Rewritten as five items with no-tests and not-in-results the right way round: not-in-results is the run answering without this file, no-tests is the file being in the answer with zero assertions.

3. not-in-results had no sentence test. Added, along with rows for the two new reasons, so the it.each table now covers every arm of REASON_PHRASE.

4. ProbeOutcome re-opened the optionality one line after the union closed it. The DistributiveOmit works exactly as you described. Two things fell out of it: entry.reason no longer compiles without narrowing on verdict, which forced the inert arm to be written out — it now says the baseline reported it green and that this explanation does not apply, rather than a fluent sentence contradicting the measurement — and unspecified is gone rather than documented as unreachable. Reverting the type reproduces the hole:

error TS2538: Type 'undefined' cannot be used as an index type.

So one of the two "unreachable defaults" caveats is deleted rather than reworded. The other, NOT_REPORTED, stays and stays labelled.

124 tests pass. The description is refreshed with these numbers.

中文说明

四条全部在 658c278 修复。第 1 条是最有价值的那类评审意见 —— 不变量在正文里被论证过,却没有在真正产出产物的地方被检查。

1. 联合类型没有到达 results,而且窟窿是三个不是两个。results 声明为 ProbeResult[] 后,两条 catch 路径如你所料变成编译错误,并暴露出第三处类型此前完全看不见的:末尾正对照重分类是原地verdict 赋值,根本不构造对象,因此不会被检查。现在改为整体替换。

两条新路径各自需要自己的 reason,且都不是 no-output,正如你所说:not-run(没有尝试任何 suite —— 没有 worktree,或 spawn 抛错);control-failed(读数为绿,但该次运行的正对照已经证明它不可能变红)。隔离后的变异(这才是关键的那个)见上:保留 ProbeResult[]、只删掉 catch 里的 reason,直接编译失败。

关于 MutantResult / HunkResult 保持不带标记:这是刻意的,而你指出正文让人以为并非如此,这一点是对的。mutant 的 inconclusive 回答的是另一个问题 —— 这个候选为何没有被评分 —— 答案是预算、上限、对照或 collocated 测试的 hold,与 ProbeReason 毫无交集。共用同一个字段会把两套词汇塞进一个名字。风险一节现在写明产物中存在两种约定及其原因。

2. 文档描述了一个五成员联合中的三个,并把两个定义写反了。 属实,而且偏偏发生在这个 PR 上。已改写为五条,并把 no-testsnot-in-results 摆正:not-in-results 是「运行给了答案但其中没有这个文件」,no-tests 是「文件在答案里,但零断言」。

3. not-in-results 是唯一没有句子测试的 reason。 已补,并连同两个新 reason 一并加入,it.each 现在覆盖 REASON_PHRASE 的每一个分支。

4. ProbeOutcome 在联合刚封上的下一行又把可选性打开了。 DistributiveOmit 的效果与你描述的完全一致。由此带来两个结果:不先按 verdict 窄化就读不到 entry.reason,这迫使 inert 分支必须被显式写出 —— 现在它说的是「基线报告它为绿,因此本解释不适用于它」,而不是一句与测量相矛盾的流畅陈述;以及 unspecified 被删除,而不是被注释为不可达。把类型改回去即可复现该窟窿(输出见上)。

因此「两个不可达默认值」的说明删掉了一个,而不是改写;另一个 NOT_REPORTED 保留并继续如实标注。

124 条测试通过,正文数字已同步刷新。

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Review

Overview. Replaces the hardcoded likely a compile or import error in the probe tree explanation attached to a collocated test was not green hold with a sentence derived from the baseline's own classification. Three parts: ProbeResult becomes a discriminated union so every inconclusive must carry a ProbeReason; collocatedNotGreenDetail maps that reason to prose; heldForRedCollocatedTest collapses the duplicated mutant/hunk guard into one function. The verdict logic is untouched — only the explanation moves.

The premise checks out. AuthDialog.test.tsx classifying gated (a real assertion failure) while being reported as an import error is a message pointing the reader at a file that imports fine, and the answer was already in baseline.perFile.

Verified locally

Ran on the PR head in an isolated worktree:

  • npx vitest run --root packages/cli src/commands/review/test-efficacy.test.ts124 passed, matching the description.
  • Whole src/commands/review/ suite → 48 files, 1509 passed. Nothing else depended on the reworded !result detail.
  • eslint + prettier --check on both files → clean.
  • The central design claim — the compiler is what enforces the tag — holds. Deleting reason: 'not-run' from the revert-probe catch:
    test-efficacy.ts(2065,22): error TS2345: Argument of type '{ file: string; verdict: "inconclusive"; detail: string; }'
      is not assignable to parameter of type 'ProbeResult'.
      Property 'reason' is missing ...
    
    Typing results as ProbeResult[] rather than a structural echo, and replacing rather than mutating in the control-failed re-class loop, are what make that hold at both levels. Worth keeping.

Findings

1. not-run is asserted for a suite that ran and was killedtest-efficacy.ts:2318-2326 (medium)

ProbeReason documents not-run as "no probe suite was attempted for it … Nothing was measured at all", and REASON_PHRASE renders it "no probe suite ran for it at all there". But that catch covers three different failures: git checkout base, safeRmWithin, and runProbeSuite — and runProbeSuite throws on r.signal, including the SIGTERM the per-run timeout fires, whose message this file itself formats as probe timed out after 300s. A probe killed at the 300s deadline ran, and possibly executed most of the suite. Tagging it not-run is the same move this PR exists to stop, one layer up: the prose detail carries the truth (probe could not run: runner killed by SIGTERM (probe timed out after 300s)), while the machine-readable tag — the field the description argues "a consumer can act on where it cannot act on prose" — names a cause nothing measured.

One tag cannot be right for all three throws. Suggest splitting: keep not-run for the pre-run failures, and derive something like runner-died when the throw came from r.signal/r.error. The same catch shape at :2064 (worktree add failed) is genuinely not-run and needs no change.

2. The it.each cast disables the check it looks like it is makingtest-efficacy.test.ts:1474 (minor)

reason: reason as 'no-output' | 'no-tests' | 'all-skipped',

The table also feeds not-in-results, not-run and control-failed, so the annotation is false about half its rows. Because it.each infers the parameter as string, the cast compiles regardless — a typo'd reason in the table would type-check and fail at runtime with a confusing toContain diff instead of at tsc. as ProbeReason is both true and load-bearing; it needs ProbeReason added to the import at :8.

3. Two REASON_PHRASE entries are unreachable from the only caller, and one contradicts its own frametest-efficacy.ts:908-911 (minor)

collocatedNotGreenDetail is only ever passed baseline.perFile, which comes from classifyProbeRun and can therefore only carry no-output | not-in-results | no-tests | all-skipped. not-run and control-failed are set exclusively on the top-level results array. For control-failed the composed sentence is self-contradictory:

this mutant's collocated test X did not run green in the unmutated baseline — it read green there, but the positive control failed …

The description is careful to label the NOT_REPORTED default as unreachable-and-therefore-a-default; these two deserve the same note, since their it.each rows currently read as coverage of paths a run cannot take. Related: the sentence hardcodes "in the unmutated baseline" while the parameter type accepts any ProbeOutcome[], so a second caller passing results would emit prose about a run it is not describing. Naming the parameter baselinePerFile costs nothing and marks the contract.

4. The distinguishing clause is pinned only against a hand-built fixturetest-efficacy.integration.test.ts:1051 (nit)

The end-to-end hold tests assert 'did not run green' and the filename — both of which the old flat wording also satisfied. The clause that actually regressed (was RED there vs. an import-error claim) is asserted only in unit tests against a hand-built perFile. Adding expect(m.detail).toContain('was RED there') there pins the whole chain — baseline classification → reason tag → sentence — through the path the bug shipped on. The f.test.ts fixture already classifies gated, so it is a one-line addition.

Smaller notes

  • Splitting !result || assertions.length === 0 into not-in-results / no-tests is the right call and the not-in-results wording is appropriately non-committal — it names both the compile error and the path miss that the boundary/case rules in classifyProbeRun exist because of.
  • DistributiveOmit is doing real work here (a plain Omit would let an inert entry reach the helper untyped), and the comment explaining why is the kind that survives a refactor. No objection.
  • Schema growth on probed[].reason is additive and nothing in docs/ or the bundled review skill describes the report shape, so there is nothing to keep in sync.
  • The inert arm's "the baseline reported it GREEN, so this explanation does not apply" is unreachable through heldForRedCollocatedTest (the caller filters on greenProbes) but is the right defensive answer for an exported function. Fine as is.

None of the four blocks merge. (1) is the one worth fixing before this lands, since it reintroduces the exact defect class the PR is closing.

`not-run` was applied to a catch covering three different failures. The
checkout and the tree removal fail before anything runs; the runner throws when
it was KILLED, and the per-run timeout fires SIGTERM at a suite that may have
executed most of its tests. Tagging that "no probe suite ran" is a cause
nothing measured -- the move this file exists to stop, one layer up, in the
machine-readable field the description argues a consumer can act on. Split into
`runner-died`, derived from the runner's own message prefixes by an exported
`probeFailureReason` so both directions are pinned rather than assumed.

Three reasons are set only on the run-level results array and can never reach
`collocatedNotGreenDetail`, which is passed the baseline. Rendered there,
`control-failed` produced "did not run green in the unmutated baseline -- it
read green there", a sentence contradicting its own frame. They now report that
the baseline did not classify the probe, the same answer the `inert` arm gives,
and the parameter is named `baselinePerFile` for the contract it has.

The `it.each` cast named three of the six reasons the table feeds, so it
compiled regardless and a typo would have surfaced as a confusing `toContain`
diff instead of a type error. It is `ProbeReason` now.

And the integration hold assertions matched what the old flat wording also
satisfied. They now pin the clause that regressed, so the chain the bug shipped
on -- baseline classification, reason tag, sentence -- is covered end to end.
@wenshao
wenshao requested a review from Copilot August 2, 2026 15:02

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 164017c.

1. not-run for a suite that was killed. Right, and it is this PR's own defect one layer up — the prose carried the truth while the machine-readable tag, the field the description argues a consumer can act on, named a cause nothing measured. Split as you suggested: runner-died when the throw came from the runner (runner killed by …, runner spawn failed: …), not-run for the checkout and the tree removal, which really do fail before anything starts. The :2064 worktree-add catch is unchanged, as you said it should be.

The derivation is an exported probeFailureReason rather than an inline ternary, because my first attempt at it was untested and survived its mutation:

$ # first attempt, inline: force the tag to 'not-run'
Tests  125 passed (125)
$ # after extracting, same mutation
× probeFailureReason > calls runner killed by SIGTERM (probe timed out after 300s) a suite that did not survive
× probeFailureReason > calls runner killed by SIGKILL a suite that did not survive
× probeFailureReason > calls runner spawn failed: ENOENT a suite that did not survive

Both directions are pinned against the runner's verbatim messages. The call site inside the catch is still not reachable from a unit test — same limitation as the guard loops, and I would rather name it than paper over it.

2. The cast. True of three of the six rows and load-bearing for none. as ProbeReason now, with the type imported.

3. Unreachable phrases, and one that contradicted its frame. not-run, runner-died and control-failed are set only on the run-level results array and can never reach a baseline entry. control-failed rendered inside that sentence read "did not run green in the unmutated baseline — it read green there", which is worse than unreachable: it is wrong if it ever appears. All three now report that the baseline did not classify the probe — the same answer the inert arm gives — and the parameter is baselinePerFile, which is the contract you pointed out was only in my head.

4. The integration assertions matched the old wording too. That is the observation I should have made myself: did not run green and the filename were both satisfied before this PR, so nothing end-to-end pinned the clause that regressed. Added toContain('was RED there') and not.toContain('compile or import error') — 28 pass, so the chain from baseline classification through the reason tag to the sentence is covered on the path the bug shipped on.

130 unit tests, 28 integration.

中文说明

四条全部在 164017c 修复。

1. 被杀死的 suite 不该标成 not-run 属实,而且这是本 PR 自身缺陷的上一层 —— 散文里写着真相,而机器可读的标签(正是描述中宣称"消费方可以据以行动"的那个字段)却指认了一个没被测量过的原因。按你的建议拆分:抛错来自运行器(runner killed by …runner spawn failed: …)时为 runner-died;checkout 与目录删除失败确实发生在任何东西启动之前,保留 not-run:2064 处 worktree add 的 catch 未改动,与你的判断一致。

该推导做成了导出的 probeFailureReason 而非内联三元表达式,因为我第一版是内联的、且在变异下存活(输出见上)。两个方向都用运行器原样的消息锁住。catch 内部的调用点仍然无法从单元测试触达 —— 与守卫循环是同一处局限,我宁可点明而不是掩饰。

2. 那个类型断言。 对六行中的三行成立,且对任何一行都不承重。现已改为 as ProbeReason 并导入该类型。

3. 不可达的措辞,以及一句与自身框架矛盾的话。 not-runrunner-diedcontrol-failed 只在运行级 results 数组上设置,永远不可能出现在基线条目里。control-failed 放进那句话会读成「did not run green in the unmutated baseline —— it read green there」,这比"不可达"更糟:一旦出现就是错的。三者现在统一报告「基线没有对它做出分类」,与 inert 分支同一个答案;参数也更名为 baselinePerFile,即你指出的那条此前只存在于我脑子里的契约。

4. 端到端断言旧措辞也满足。 这是我本该自己发现的:did not run green 与文件名在本 PR 之前就已成立,因此没有任何端到端测试锁住真正回归的那一句。已加上 toContain('was RED there')not.toContain('compile or import error') —— 28 条通过,于是从基线分类、reason 标签到句子的整条链,在这个 bug 当初出货的路径上被覆盖。

单元测试 130 条,集成测试 28 条。

wenshao added 2 commits August 2, 2026 23:17
…prose

`probeFailureReason` matched `/^runner (killed|spawn failed)/` against the
thrown message, and neither real failure produces that text. Measured:
`spawnSync` reports a timeout as `error` (`spawnSync … ETIMEDOUT`, with
`signal` also set) and a missing binary as `spawnSync … ENOENT`, and
`runProbeSuite` throws `r.error` before it ever composes a "runner killed by"
sentence. So `runner-died` was never produced -- the tag added last round to
stop a cause being invented was itself inoperative -- and the test that covered
it asserted `runner spawn failed: ENOENT`, a string that exists nowhere but in
that test.

The reason is now read off the spawn result's structure by an exported
`runnerFailureReason`, and carried on a `ProbeRunFailure` rather than left to
be parsed back out. Its cases are driven through real `spawnSync` calls -- a
process killed at a 300ms deadline and a binary that does not exist -- so the
fixture is measured rather than written.

`not-run` widens to "no suite ran: the tree could not be prepared, or the
runner could not be started", which is what a spawn that fails actually is.

Also from this round: the `ProbeReason` doc said "Five different things" over
seven bullets, and `heldForRedCollocatedTest` still called its parameter
`perFile` after the helper it forwards to was renamed `baselinePerFile`.
`runner-died`'s phrase still offered "or a spawn that failed" after a failed
spawn was reclassified to `not-run` -- naming a case that no longer arrives
there, which is the mismatch this change exists to remove. `not-run`'s comment
gained the same case it acquired in the type. And the `results` declaration
said "the two catch paths below" when the control-failed re-class is a third
site the union now constrains.
@wenshao
wenshao requested a review from Copilot August 2, 2026 15:21

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 rounds found something; the fourth came back clean.

Round 1 — the tag added last round was inoperative. probeFailureReason matched /^runner (killed|spawn failed)/ against the thrown message, and neither real failure produces that text. Measured directly:

timeout   -> error: spawnSync /usr/bin/node ETIMEDOUT | signal: SIGTERM
no binary -> error: spawnSync /nonexistent ENOENT     | signal: null

runProbeSuite throws r.error before it ever composes a "runner killed by" sentence, so runner-died was never produced in a real run — the tag introduced to stop a cause being invented was itself never reached. The test that covered it asserted runner spawn failed: ENOENT, a string that exists nowhere but in that test, which is why its mutation check passed.

Now read off the spawn result's structure by runnerFailureReason, carried on a ProbeRunFailure, and the fixtures are produced by driving real spawnSync calls rather than written by hand. not-run widened to cover a runner that could not be started, which is what an ENOENT spawn actually is.

Round 1 also caught a regression I introduced while fixing it. Rewriting the throw as if (r.error || r.signal) inverted the precedence, so an ENOBUFS failure that was also killed reported "killed by SIGTERM" and lost the useful half. The integration suite caught it — I had run only the unit tests after that edit, and mistook the red for a mutation kill until I read the assertion. r.error goes first again.

Round 2 — phrasings naming cases that no longer route to them. runner-died still offered "or a spawn that failed" after that case moved to not-run; not-run's comment had not gained it; and the results declaration said "the two catch paths" when the control-failed re-class is a third site the union constrains. Same class of defect as the one this PR fixes, so worth naming rather than tidying silently.

Round 3 — checked the tests for hollow assertions. Two arms of the explanation share the words "does not apply", so an assertion on that alone could not tell them apart. Collapsing the two arms into one reddens all three of the relevant cases, so the specific clauses are what is pinned.

Round 4 — cross-checked the taxonomy against the code rather than the comments. Seven reasons, seven phrases, and BASELINE_REASON's four are exactly the four classifyProbeRun sets. Nothing outside this file imports the new types, and every ProbeResult construction is tagged (the three untagged inconclusive returns elsewhere are MutantResult/HunkResult, which answer a different question).

Known and disclosed rather than papered over: losing the reason on its way from ProbeRunFailure into the catch is not caught by any test — runProbeSuite sits inside a handler that builds a git worktree, so there is no seam a unit test reaches, and no integration fixture drives the revert probe into that catch. The classifier and the error each carry a test; the wire between them does not.

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

中文说明

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

第 1 轮 —— 上一轮加的那个标签根本没生效。 probeFailureReason/^runner (killed|spawn failed)/ 去匹配抛出的消息,而两种真实失败都不产生这种文本(实测输出见上)。runProbeSuite 在拼出 "runner killed by" 之前就先抛了 r.error,因此 runner-died 在真实运行中从未产生 —— 一个为了阻止"臆造原因"而引入的标签,自己从未被触达。覆盖它的测试断言的是 runner spawn failed: ENOENT,一个只存在于该测试中的字符串,这正是它的变异检查也能通过的原因。现在改为从 spawn 结果的结构判定,并由 ProbeRunFailure 携带;fixture 由真实 spawnSync 驱动产生,而非手写。not-run 扩展为覆盖"运行器根本起不来",ENOENT 正是如此。

第 1 轮还抓到我在修它时引入的回归。 我把抛出改写成 if (r.error || r.signal),颠倒了优先级,于是"同时被杀死的 ENOBUFS 失败"会报成 "killed by SIGTERM",丢掉了有用的那一半。是集成测试抓到的 —— 我改完只跑了单元测试,并且一度把这次红误当成变异被杀,直到读了断言原文。现在 r.error 重新优先。

第 2 轮 —— 措辞点名了不再路由到它的情形。 runner-died 仍写着"或 spawn 失败",而该情形已归入 not-runnot-run 的注释没有相应补上;results 的声明写着"下面两处 catch",而 control-failed 重分类是被联合约束的第三处。与本 PR 所修的是同一类缺陷,因此点明而非默默整理。

第 3 轮 —— 查测试是否空洞。 解释文案有两个分支共用"does not apply",只断言这一句无法区分它们。把两个分支合并会让三条相关用例同时转红,说明被锁住的是各自特有的措辞。

第 4 轮 —— 拿代码而非注释去核对分类学。 七个 reason 对七条措辞,BASELINE_REASON 的四个恰为 classifyProbeRun 实际设置的四个。本文件之外无人导入这些新类型,且每一处 ProbeResult 构造都带标签(别处三处未带标签的 inconclusiveMutantResult/HunkResult,回答的是另一个问题)。

已知并如实披露、而非掩饰:reason 从 ProbeRunFailure 传入 catch 这条线没有任何测试覆盖 —— runProbeSuite 位于一个会构建 git worktree 的 handler 内部,单元测试够不到接缝,也没有集成 fixture 能把 revert 探针驱动进那个 catch。分类器与错误各自有测试,它们之间那根线没有。

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

@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 — well-structured fix. The ProbeReason discriminated union makes untagged inconclusive a compile error, the shared heldForRedCollocatedTest + collocatedNotGreenDetail functions eliminate the duplicated flat wording, and the classification is correct per-file (gated vs no-tests vs not-in-results vs all-skipped). Tests are load-bearing: restoring the old flat wording reddens exactly 8 cases, deleting a reason tag is caught by both tsc and assertion. Integration test pins the exact #8368 regression. No correctness issues found.

@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 54 passed · 0 failed · 54 total

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

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

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

Verification report

PR #8374 — Deep Verification (round 2)

Verdict: merge-ready — 54/54 scripted assertions passed (A/B 26, wire-oracle 21, mutation kills 6, compile-error 1), 0 fail. Collocated unit suite 128/128 and integration suite 28/28 at head (targeted gates). Scoped tsc and ESLint clean (both proven live). No blocking findings.
Verified head: 15d1fa78c2629a50e27260410d377d37fef6e2b2 (HEAD^2, commit 7 of 7); base tip: 295230a48fce0871c4c1842f191c284eaf207bc7 (HEAD^1). The metadata snapshot's baseRefOid (4379755…) has drifted from the merge commit's first parent; on this merge-ref checkout HEAD^1 is the authoritative A/B base.

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

第 2 轮(follow-up)。PR 已从 1 个 commit 扩展到 7 个;中心主张不变,但机制更丰富(ProbeReason 七元联合、ProbeResult 判别联合、heldForRedCollocatedTest 单一决策、runnerFailureReason 按 spawn 结构判定、classifyProbeRun 每个 inconclusive 分支都带 reason 标记)。在隔离、无凭证容器中对新 head 重新实测(未沿用旧报告数字)。

  • 结论merge-ready。全部脚本化断言通过(计数见下方各表),无阻塞项。
  • A/B 结论:中心改动承重。base 措辞对判定完全盲(静态模板,恒为「compile or import error」);head 随 baseline 的 reason 变化 —— gated⇒「it was RED there」(base→head 翻转)、四种 inconclusive reason 各得其句、absent⇒「did not report it」、inert 与非 baseline reason 走「does not apply」防御分支。选择哪些候选被搁置与 base 逐字节等价greenProbes 推导未变)。
  • 次级主张runnerFailureReason 经真实 spawnSync 验证 —— 超时=ETIMEDOUTrunner-died、缺二进制=ENOENTnot-run;并实测证实旧版 /^runner (killed|spawn failed)/ 消息匹配在真实消息上不会触发(即 commit 6 所称「标记从未生效」属实)。classifyProbeRun 对 inconclusive 只发出 {no-output, not-in-results, no-tests, all-skipped},恰为解释函数接受的集合。
  • 承重性(vacuity):6 个单行变异全部被杀,各只红自己的用例;删一个 reason 标记同时被 tsc(TS2322)与运行时测试拦下(「caught twice」属实)。第 1 轮的 M4 存活(collected-nothing 句尾未锁定)已闭合 —— 该措辞已按 reason 拆分,no-tests 句尾现由 it.eachalsoPhrase 断言锁定。
  • findings:无阻塞项。仅一条非阻塞观察:三个非 baseline reason(control-failed/not-run/runner-died)的 REASON_PHRASE 全文未被测试逐字锁定(仅在「does not apply」括号内渲染,属不可达防御分支的人类散文)。
  • 未覆盖范围:未跑全仓测试/全仓 typecheck(只跑受影响文件的单元+集成套件与 cli 包定向 tsc/ESLint);逐 commit 归因不可达(shallow depth 2,本地仅 1 个 commit 可达,元数据有 7 个);仅 Linux。

Previous-finding status (follow-up round)

Round 1 verified head 7908854… (then commit 1 of 1) and reported merge-ready, 27/27. Six commits landed since; every measurement below was re-run at the new head, not carried forward.

# round-1 finding severity status at 15d1fa78c
1 central claim load-bearing (gated flips base→head via collocatedNotGreenDetail) stands, re-measured — same flip holds; the function now reads a machine-readable reason off the baseline and is exercised across the full 7-reason matrix (A/B table below).
2 selection of held probes unchanged from base stands, re-measuredgreenProbes = perFile.filter(inert).map(file) is byte-identical to base; heldForRedCollocatedTest holds iff own && !greenProbes.includes(own) (selection-equivalence cells in the A/B).
3 M4 survivor: collected-nothing sentence's parenthetical tail not pinned by any test non-blocking closed (fixed) — the collected-nothing wording was split into per-reason sentences; the no-tests tail ("…compile or import error…") is now asserted by the it.each alsoPhrase (expect(detail).toContain(alsoPhrase)). My M1/M2 mutations confirm the gated wording and the no-tests tag are each pinned.

Central claim + A/B

Central claim. When a mutant/hunk is held inconclusive because its collocated test was not green in the unmutated baseline, the report's detail now reads the reason off the baseline run — via one shared exported decision (heldForRedCollocatedTest) and one shared sentence builder (collocatedNotGreenDetail) — instead of base's flat, verdict-blind "likely a compile or import error in the probe tree".

The base cell is the verbatim HEAD^1 literal (git show HEAD^1:…test-efficacy.ts lines 2022/2067): a static template with no reason input, so it is verdict-blind by construction. The head cell imports the real collocatedNotGreenDetail / heldForRedCollocatedTest from packages/cli/dist/…/test-efficacy.js and drives a production-shaped baseline.perFile (ProbeResult[]). Witness: 01-ab-reason-matrix-base-vs-head.png.

cell base (HEAD^1 literal) head (dist export)
gated (ran, failed — the #8368 AuthDialog.test.tsx shape) "…compile or import error…" ❌ "…it was RED there…" ✅ — flips
inconclusive / no-tests "…compile or import error…" "…collected no tests there…"
inconclusive / not-in-results "…compile or import error…" "…produced results there but none for it…"
inconclusive / no-output "…compile or import error…" "…produced no parseable output…"
inconclusive / all-skipped "…compile or import error…" "…executed none of them…"
absent (no baseline entry) "…compile or import error…" "…the baseline did not report it…"
inconclusive / {control-failed,not-run,runner-died} (non-baseline, defensive) n/a "…the baseline did not classify it…does not apply…"
inert (green, defensive — unreachable via the hold) n/a "…reported it GREEN…does not apply…"
verdict sensitivity (same probe, vary reason) none (arity-2 template) yes
exact gated-mutant sentence n/a .toBe(…) matches the test's expected string
selection: x.ts (gated own) / ok.ts (inert own) / untested.ts (no own) holds / not / not holds / not / not — identical to base

26/26 A/B assertions passed. The two non-baseline arms (inert; control-failed/not-run/runner-died) are provably unreachable through the pipeline — greenProbes is exactly the inert files, and classifyProbeRun only emits the four baseline reasons (closure asserted in the wire harness) — so their "does not apply" wording is a defensive default, consistent with the PR's own scope note.

End-to-end corroboration (closes round-1 "no live run" gap). The integration suite drives a real probe tree in which f.test.ts fails an assertion (measured gated) and asserts the generated report's detail contains was RED there and does not contain compile or import error — i.e. the baseline-classification → reason-tag → sentence chain lands in a real artifact, not just a unit fixture. 28/28 at head.

Wire-oracle harnesses (secondary claims)

02-wire-runner-classify.png. 21/21 passed.

  • runnerFailureReason driven through real spawnSync (not hand-written strings): a process killed at a 300 ms deadline reports error.code=ETIMEDOUT, signal=SIGTERM, message "spawnSync /usr/local/bin/node ETIMEDOUT"runner-died; a missing binary reports ENOENT, signal=nullnot-run. Structural logic table (signal-only, ETIMEDOUT, ENOENT, ENOBUFS+signal, empty) all as specified; ProbeRunFailure carries the reason.
  • The old message-match is proven inoperative, not merely claimed. The commit-5 version matched /^runner (killed|spawn failed)/ against the thrown text; I tested that regex against the two real spawnSync messages above and it matched neither — so the tag it existed to produce was never produced, and the structure-read that replaced it is what makes the tag fire. This is the round's independent confirmation of commit 6's thesis.
  • classifyProbeRun reason tags driven through real vitest-JSON shapes: no-output, not-in-results, no-tests, all-skipped each tagged; gated/inert untagged ('reason' in r === false). Closure: every inconclusive reason it emits is in the baseline-accepted set {no-output, not-in-results, no-tests, all-skipped}.

Vacuity / mutation matrix

Positive control: unmutated source 128/128. Each mutation is a single unique-line replacement in the source (vitest transforms TS on the fly; dist untouched), restored byte-for-byte (git diff clean) after each. 03-mutation-matrix.png.

mutation failed which tests went red
unmutated (positive control) 0 — (128 green)
M1 gated phrase ⇒ collected-nothing (never says RED) 3 "says the test was red…", "names the probe…per kind", held "holds…and explains why"
M2 no-tests tag ⇒ all-skipped 1 "tags a file that collected nothing as no-tests"
M3 runnerFailureReason inverted 3 all three runnerFailureReason cases
M4 heldForRedCollocatedTest never holds 1 held "holds when the collocated test was not green"
M5 BASELINE_REASON gate disabled (renders non-baseline phrase) 3 the three "refuses to explain {not-run,runner-died,control-failed}" cases
M6 absent phrase changed 1 "says the baseline never reported a probe…"

6/6 killed, no survivors, each reddening exactly its own case and nothing else. M2 proves the round-3 "deleting a tag left all tests green" defect is now pinned at runtime; M5 proves the defensive baseline-reason gate is pinned.

Compile-error check (04-compile-error-untagged.png). Deleting reason: 'no-tests' as const, from classifyProbeRun makes scoped tsc fail with TS2322: the untagged arm (reason?: undefined) is not assignable to ProbeResult, whose inconclusive member requires reason: ProbeReason. Baseline scoped tsc is clean (exit 0). So an untagged inconclusive is caught twice — by tsc and by the M2 runtime test — exactly as the PR claims. Source restored clean afterward.

Findings

No blocking findings.

Non-blocking coverage observation. The full text of the three non-baseline REASON_PHRASE entries (control-failed, not-run, runner-died) is not asserted verbatim by any test: the "refuses to explain…" tests pin only toContain('the baseline did not classify it') and toContain('does not apply'), not the inner phrase. This is an ordinary coverage gap, not dead code — those phrases are rendered inside the parenthetical and are read by humans — but it falls on the defensive arms that the pipeline cannot reach, and the PR states detail is prose nothing parses. Not a merge condition. (The analogous round-1 gap on the collected-nothing tail is closed; see status table row 3.)

Not covered

  • Per-commit attribution is out of reach. The checkout is depth 2: git rev-list HEAD^1..HEAD^2 returns 1 commit at the shallow boundary while $QWEN_VERIFY_CONTEXT lists 7. I verified the aggregate HEAD^1..HEAD diff and did not exercise each commit's individual claim (e.g. commit 7 is docs/phrase-only; its routing effect is covered by the wire harness, but not isolated per commit).
  • Targeted gates only. Ran the affected file's unit suite (128/128), its integration suite (28/28), and cli-package tsc/ESLint (clean, both proven live). Did not re-run the repo-wide suite, repo-wide typecheck, or Prettier — repo-wide gates are CI's job, and the HEAD build already compiled the new code.
  • No full /review invocation. Verification is at the function level (real dist exports), the collocated suites (which drive a real probe tree end-to-end for the gated path), and the mutation/compile checks. I did not launch a complete /review run against a live PR; the integration suite's real-probe assertion is the closest substitute and it passes.
  • Linux only. The changed code is platform-agnostic (pure string lookup + spawn-structure read); path normalisation lives upstream in classifyProbeRun. macOS/Windows not exercised (the PR itself tested Linux only).

Methodology

Environment: CI verify container (node:22-bookworm, Node v22.23.2), merge-ref checkout at depth 2 (HEAD = merge commit, HEAD^1 = base tip 295230a48, HEAD^2 = PR head 15d1fa78c), npm ci + npm run build already complete at HEAD. A/B (01-ab.mjs): base cell is the verbatim HEAD^1 literal; head cell imports the real exports from dist and drives {gated, inert, absent, 4 baseline reasons, 3 non-baseline reasons} × {mutant, hunk} over a production-shaped perFile, plus a selection-equivalence matrix against base's predicate. Wire-oracle (02-wire.mjs): runnerFailureReason driven through real spawnSync (timeout kill + missing binary) and a structural logic table; the old /^runner (killed|spawn failed)/ regex tested against the real messages; classifyProbeRun driven through real vitest-JSON shapes. Mutation matrix (03-mutation.mjs): six single-line source mutations, each run against the full unit suite via vitest's JSON reporter and restored byte-for-byte (git diff clean, post-restore suite green). Compile-error check: delete one reason tag, scoped tsc -p packages/cliTS2322, restore. Gates: unit 128/128, integration 28/28, scoped tsc clean, scoped ESLint clean (gate proven live via a planted any ⇒ 1 error/exit 1). assertions.json (54 = 26 A/B + 21 wire + 6 mutation kills + 1 compile-error) counts only the independent oracle assertions authored here; the PR's own 128+28-test suites are reported as targeted gates, not double-counted. Raw logs in logs/; harnesses are rerunnable .mjs in this directory.

Evidence images

01-ab-reason-matrix-base-vs-head

02-wire-runner-classify

03-mutation-matrix

04-compile-error-untagged

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot qwen-code-ci-bot 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.

Reviewed. Suggestions are inline. Test Plan (not a blocker): src/ui/auth/AuthDialog.test.tsxno such file or directory.

中文说明

已审查。 建议见行内评论。 Test Plan(非阻断):src/ui/auth/AuthDialog.test.tsxno such file or directory

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

Comment on lines +927 to +929
}): ProbeReason {
return r.signal || r.error?.code === 'ETIMEDOUT' ? 'runner-died' : 'not-run';
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] runnerFailureReason re-derives the spawnSync death/timeout detection (error.code === 'ETIMEDOUT' / signal) that this directory already centralizes in the exported spawnTimedOut (build-test.ts:119). The convention to reuse it is documented in spawnTimedOut's own JSDoc and in test-delta.ts's reuse comment ("The sibling's predicate, not a weaker re-derivation") — a prior drift exactly like this one fed a silent "base is green". — Concrete cost: if the authoritative timeout signal changes (a Node version surfaces it differently, a non-default killSignal), the two predicates must be edited in lockstep; miss one and a probe suite that died at the deadline is misclassified not-run instead of runner-died.

Suggested change
}): ProbeReason {
return r.signal || r.error?.code === 'ETIMEDOUT' ? 'runner-died' : 'not-run';
}
}): ProbeReason {
return r.signal || spawnTimedOut(r) ? 'runner-died' : 'not-run';
}
中文说明

runnerFailureReason 重新推导了 spawnSync 的死亡/超时检测(error.code === 'ETIMEDOUT' / signal),而本目录已在导出的 spawnTimedOutbuild-test.ts:119)中集中处理。复用约定记录在 spawnTimedOut 的 JSDoc 和 test-delta.ts 的复用注释中("The sibling's predicate, not a weaker re-derivation")——此前一次完全相同的偏差曾导致静默的 "base is green"。— 具体代价:若权威的超时信号发生变化(Node 版本以不同方式呈现、设置了非默认的 killSignal),两个谓词必须同步修改;漏改其一,一个在截止时间死去的探针套件会被误判为 not-run 而非 runner-died

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@wenshao
wenshao added this pull request to the merge queue Aug 2, 2026
Merged via the queue into main with commit 783787c Aug 2, 2026
78 of 79 checks passed
@wenshao
wenshao deleted the fix/efficacy-baseline-reason branch August 2, 2026 16:11
wenshao added a commit that referenced this pull request Aug 2, 2026
@wenshao

wenshao commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

Local verification on macOS — real build, real probe run

Verified at 15d1fa78c against main@437975547 (the merge base). Not unit tests standing in for the pipeline: two bundles built from source (npm run build -- --cli-only && npm run bundle), and the actual qwen review test-efficacy subcommand run end to end against a purpose-built fixture repository, once per binary.

The PR body marks macOS not tested. It is now: macOS 26.6 (arm64), Node v24.18.1, vitest 3.2.4.

The fixture

A real git repo with two commits, so the probe has a genuine base..HEAD to work with. Four collocated pairs, chosen so that a single run exercises every branch the change touches — including the one the report used to name unconditionally:

source collocated test what vitest actually did baseline verdict
green.ts green.test.ts 2 collected, 2 passed inert — so greenProbes > 0 and mutants really run
red.ts red.test.ts compiled, 3 collected, 1 failed gated — the AuthDialog.test.tsx shape from #8368
broken.ts broken.test.ts import error, 0 collected inconclusive / no-tests — a genuine import error
gate.ts gate.test.ts compiled, 2 collected, 1 failed gated, reached through the hunk loop, not the mutant loop

gate.ts's diff carries no safety verb, so it produces a hunk candidate rather than a mutant — that is what puts both of the loops this PR unified into the same run.

The per-file counts above are measured, not assumed:

$ node node_modules/vitest/vitest.mjs run <the three probe files> --reporter=json
broken.test.ts       collected= 0 passed=0 failed=0
gate.test.ts         collected= 2 passed=1 failed=1
red.test.ts          collected= 3 passed=2 failed=1

1. The misdiagnosis reproduces, and the PR fixes it

Same fixture, same probe run, two binaries. Before, all three holds name a compile or import error. Exactly one of the three has one.

before and after on a real run

Both the mutant and the hunk hold now route through the one function, and each sentence matches what was measured for that file. The red.ts line is the #8368 case reproduced from scratch: a test that compiled, collected 3 and failed 1, previously reported as an import problem that was never there.

2. The artifact change is additive

the serialised probe entry

reason is a new key on the inconclusive arm; nothing else in the report moved. I grepped for consumers: no code in the repo parses probed[]lib/agent-briefs.ts directs Agent 7 to findings[] and the mutants.* / hunks.* counters, and the detail prose is read only by the review agent itself. So the addition can only help a consumer, and the prose change lands exactly where it was aimed.

3. The new tests are load-bearing

mutation experiments

  • (A) restore the pre-PR flat wording12 failed | 116 passed (128), and the integration suite's new assertion catches it independently: 1 failed | 27 passed (28).
  • (B) delete one reason tag (reason: 'no-tests' as const,) → tsc 1 error (TS2322, the union rejecting the untagged arm) and 1 failed | 127 passed (128). Caught twice, as claimed.

Both mutations were applied to the PR's own source and reverted afterwards; the tree was clean before and after.

4. Regressions

check result
vitest run --root packages/cli src/commands/review/test-efficacy.test.ts 128 passed
vitest run --root packages/cli src/commands/review/test-efficacy.integration.test.ts 28 passed
whole src/commands/review/ suite 48 files, 1513 passed
tsc --noEmit -p packages/cli clean
eslint on the three changed files clean

runnerFailureReason's tests drive real spawnSync ETIMEDOUT / ENOENT — the platform-sensitive part of this diff — and they pass on macOS, which is the row the PR body could not fill in.

Notes — none blocking

  1. The no-tests sentence nests an em-dash inside an em-dash clause. In real output it reads: "… did not run green in the unmutated baseline — it collected no tests there — the shape a compile or import error in the probe tree takes, so the remaining probes passing cannot show …". The inner clause is a gloss on the reason, but at a glance it parses as a second top-level clause (visible in the middle block of the first screenshot). A comma or parentheses around the shape … would read better. Cosmetic, and only in this one reason.
  2. The Reviewer Test Plan's mutation figures do not reproduce at this revision. The body reports 8 failed | 116 passed (124); the file holds 128 tests at 15d1fa78c, and restoring the flat wording reddens 12. Those numbers were measured on an earlier revision of the branch. The claim they support is not just intact but stronger — worth refreshing so a reviewer reproducing them is not surprised.
  3. One report-visible change is slightly wider than "the hold sentence". Splitting !result from assertions.length === 0 in classifyProbeRun also changes the probed[].detail prose for a file absent from the results (now "the run produced results but none for this file … a path that did not match"). It is the right split and is exactly what makes not-in-results distinguishable — it is just not called out in Risk & Scope, which mentions only the new reason key.

Verdict: behaves as described. The stated defect reproduces on main and is gone at 15d1fa78c; both loops produce the corrected sentence from one place; the guard's hold decision is unchanged, as claimed; the tests fail when the behaviour is removed; nothing else in the review command suite regressed. Good to merge from my side — the three notes are follow-ups, not conditions.

中文版

本地 macOS 真实环境验证

15d1fa78c 上、以 main@437975547(merge base)为对照做的验证。没有用单元测试代替流水线:从源码分别构建了两个 bundlenpm run build -- --cli-only && npm run bundle),然后用真实的 qwen review test-efficacy 子命令,对一个专门构造的 fixture 仓库各完整跑了一遍。

PR 描述里 macOS 一栏是未测试,现在补上了:macOS 26.6(arm64)、Node v24.18.1、vitest 3.2.4。

fixture 设计

一个真实的 git 仓库,两个提交,让探针有真正的 base..HEAD 可用。四组 collocated 配对,目的是让一次运行同时覆盖到本次改动涉及的每个分支——包括此前被一律套用同一句解释的那个分支:

源文件 collocated 测试 vitest 实测行为 基线判定
green.ts green.test.ts 收集 2 条、全通过 inert —— 保证 greenProbes > 0,mutant 才会真正运行
red.ts red.test.ts 编译正常,收集 3 条、失败 1 条 gated —— 即 #8368AuthDialog.test.tsx 的形态
broken.ts broken.test.ts 导入错误,收集 0 条 inconclusive / no-tests —— 真正的导入错误
gate.ts gate.test.ts 编译正常,收集 2 条、失败 1 条 gated,且走的是 hunk 循环而非 mutant 循环

gate.ts 的 diff 不含 safety verb,所以它产出的是 hunk 候选而不是 mutant —— 这正是让本 PR 合并的那两个循环同时出现在同一次运行里的办法。

上表的每文件计数是实测的,不是推断的:

$ node node_modules/vitest/vitest.mjs run <三个探针文件> --reporter=json
broken.test.ts       collected= 0 passed=0 failed=0
gate.test.ts         collected= 2 passed=1 failed=1
red.test.ts          collected= 3 passed=2 failed=1

1. 误诊可复现,且本 PR 修好了它

同一个 fixture、同一轮探针、两个二进制。改动前三处 hold 全部声称是编译或导入错误;三者中恰好只有一个真是。

见上文第一张截图。两个循环(mutant 与 hunk)的 hold 现在都经由同一个函数产出,每句话都与该文件的实测结果一致。其中 red.ts 那条就是从零复现出来的 #8368 情形:一个编译正常、收集 3 条、失败 1 条的测试,此前被报告成一个根本不存在的导入问题。

2. 产物结构的改动是增量的

见第二张截图。reasoninconclusive 分支上新增的键,报告里其余部分没有移动。我检索了消费方:仓库里没有任何代码解析 probed[] —— lib/agent-briefs.ts 指引 Agent 7 去看的是 findings[] 以及 mutants.* / hunks.* 计数器,而 detail 这段散文只有评审 agent 自己在读。所以这次新增对消费方只增不减,措辞改动也恰好落在它本该影响的地方。

3. 新增测试确实承重

见第三张截图。

  • (A) 把 PR 之前那句写死的措辞恢复回去12 failed | 116 passed (128);集成测试里新增的断言也独立拦下了它:1 failed | 27 passed (28)
  • (B) 删掉一个 reason 标记reason: 'no-tests' as const,)→ tsc 报 1 个错(TS2322,联合类型拒绝未打标记的分支)并且 1 failed | 127 passed (128)。确实被拦了两次。

两次变异都施加在 PR 自身源码上并在之后还原;前后工作树都是干净的。

4. 回归检查

检查项 结果
test-efficacy.test.ts 128 通过
test-efficacy.integration.test.ts 28 通过
整个 src/commands/review/ 测试套件 48 个文件、1513 条通过
tsc --noEmit -p packages/cli 干净
三个改动文件的 eslint 干净

runnerFailureReason 的测试是通过真实 spawnSyncETIMEDOUT / ENOENT 驱动的 —— 这是本 diff 里对平台最敏感的部分 —— 它们在 macOS 上通过,正好补上 PR 描述里空着的那一行。

备注 —— 均不阻塞合并

  1. no-tests 那句话在破折号子句里又嵌了一个破折号。 真实输出读起来是:"…… did not run green in the unmutated baseline — it collected no tests there — the shape a compile or import error in the probe tree takes, so ……"。内层子句本意是对 reason 的补充说明,但乍看会被读成第二个并列子句(第一张截图中间那段可见)。给 the shape … 加逗号或括号会更好读。属于观感问题,且只出现在这一个 reason 上。
  2. 测试计划里的变异数字在当前修订上复现不出来。 描述写的是 8 failed | 116 passed (124);而在 15d1fa78c 上该文件有 128 条测试,恢复写死措辞会红 12 条。那组数字是在分支较早的修订上测的。它要支撑的结论不但成立,而且更强 —— 建议刷新一下,免得复现的人困惑。
  3. 有一处对报告可见的改动,略微超出「那句 hold 措辞」的范围。 classifyProbeRun!resultassertions.length === 0 里拆出来之后,一个未出现在结果中的文件其 probed[].detail 散文也变了(现在是 "the run produced results but none for this file …… a path that did not match")。这个拆分是对的,也正是 not-in-results 能被区分出来的原因 —— 只是「风险与影响范围」里只提到了新增的 reason 键,没提这一条。

结论:行为与描述一致。 所述缺陷在 main 上可复现、在 15d1fa78c 上消失;两个循环从同一处产出修正后的句子;hold 的判定条件如描述所言未改变;行为被移除时测试会失败;review 命令套件其余部分无回归。从我这边看可以合并 —— 上述三条是后续项,不是合并条件。

@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. Test Plan (not a blocker): src/ui/auth/AuthDialog.test.tsxno such file or directory.

中文说明

已审查。 建议见行内评论。 Test Plan(非阻断):src/ui/auth/AuthDialog.test.tsxno such file or directory

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

Comment on lines +945 to +947
const BASELINE_REASON = new Set<ProbeReason>([
'no-output',
'not-in-results',

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.

[Suggestion] BASELINE_REASON is the one invariant in this design that the compiler does not enforce — a runtime Set that must stay in sync with the reasons classifyProbeRun produces, surrounded by machinery that makes every other sync obligation compile-time (REASON_PHRASE: Record<ProbeReason, string>, the ProbeResult union). — Failure scenario: a maintainer adds a new ProbeReason (e.g. 'partial-output'), adds it to REASON_PHRASE (compiler forces this), tags a new classifyProbeRun branch (union forces this), but omits it from BASELINE_REASON. collocatedNotGreenDetail then hits the !BASELINE_REASON.has(entry.reason) branch and emits "the baseline did not classify it" for a reason that IS a valid baseline classification — the exact misleading wording this PR exists to eliminate, one layer down.

Suggested change
const BASELINE_REASON = new Set<ProbeReason>([
'no-output',
'not-in-results',
const BASELINE_REASON = new Set<ProbeReason>([
'no-output',
'not-in-results',
'no-tests',
'all-skipped',
] satisfies readonly ProbeReason[]);

Consider defining a BaselineReason subtype so the compiler checks the boundary.

中文说明

BASELINE_REASON 是本设计中唯一一个编译器未强制的不变量 —— 一个必须与 classifyProbeRun 产出的 reason 保持同步的运行时 Set,而周围的所有其他同步义务都已由编译器保证(REASON_PHRASE: Record<ProbeReason, string>ProbeResult 联合类型)。失败场景:维护者新增一个 ProbeReason(如 'partial-output'),加入 REASON_PHRASE(编译器强制),在 classifyProbeRun 中新打一个分支(联合类型允许),但忘了加入 BASELINE_REASONcollocatedNotGreenDetail 就会走到 !BASELINE_REASON.has(entry.reason) 分支,对一个确实是有效基线分类的 reason 输出「基线未对其进行分类」—— 恰好是本 PR 要消除的那种误导性措辞,只是下移了一层。建议定义一个 BaselineReason 子类型,让编译器检查边界。

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

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

4 participants