Skip to content

fix(web-shell): stop rendering unrecognized daemon events in transcripts - #8812

Merged
ytahdn merged 9 commits into
mainfrom
fix/web-shell-hide-unrecognized-debug
Aug 10, 2026
Merged

fix(web-shell): stop rendering unrecognized daemon events in transcripts#8812
ytahdn merged 9 commits into
mainfrom
fix/web-shell-hide-unrecognized-debug

Conversation

@wenshao

@wenshao wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This PR stops Web Shell from rendering the daemon UI normalizer's "I don't know this frame" debug projections as conversation content. The normalizer now stamps a structured debugReason on every debug event it produces, and Web Shell branches on that instead of pattern-matching the debug text.

Web Shell is the primary entry point for daemon-backed sessions, and it is the only surface where these projections are user-visible — so this is a user-facing defect on the main path, not a niche renderer detail. It should land ahead of further per-kind suppressions.

Why it's needed

The normalizer projects any frame it has no case for into a debug event whose text is a raw JSON dump of the payload. webui's ChatViewer drops those blocks (packages/webui/src/daemon/transcriptAdapter.ts:56), but Web Shell renders status and debug together as a system info message (packages/web-shell/client/adapters/transcriptToMessages.ts). So every event kind the daemon ships ahead of the UI surfaces in Web Shell as an unreadable JSON row in the middle of the conversation.

This has been patched per-symptom three times already:

Each fix covers exactly one kind, and the next new daemon event leaks again. This PR addresses the classification instead.

debugReason splits the debug channel into three cases:

  • unrecognized_event / unrecognized_session_update — the daemon runs ahead of this client. Developer diagnostics, not conversation content; Web Shell no longer renders them.
  • malformed_payload — a frame the client does have a case for arrived unusable. That signals an actual defect, so it stays visible.
  • No debugReason at all — debug events dispatched by clients themselves, such as Web Shell's own model-switch summary (App.tsx, source: 'model_switch_summary'). These keep rendering; the filter must not sweep them up.

The two (unrecognized daemon event) prefix checks are now covered by debugReason and are removed. The Model switched: check stays: model.changed projects to a status block, not a debug one.

Reviewer Test Plan

How to verify

  1. Start a daemon-backed Web Shell session and trigger any daemon event kind the normalizer has no case for. A convenient one: register a stdio MCP server whose name contains a2ui exposing a tool that returns an A2UI command array plus fallback text, set tools.toolSearch.enabled: false so the tool is declared upfront, and prompt the model to call it — the ACP bridge republishes the commands as sessionUpdate: 'a2ui', which no normalizer case handles.
  2. Confirm no raw JSON row appears in the transcript, while the tool call, assistant text and token accounting remain visible.
  3. Confirm the frame is still on the wire: subscribe to GET /session/:id/events and check the a2ui frame is still delivered.
  4. Switch models from the Web Shell model picker and confirm the model-switch summary still appears in the transcript (it is a client-dispatched debug block with no debugReason).

Evidence (Before & After)

Verified against a real qwen serve daemon with an isolated QWEN_HOME, a recording mock OpenAI-compatible provider, a stdio MCP server named a2ui, and the real Web Shell in Chrome.

The verification build deliberately contains no case 'a2ui' in the normalizer — grep 'case"a2ui"' dist/web-shell/assets/index-*.js returns 0 — so what the screenshot shows is the classification fix alone suppressing a kind nothing special-cases.

Before (build without this change): the transcript carries a full a2ui: { "sessionUpdate": "a2ui", "a2ui": { "surfaceId": ..., "commands": [...] } } row.

Before: raw JSON row in the Web Shell transcript

After (this change, still no per-kind case): same prompt, header still reports one tool call, only Surface presented. remains.

After: the JSON row is gone, only the assistant message remains

A follow-up SSE capture confirms the a2ui frame is still emitted once — the frame is unaffected, only its transcript projection changed.

Unit coverage: the normalizer stamps each of the three reasons; the Web Shell adapter drops both unrecognized_* reasons, keeps malformed_payload, and keeps client-dispatched debug blocks with their source/data intact. Removing the filter line makes two of those tests fail (mutation-checked).

Tested on

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

Environment (optional)

macOS, local Node.js workspace, real qwen serve daemon + real Web Shell. Full sdk-typescript (1484), webui (454) and web-shell (2944) suites pass, plus lint and typecheck on both packages.

Risk & Scope

  • Main risk or tradeoff: unrecognized daemon frames become invisible in Web Shell rather than appearing as JSON. That is the intent, but it does mean a daemon/UI version skew is no longer self-announcing in the transcript. rawEvent still carries the original envelope for debug panels, and malformed_payload — the case that indicates a real defect — stays visible.
  • Not validated / out of scope: surfacing unrecognized frames in a dedicated debug view, webui's own debug handling (it already drops these blocks), and rendering A2UI surfaces.
  • Breaking changes / migration notes: none. debugReason is an optional field on DaemonUiStatusEvent and DaemonStatusTranscriptBlock; consumers that ignore it behave exactly as before.

Linked Issues

#8790 suppressed usage_update and #8808 would have suppressed a2ui, one event kind each. This PR fixes the classification both work around, so no further per-kind suppression is needed — #8808 has been closed in favour of this one. Since Web Shell is the main entry point for daemon-backed sessions, this is a user-facing defect on the main path.

中文说明

本 PR 的改动

本 PR 让 Web Shell 不再把 daemon UI normalizer "我不认识这个帧" 的 debug 投影当作对话内容显示。normalizer 现在给它产生的每个 debug 事件打上结构化的 debugReason,Web Shell 依据它分支,而不是去匹配 debug 文本。

Web Shell 是 daemon 会话的主入口,也是唯一会把这些投影暴露给用户的界面——所以这是主路径上的用户可见缺陷,而不是某个渲染器的边角细节,应当优先于继续按类型逐个屏蔽。

为什么需要

normalizer 会把任何没有对应分支的帧投影成 debug 事件,文本是 payload 的原始 JSON。webui 的 ChatViewer 会丢弃这些块(packages/webui/src/daemon/transcriptAdapter.ts:56),而 Web Shell 把 statusdebug 一起渲染成 system 信息(packages/web-shell/client/adapters/transcriptToMessages.ts)。因此,daemon 每领先 UI 增加一种事件类型,Web Shell 就会在对话中间出现一行无法阅读的 JSON。

这个症状已经被逐个打过三次补丁:

每次修复只覆盖一种类型,下一个新事件照样泄漏。本 PR 改的是分类本身。

debugReason 把 debug 通道拆成三种情况:

  • unrecognized_event / unrecognized_session_update——daemon 领先于当前客户端。属于开发者诊断信息而非对话内容,Web Shell 不再渲染。
  • malformed_payload——客户端确实有分支的帧带着不可用的 payload 到达。这说明真的出了问题,因此保持可见。
  • 完全没有 debugReason——客户端自己派发的 debug 事件,例如 Web Shell 自己的模型切换摘要(App.tsx,source: 'model_switch_summary')。这些继续渲染,过滤不能把它们一起扫掉。

两条 (unrecognized daemon event) 前缀检查已由 debugReason 覆盖,予以删除。Model switched: 那条保留:model.changed 投影成的是 status 块,不是 debug 块。

审查者测试计划

验证方法

  1. 启动 daemon 驱动的 Web Shell 会话,触发任意一种 normalizer 没有分支的 daemon 事件。一个方便的选择:配置名字含 a2ui 的 stdio MCP server,提供返回 A2UI 命令数组 + fallback 文本的工具,设置 tools.toolSearch.enabled: false 让工具直接声明,然后提示模型调用它——ACP bridge 会把命令重新发成 sessionUpdate: 'a2ui',而 normalizer 没有对应分支。
  2. 确认 transcript 中不再出现原始 JSON 行,同时工具调用、助手文本和 token 统计仍然可见。
  3. 确认帧仍在线上:订阅 GET /session/:id/events,检查 a2ui 帧仍被投递。
  4. 在 Web Shell 的模型选择器里切换模型,确认模型切换摘要仍显示在 transcript 中(它是客户端派发的、没有 debugReason 的 debug 块)。

证据(修复前与修复后)

在真实 qwen serve daemon(隔离 QWEN_HOME)、记录型 mock OpenAI 兼容服务、名为 a2ui 的 stdio MCP server 以及 Chrome 中的真实 Web Shell 上验证。

验证用的构建故意不包含 normalizer 里的 case 'a2ui'——grep 'case"a2ui"' dist/web-shell/assets/index-*.js 结果为 0——因此截图展示的是分类修复本身挡住了一个没有任何专门处理的类型。

修复前(不含本改动的构建):transcript 中出现完整的 a2ui: { "sessionUpdate": "a2ui", "a2ui": { "surfaceId": ..., "commands": [...] } } 行。

修复后(本改动,仍然没有按类型的分支):同一条 prompt,头部仍显示一次工具调用,只剩 Surface presented.

随后再抓一次 SSE,确认 a2ui 帧仍然发出一次——帧本身不受影响,变的只是它的 transcript 投影。

单元测试覆盖:normalizer 会打上三种 reason;Web Shell 适配器丢弃两种 unrecognized_*,保留 malformed_payload,并保留客户端派发的 debug 块及其 source/data。删掉过滤那一行会让其中两个测试失败(已做变异验证)。

测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

macOS、本地 Node.js workspace、真实 qwen serve daemon + 真实 Web Shell。sdk-typescript(1484)、webui(454)和 web-shell(2944)完整测试套件全部通过,两个包的 lint 与 typecheck 亦通过。

风险与范围

  • 主要风险或权衡:未识别的 daemon 帧在 Web Shell 中变为不可见,而不是以 JSON 形式出现。这正是本意,但也意味着 daemon 与 UI 的版本错配不再会在 transcript 里自我暴露。rawEvent 仍然保留原始事件信封供调试面板使用,而真正表示缺陷的 malformed_payload 保持可见。
  • 未验证 / 范围外:在专门的调试视图中展示未识别帧、webui 自身的 debug 处理(它已经丢弃这些块),以及 A2UI surface 的渲染。
  • 破坏性变更 / 迁移说明:无。debugReasonDaemonUiStatusEventDaemonStatusTranscriptBlock 上的可选字段,忽略它的消费者行为与此前完全一致。

关联 Issue

#8790 屏蔽了 usage_update,#8808 本来要屏蔽 a2ui,各自只覆盖一种事件类型。本 PR 修的是两者共同绕开的分类问题,因此不再需要继续按类型逐个屏蔽——#8808 已因本 PR 关闭。鉴于 Web Shell 是 daemon 会话的主入口,这是主路径上的用户可见缺陷。

The daemon UI normalizer projects any frame it has no case for into a
`debug` event carrying a raw JSON dump. webui's ChatViewer drops those
blocks, but Web Shell renders `status` and `debug` together as system
info, so every event kind the daemon ships ahead of the UI surfaces as
unreadable JSON in the middle of the conversation. This has been patched
per-symptom three times now: two string-prefix suppressions inside
`isIgnoredWebShellStatus`, plus #8790 for `usage_update`.

Give the normalizer's debug events a structured `debugReason` and let
Web Shell branch on it instead of pattern-matching text:

- `unrecognized_event` / `unrecognized_session_update` — the daemon runs
  ahead of this client; developer diagnostics, not conversation content.
  Web Shell no longer renders them.
- `malformed_payload` — a frame the client does know arrived unusable.
  That is a real defect signal, so it stays visible.

Debug events dispatched by clients themselves, such as Web Shell's own
model-switch summary, carry no `debugReason` and keep rendering.

The two `(unrecognized daemon event)` prefix checks are now covered by
`debugReason` and are removed; the `Model switched: ` check stays, since
`model.changed` projects to a `status` block rather than a debug one.
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

Rendered against a mock daemon (no real backend): the PR base vs this PR head 1d8a5d7. Only screenshots that changed are shown (flows below, if any, are head-only) — refreshes on every push.

Screenshots · before / after

ℹ️ No screenshot changed against the PR base — but this PR edits 1 render-shaping file:

  • packages/web-shell/client/components/MessageList.tsx

Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to packages/web-shell/client/e2e/visuals/screenshots.spec.ts that seeds whatever state the UI is gated on; it then appears here as a head-only (NEW) capture.

Full-resolution recordings (.webm) are attached to the workflow run.

Qwen Code · web-shell visuals

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.81% 83.81% 89.75% 83.02%
Core 87.86% 87.86% 89.39% 86.36%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.81 |    83.02 |   89.75 |   83.81 |                   
 src               |   84.97 |    81.29 |   88.49 |   84.97 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |    72.8 |    77.39 |   80.76 |    72.8 | ...1299-1303,1424 
  ...ractiveCli.ts |   86.74 |    81.15 |   88.13 |   86.74 | ...2955,2961,3026 
  ...liCommands.ts |   89.33 |     85.6 |      90 |   89.33 | ...01,518,552,674 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   71.19 |    73.65 |   90.84 |   71.19 |                   
  acpAgent.ts      |   70.59 |    73.45 |   90.37 |   70.59 | ...29,12234-12236 
  ...k-reporter.ts |     100 |    80.95 |     100 |     100 | 77,80,115,135     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...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,242-243 
 ...ration/session |   91.49 |    86.98 |   96.71 |   91.49 |                   
  Session.ts       |   90.51 |    85.18 |   95.94 |   90.51 | ...90,10717-10721 
  ...entTracker.ts |    96.8 |    89.36 |      90 |    96.8 | 137-143,221       
  ...projection.ts |   98.57 |    93.29 |     100 |   98.57 | ...76,333,344,356 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   93.44 |    91.74 |     100 |   93.44 | 74,85-88,115-125  
  ...y-replayer.ts |   98.54 |    95.65 |     100 |   98.54 | 241-243           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...lure-guard.ts |   98.32 |    97.75 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   96.01 |    94.15 |   96.66 |   96.01 |                   
  ...ageEmitter.ts |   95.95 |       96 |     100 |   95.95 | 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.47 |     100 |   99.18 | 355-356           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/agent-view    |   89.03 |    81.31 |   89.09 |   89.03 |                   
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  ...sor-client.ts |   80.38 |       72 |   76.66 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    89.47 |   84.61 |   96.61 | 129-130,150-151   
  ...sor-runner.ts |    84.9 |     75.6 |      85 |    84.9 | ...44,468,471-481 
  ...sor-server.ts |   85.71 |    83.06 |   95.45 |   85.71 | ...67-468,471-488 
  ...isor-store.ts |   97.73 |    81.16 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |     91.3 |   83.33 |   93.98 | 228-238           
 src/commands      |   90.81 |    79.61 |   66.66 |   90.81 |                   
  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.66 |      100 |      50 |   98.66 | 86                
  serve.ts         |   89.84 |    77.32 |     100 |   89.84 | ...50,853-856,868 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   88.91 |    88.48 |   90.54 |   88.91 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   95.21 |    96.73 |   88.88 |   95.21 | ...18-221,266-269 
  ...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.96 |    85.33 |   94.23 |   93.96 | ...1229,1236-1237 
  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       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    85.8 |    82.17 |      88 |    85.8 | ...85,591-594,606 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.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.31 |    84.61 |   83.33 |   90.31 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   93.15 |    84.84 |      80 |   93.15 | ...78-180,198-199 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |    87.4 |    87.94 |   88.33 |    87.4 |                   
  agent-prompt.ts  |   93.45 |    91.63 |   97.22 |   93.45 | ...2399,2513-2593 
  base-tree.ts     |   76.16 |    80.76 |   77.77 |   76.16 | ...50-371,373-386 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  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 |   96.33 |    91.85 |      96 |   96.33 | ...1916,1944-1966 
  cost-ledger.ts   |   94.67 |    95.86 |   78.57 |   94.67 | ...04-505,545-555 
  drive.ts         |   76.07 |    85.71 |   81.81 |   76.07 | ...90-492,497-499 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-pr.ts      |    76.7 |    68.75 |   63.63 |    76.7 | ...95,417,450-455 
  findings.ts      |   89.35 |    89.13 |   95.45 |   89.35 | ...15-918,927-928 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.54 |     92.3 |   66.66 |   85.54 | 67-72,131-136     
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.66 |    96.55 |     100 |   99.66 | 404               
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   81.77 |    80.86 |   92.85 |   81.77 | ...1043,1072-1074 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ish-assets.ts |   77.18 |    82.14 |   71.42 |   77.18 | ...85-531,533-544 
  repo-context.ts  |   94.92 |    90.82 |     100 |   94.92 | ...67-368,376-377 
  ...ve-anchors.ts |   77.77 |    88.88 |      75 |   77.77 | ...77-182,194-211 
  run.ts           |   82.16 |    87.12 |   91.66 |   82.16 | ...52,468-516,529 
  save-artifact.ts |    89.9 |    81.81 |   94.11 |    89.9 | ...08-311,404-407 
  script-lint.ts   |   81.14 |    79.23 |   88.88 |   81.14 | ...59-773,775-797 
  submit.ts        |    84.1 |     84.7 |    90.9 |    84.1 | ...66,555,582-618 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  test-efficacy.ts |   88.04 |    84.12 |   95.45 |   88.04 | ...2602,2610-2630 
  test-plan.ts     |   91.44 |    91.39 |   89.47 |   91.44 | ...38-839,903-920 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |   96.95 |    94.77 |   97.68 |   96.95 |                   
  agent-briefs.ts  |   98.96 |      100 |      50 |   98.96 | 719-720           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  authorization.ts |    92.4 |    92.59 |     100 |    92.4 | 127-133           
  budget.ts        |     100 |    96.29 |     100 |     100 | 370,401           
  coverage.ts      |   94.48 |    94.57 |      96 |   94.48 | ...72-489,526-537 
  deadline.ts      |   97.68 |    91.22 |     100 |   97.68 | 140-141,190,352   
  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            |   86.42 |    91.83 |      75 |   86.42 | ...52,289-290,317 
  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 
  ...ry-context.ts |   96.19 |    94.93 |     100 |   96.19 | ...90-491,496-499 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |     87.5 |     100 |     100 | 92                
  prompt-record.ts |   97.88 |    93.87 |     100 |   97.88 | 260-261,267       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   97.26 |    91.42 |     100 |   97.26 | 49-50             
  report.ts        |   94.68 |    93.75 |     100 |   94.68 | 189-193           
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 184               
  retirement.ts    |     100 |     92.3 |     100 |     100 | ...37,317-318,457 
  review-footer.ts |     100 |      100 |     100 |     100 |                   
  roster.ts        |     100 |    95.71 |     100 |     100 | 145,163,208       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.11 |    94.04 |     100 |   98.11 | 416,457,497-498   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.59 |     94.5 |     100 |   96.59 | ...08,297-298,323 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 172               
  workspaces.ts    |     100 |     95.9 |     100 |     100 | ...27,452,499,512 
  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.84 |    89.74 |   96.22 |   94.84 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   88.93 |    88.59 |   83.33 |   88.93 | ...2451,2453-2461 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   96.42 |    93.22 |      95 |   96.42 | ...69-570,624-625 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |   97.43 |       50 |     100 |   97.43 | 236-239           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.96 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.27 |    92.64 |      90 |   91.27 | ...1030,1032-1033 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.47 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    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.98 |    77.27 |   84.12 |   80.98 |                   
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...31-632,635-636 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |    44.9 |    66.19 |   55.26 |    44.9 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   55.01 |    67.14 |   58.33 |   55.01 | ...15-624,639-644 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   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.1 |    94.16 |   95.23 |    98.1 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1415,1431-1432 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.49 |      100 |   90.47 |   98.49 | 85-86,126-127     
  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.51 |    83.77 |   90.46 |   87.51 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.43 |    93.05 |     100 |   93.43 | ...20-321,324-326 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 672               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.89 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   88.59 |    93.68 |   96.29 |   88.59 | ...95-207,451-454 
  ...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.42 |    84.44 |    97.1 |   92.42 | ...1466,1520-1524 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.1 |    77.83 |   94.73 |    90.1 | ...1014,1021-1026 
  daemon-logger.ts |    82.2 |    77.42 |   91.76 |    82.2 | ...1720,1747-1753 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.57 |     90.8 |     100 |   98.57 | ...1411,1413-1414 
  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 
  ...d-provider.ts |   92.06 |    86.95 |     100 |   92.06 | ...72,287-293,316 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.89 |    90.25 |     100 |   94.89 | ...24,702,718,728 
  fast-path.ts     |   90.99 |    81.38 |   95.45 |   90.99 | ...33-542,608-609 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-144             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...30-131,142-143 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   83.96 |    80.01 |   75.26 |   83.96 | ...7435,7441-7442 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.22 |    88.99 |     100 |   94.22 | ...27,531-532,572 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   90.58 |    91.18 |   71.81 |   90.58 | ...2718,2732-2736 
  ...-admission.ts |   98.24 |    94.73 |     100 |   98.24 | 79-80,303-304     
  ...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 | ...20,823,836-838 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   92.18 |    88.37 |     100 |   92.18 | ...21-224,267-270 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   93.89 |     87.5 |     100 |   93.89 | ...18-519,525-526 
  ...e-remember.ts |   98.23 |    92.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.63 |    84.26 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   77.89 |    79.56 |   93.03 |   77.89 |                   
  ...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.55 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   73.19 |    76.77 |      94 |   73.19 | ...5165,5213-5219 
  index.ts         |   82.23 |    80.11 |   91.07 |   82.23 | ...2341,2425-2426 
  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 |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 src/serve/fs      |   86.39 |    80.74 |     100 |   86.39 |                   
  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.16 |    79.55 |     100 |   86.16 | ...2510,2520-2521 
 src/serve/live    |   77.28 |    69.21 |   89.91 |   77.28 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  ...-workspace.ts |   88.63 |    82.53 |     100 |   88.63 | ...40-241,253-254 
  discovery.ts     |   85.77 |    76.92 |      90 |   85.77 | ...49-250,255-256 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.75 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |   45.17 |    81.96 |   68.18 |   45.17 | ...80-381,395-407 
  ...oordinator.ts |   76.17 |     64.4 |   85.36 |   76.17 | ...1858,1949-1950 
  ...controller.ts |   67.82 |    79.31 |   72.72 |   67.82 | ...66-278,287-295 
  ...ak-to-user.ts |   96.66 |      100 |   83.33 |   96.66 | 37-38             
  ...sk-service.ts |   86.22 |    59.64 |   93.33 |   86.22 | ...1152,1175-1182 
  ...task-tools.ts |      99 |      100 |   85.71 |      99 | 205-206           
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.83 |    77.58 |     100 |   94.83 | ...18,327-330,350 
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/serve/routes  |   85.52 |    79.98 |   94.72 |   85.52 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   86.45 |       88 |     100 |   86.45 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   95.65 |    88.88 |     100 |   95.65 | 63-67,186         
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |    82.4 |    71.42 |     100 |    82.4 | ...-94,96-101,121 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.29 |    82.94 |   92.59 |   87.29 | ...1275,1318-1319 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.41 |    81.79 |   91.04 |   85.41 | ...4730,4732-4733 
  sse-events.ts    |   86.82 |    85.71 |   94.11 |   86.82 | ...16-927,930,937 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.92 |    79.69 |     100 |   90.92 | ...81-482,501-502 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.15 |    74.95 |   92.98 |   88.15 | ...2027,2072-2073 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   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 |   87.41 |    84.13 |     100 |   87.41 | ...1660,1680-1685 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.04 |    72.99 |     100 |   75.04 | ...79-690,696-697 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.9 |    87.15 |     100 |    76.9 | ...29-354,360-394 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.92 |    66.21 |      80 |   78.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |    90.8 |     88.4 |   96.57 |    90.8 |                   
  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 |    86.5 |    72.34 |     100 |    86.5 | ...47,764,827-836 
  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.13 |    95.09 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |      95 |     87.5 |     100 |      95 | 182-188           
  ...on-archive.ts |   89.55 |    87.83 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   99.02 |    97.44 |     100 |   99.02 | ...25,639,781-783 
 src/serve/voice   |    92.7 |    91.48 |   97.67 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   90.65 |    87.73 |   91.11 |   90.65 |                   
  index.ts         |   90.13 |    87.04 |   89.74 |   90.13 | ...1464-1468,1471 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.48 |    89.31 |      98 |   92.48 |                   
  ...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.23 |    86.48 |     100 |   88.23 | ...94-199,232-233 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |     86.8 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.77 |   94.73 |   88.28 | ...1362,1366-1373 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.09 |    79.16 |   77.77 |   94.09 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   73.08 |    75.43 |   67.41 |   73.08 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   74.29 |    72.05 |   68.57 |   74.29 | ...4112,4228-4234 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   70.08 |    71.73 |   66.66 |   70.08 | ...01,324,377-382 
  ...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.67 |    83.16 |   89.15 |   82.67 |                   
  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 |    81.25 |     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 |   69.07 |     72.6 |   84.61 |   69.07 | ...78-611,622-623 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   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   |   72.81 |    86.84 |   66.66 |   72.81 | ...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 |   94.44 |    90.14 |     100 |   94.44 | ...13-214,241-251 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   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.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   92.92 |       85 |   66.66 |   92.92 | ...72-177,276-281 
 src/ui/components |   71.52 |    79.07 |   79.85 |   71.52 |                   
  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       |   76.99 |    66.66 |      50 |   76.99 | ...96,233,255-260 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.28 |    66.99 |     100 |   79.28 | ...08,511,514-520 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   83.26 |    82.23 |      80 |   83.26 | ...2231,2257,2331 
  ...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  |   96.28 |     94.8 |      50 |   96.28 | ...01,459-463,466 
  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 |   95.67 |    87.09 |     100 |   95.67 | ...24-125,275-277 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |   85.34 |    84.91 |   92.98 |   85.34 |                   
  ...sksDialog.tsx |   81.87 |    82.77 |   85.71 |   81.87 | ...1853,1965-1971 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |   50.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.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.26 |    86.88 |   85.57 |   90.26 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.11 |    95.83 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.63 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.06 |    86.32 |   93.75 |   93.06 | ...1037,1082-1084 
 ...ponents/shared |   86.29 |    82.41 |   94.17 |   86.29 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.95 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.16 |    81.83 |   85.13 |   84.16 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       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      |   85.49 |    82.95 |   88.01 |   85.49 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...87-288,293-294 
  ...dProcessor.ts |   85.75 |     68.4 |   81.81 |   85.75 | ...1464,1485-1489 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...ng-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      52 |    63.63 |     100 |      52 | ...59,67-70,76-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.45 |    83.01 |     100 |   95.45 | ...60-161,285-288 
  ...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 |   86.08 |    81.23 |   76.92 |   86.08 | ...5198-5200,5202 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.38 |    98.85 |     100 |   98.38 | 141-144           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.4 |     100 |     100 | 175,262           
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.48 |    88.88 |     100 |   89.48 | ...54-456,489-499 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.26 |    77.14 |     100 |   95.26 | 120-121,223-228   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.26 |     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      |   87.13 |    85.34 |   95.62 |   87.13 |                   
  ...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.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.38 |    92.38 |     100 |   98.38 | 108,136-137,343   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.18 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.42 |       95 |     100 |   91.42 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |   96.03 |     97.1 |     100 |   96.03 | 103-106           
  ...mage-parts.ts |   97.75 |    94.87 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   82.73 |    79.48 |     100 |   82.73 | ...84-606,737-738 
  ...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 |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...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 |     60.3 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    66.38 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.27 |    79.92 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |    81.4 |    87.04 |   92.57 |    81.4 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       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 |    89.65 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...64,381-382,427 
  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.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.87 |    56.93 |   76.92 |   45.87 | ...1040,1052-1075 
  ...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 |       90 |     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.86 |    86.36 |   89.39 |   87.86 |                   
 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.38 |    84.54 |   94.85 |   90.38 |                   
  ...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 |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
 src/agents/arena  |   76.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 |    91.1 |    86.68 |   89.23 |    91.1 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |    92.4 |       90 |   83.78 |    92.4 | ...1862,1911-1914 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1705,1711-1712 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   82.04 |    84.17 |   88.97 |   82.04 |                   
  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       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.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.98 |    87.13 |   75.37 |   84.98 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.29 |    86.85 |   73.79 |   84.29 | ...8350,8354-8355 
  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.34 |    88.04 |   93.26 |   92.34 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   91.95 |    87.18 |   91.56 |   91.95 | ...3928,4026-4027 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6215,6243-6259 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 68-72             
  ...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.67 |    93.12 |     100 |   98.67 | ...79,707-708,755 
  ...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.63 |    90.43 |   95.61 |   91.63 |                   
  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      |   95.45 |    91.18 |     100 |   95.45 | ...1301,1309,1408 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.19 |    90.44 |   98.36 |   97.19 |                   
  dashscope.ts     |   98.36 |    92.99 |   95.65 |   98.36 | ...93-494,636-637 
  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     |   87.27 |    84.01 |   92.52 |   87.27 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.85 |    86.38 |   97.87 |   90.85 | ...1218-1224,1268 
  ...ionManager.ts |   82.24 |    80.14 |   81.52 |   82.24 | ...2730,2752-2753 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.36 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.42 |    82.66 |     100 |   90.42 | ...0,990-991,1001 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |    79.9 |    78.92 |    90.9 |    79.9 |                   
  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.76 |    64.76 |   71.42 |   71.76 | ...53-654,661-662 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |    93.3 |    89.05 |    94.6 |    93.3 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.79 |     88.5 |   96.42 |   88.79 | ...04-805,828-831 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...83,186,190-192 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |   95.74 |    93.33 |     100 |   95.74 | 154-155           
  goal-reducer.ts  |    93.4 |    90.65 |   96.96 |    93.4 | ...27,501,519-520 
  goal-runtime.ts  |   97.62 |     89.9 |     100 |   97.62 | ...1049,1169-1170 
  goal-tools.ts    |   98.22 |    93.02 |      95 |   98.22 | ...46-147,248-249 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.34 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.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.83 |    83.94 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |     82.6 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.97 |   91.13 |   92.55 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.17 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.63 |    89.01 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |     92.7 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.09 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.74 |    84.58 |   96.92 |   89.74 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.68 |    85.71 |     100 |   97.68 | ...96,119,490-491 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   91.41 |    85.15 |   95.65 |   91.41 | ...2116,2143-2144 
  ...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 |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...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.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.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.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.79 |    83.72 |   97.18 |   88.79 | ...2477,2553-2573 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...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 |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.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.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.73 |    83.97 |   84.83 |   81.73 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   76.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.1 |    95.72 |      95 |    99.1 | 145,369-370       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.03 |    76.51 |   66.07 |   60.03 | ...1484,1501-1521 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,482-483,499 
  sdk.ts           |   82.12 |    90.47 |   66.66 |   82.12 | ...90-194,232-254 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |    91.1 |    88.68 |   96.77 |    91.1 | ...1737,1768-1771 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |      83 |    94.32 |   86.36 |      83 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.02 |    98.41 |   82.92 |   96.02 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.24 |    84.99 |   88.72 |   86.24 |                   
  ...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 |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  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 |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.69 |    77.08 |   81.25 |   85.69 | ...95-911,957-958 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5035,5098-5099 
  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.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  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.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.89 |    89.62 |   96.87 |   92.89 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   83.01 |    95.03 |    61.9 |   83.01 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.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 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.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.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.11 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.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.34 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...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 |    87.5 |    86.02 |     100 |    87.5 | ...76-480,510-525 
  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 |   96.74 |    91.04 |     100 |   96.74 | ...69,196,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.

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

Review findings are provided inline.

— GPT-5 via Qwen Code /review (v0.21.6)

Comment thread packages/sdk-typescript/src/daemon/ui/normalizer.ts Outdated
Comment thread packages/sdk-typescript/src/daemon/ui/normalizer.ts
Comment thread packages/sdk-typescript/src/daemon/ui/transcript.ts
Review of #8812 caught a hole in the new classification: `session_update`
payloads such as `{}` or `{ sessionUpdate: 42 }` reach the default branch
with `kind === undefined`, and stamping them `unrecognized_session_update`
made Web Shell hide the only diagnostic a malformed frame produces.
Reserve the unrecognized reason for a real unknown string kind.

Also update the top-level default-case comment, which still pointed
adapters at the debug text prefix, and add a reducer-level test proving
`debugReason` survives the UI-event → transcript-block boundary: the
normalizer tests inspect events and the Web Shell tests build blocks by
hand, so dropping the spread in transcript.ts would leave both green.
@carffuca

carffuca commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Re-reviewed commit 2736e7f. The three previous findings are addressed, and I found no new actionable issues.

@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Sandboxed verification: ⚠️ incomplete — the run timed out with partial evidence - workflow run

The verification run did not complete, so the phases below may be partial or missing entirely. Advisory evidence for human reviewers — not a review, an approval, or a CI check.

中文 — 判定:⚠️ 未完成 · 运行超时,证据不完整

本次验证运行未正常结束,下列内容可能不完整甚至缺失。仅作为评审证据,不构成评审、批准或 CI 检查

No report.md was found in the run artifacts, so the report section is omitted — see the workflow run output.

Evidence images

01-pipeline-ab-base-vs-head

02-wire-sse-base-vs-head

03-mutation-matrix-all-killed

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 9, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Re-run gate pass at the current head — the review-round fix commits and the merge of main don't change any gate input, so the earlier assessment stands, updated for the grown diff.

Template looks good ✓

Problem: observed, not theoretical. The normalizer projects any daemon frame it has no case for into a debug event carrying a raw JSON dump, and Web Shell renders status/debug blocks as system messages — so every event kind the daemon ships ahead of the UI shows up as an unreadable JSON row mid-conversation. Already patched per-symptom three times (language_changed/session_cwd_changed prefixes, #8790 usage_update, #8808 a2ui). Before/after screenshots included, verified against a real qwen serve daemon with a build that deliberately contains no case 'a2ui' — the classification alone suppresses a kind nothing special-cases.

Direction: aligned. Web Shell is the main entry point for daemon-backed sessions, and this fixes the leak class instead of adding a fourth per-kind filter; #8808 was closed in favour of it. The SDK change is additive only (an optional debugReason on DaemonUiStatusEvent / DaemonStatusTranscriptBlock), so consumers that ignore it behave exactly as before.

Size: cross-package (sdk-typescript + web-shell) but small — ≈162 production lines (141+/21−), 401 test lines, 37 doc lines. No size concerns; the growth since the first pass is the review rounds' legacy-compat shim and its tests, which earn their place.

Approach: right-sized. The three-way split is the minimum that stops the leak class without hiding real signals: unrecognized_* hidden (developer diagnostics), malformed_payload kept (a known frame arrived broken — real defect signal), client-dispatched debug blocks kept (no debugReason at all). All seven debug-producing sites in the normalizer get a reason stamped; the only unstamped producer anywhere is Web Shell's own model_switch_summary dispatch in App.tsx, which is exactly the one that must keep rendering. The legacy shape shim for pre-debugReason transcripts is anchored and scoped (see the code review), not a fresh content filter.

Risk: no high-risk paths matched. The design fails open: any debug block without a debugReason renders exactly as it does today.

Moving on to code review. 🔍

中文说明

感谢贡献!

在当前 head 上的复审 gate——review 轮次的修复提交与 main 合并不改变任何 gate 输入,此前结论仍然成立,仅按当前 diff 更新数据。

模板完整 ✓

**问题:**已观测到的 bug,不是理论问题。normalizer 会把任何没有对应分支的 daemon 帧投影成带原始 JSON 的 debug 事件,而 Web Shell 把 status/debug 块渲染成 system 消息——daemon 每领先 UI 增加一种事件类型,对话中间就会出现一行无法阅读的 JSON。这个症状已经被逐个打过三次补丁(language_changed/session_cwd_changed 前缀、#8790usage_update#8808a2ui)。PR 附带 before/after 截图,在真实 qwen serve daemon 上验证,且验证构建故意不含 case 'a2ui'——证明仅靠分类本身就能屏蔽一个没有任何专门处理的类型。

**方向:**对齐。Web Shell 是 daemon 会话的主入口,本 PR 修的是整类泄漏而不是再加第四个按类型的过滤器;#8808 已因此关闭。SDK 改动纯增量(DaemonUiStatusEvent / DaemonStatusTranscriptBlock 上的可选 debugReason),忽略它的消费者行为完全不变。

**规模:**跨包(sdk-typescript + web-shell)但很小——约 162 行生产代码(141+/21−)、401 行测试、37 行文档。无规模顾虑;相比首轮增加的部分是 review 轮次要求的向后兼容 shim 及其测试,值得保留。

**方案:**范围恰当。三分法是挡住整类泄漏、同时不隐藏真实信号的最小方案:unrecognized_* 隐藏(开发者诊断),malformed_payload 保留(已知帧带着坏 payload 到达——真实缺陷信号),客户端自己派发的 debug 块保留(完全没有 debugReason)。normalizer 中全部七个 debug 产生点都打上了 reason;唯一不打 reason 的产生点是 Web Shell 自己在 App.tsx 里派发的 model_switch_summary,正是必须继续渲染的那个。面向 pre-debugReason 旧 transcript 的形状匹配 shim 是有锚点、有作用域的(见代码审查),不是一个全新的内容过滤器。

**风险:**未命中高风险路径。设计是 fail-open 的:任何没有 debugReason 的 debug 块渲染行为与今天完全一致。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@carffuca carffuca 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 — no blockers. Suggestions are inline.

中文说明

已审查——无阻断问题。 建议见行内评论。

— Kimi-K3 via Qwen Code /review (v0.21.6)

Comment on lines 158 to 160
DaemonUiAuthDeviceFlowThrottledEvent,
DaemonUiDebugReason,
DaemonUiErrorEvent,

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] DaemonUiDebugReason is a new public type of @qwen-code/sdk/daemon, but nothing gates that public surface: no test imports it through this barrel, so if the re-export were dropped or the type renamed without updating the barrel, every suite stays green (the only in-repo referents are types.ts itself and the two re-export lines, and an esbuild-stripped export type can never fail at runtime) while external consumers lose the documented union type — the first signal would be their tsc error after upgrade. — Failure scenario: a future refactor drops this re-export → all builds and tests pass → the advertised public API silently shrinks until a consumer's compile breaks. (Note: the inner daemon/ui barrel IS transitively guarded — this outer barrel re-exports from ./ui/index.js, so deleting the inner line fails the sdk build; only the outermost export needs an explicit guard.)

// In an existing sdk test, import through the public barrel and pin the surface:
import type { DaemonUiDebugReason } from '../../src/daemon/index.js';
expectTypeOf<DaemonUiDebugReason>().toEqualTypeOf<
  'unrecognized_event' | 'unrecognized_session_update' | 'malformed_payload'
>();
中文说明

DaemonUiDebugReason@qwen-code/sdk/daemon 新增的公开类型,但这一公开面无任何守护:没有任何测试经公共 barrel 导入它,因此若某次重构丢失该再导出、或类型改名后忘了同步,所有构建与套件依旧全绿(仓内只有 types.ts 与两行再导出引用它,而 export type 会被 esbuild 擦除、运行时永不报错),外部消费者则无声地失去文档承诺的联合类型——第一个信号是他们升级后自己的 tsc 报错。——失败场景:未来的重构删掉了这一行再导出,构建测试全部通过,公开 API 静默缩水,直到消费者的编译中断。(说明:内层 daemon/ui barrel 其实已被传递守护——外层 barrel 从 ./ui/index.js 再导出,删除内层那行会让 sdk 构建直接报错;真正需要显式守护的只有这个最外层导出。)

— Kimi-K3 via Qwen Code /review (v0.21.6)

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.

Good catch, and the suggested guard turned out not to hold — worth flagging since it affects other type-only guards in this package.

I implemented it as written first, then mutation-checked by deleting the re-export from src/daemon/index.ts. Both vitest run (14 passed) and npm -w packages/sdk-typescript run typecheck stayed green. Two reasons: vitest transpiles through esbuild, which erases export type without checking it, and this package's tsconfig is include: ["src/**/*.ts"] with exclude: [..., "test"], so nothing type-checks the test file at all. expectTypeOf alone cannot fence this surface here.

So in bc32742 the union ships as a closed enum value instead, matching DAEMON_ERROR_KINDS / DAEMON_APPROVAL_MODES:

export const DAEMON_UI_DEBUG_REASONS = [
  "unrecognized_event",
  "unrecognized_session_update",
  "malformed_payload",
] as const;
export type DaemonUiDebugReason = (typeof DAEMON_UI_DEBUG_REASONS)[number];

Re-exported as a value through both barrels, with a runtime toEqual assertion next to the expectTypeOf you suggested. Mutation-checked: dropping the outer re-export now fails that test.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: reverse audit — stopped before round 2 by the review time budget.

中文说明

已审查。 建议见行内评论。 未审查:反向审计——评审时间预算不足,未能开始第 2 轮。

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

Comment on lines +856 to +858
debugReason: kind
? 'unrecognized_session_update'
: 'malformed_payload',

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] The kind ? … : … split treats any truthy string discriminator as a forward-compatible unknown kind — but a whitespace-only discriminator (sessionUpdate: ' ') is truthy, so such a broken frame is classified unrecognized_session_update and hidden by Web Shell, defeating the invariant the comment above states: a broken frame is not a kind from a newer daemon, and must stay visible as malformed_payload. The same utils file already encodes the stricter convention — getFirstString treats whitespace-only strings as missing via entry.trim().length > 0. Probe-verified at the reviewed commit: sessionUpdate: ' ' currently yields unrecognized_session_update; gating on trim() flips it to malformed_payload with all of this PR's tests still green. — Failure scenario: a buggy daemon, older ACP peer, or proxying layer emits session_update with sessionUpdate: ' ' → classified unrecognized_session_update → Web Shell drops the block → the only diagnostic the malformed frame produces silently disappears from the transcript.

Suggested change
debugReason: kind
? 'unrecognized_session_update'
: 'malformed_payload',
debugReason: kind && kind.trim() !== ''
? 'unrecognized_session_update'
: 'malformed_payload',
中文说明

kind ? … : … 分支把任何为真值(truthy)的字符串判别符都视为来自更新版 daemon 的前向兼容未知类型——但纯空白判别符(sessionUpdate: ' ')同样是真值,这种损坏帧因此被归为 unrecognized_session_update 并被 Web Shell 隐藏,违背上方注释声明的不变量:损坏帧不是来自更新版 daemon 的类型,必须以 malformed_payload 保持可见。同一 utils 文件已有更严格的惯例——getFirstStringentry.trim().length > 0 将纯空白字符串视为缺失。已在被审提交上用探针验证:sessionUpdate: ' ' 当前产生 unrecognized_session_update;改为 trim() 判断后翻转为 malformed_payload,且本 PR 全部测试依旧通过。——失败场景:有缺陷的 daemon、旧版 ACP 对端或中间代理发出 sessionUpdate: ' 'session_update → 被归类为 unrecognized_session_update → Web Shell 丢弃该块 → 该损坏帧唯一的诊断信息从 transcript 中静默消失。

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

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.

Fixed in bc32742 — gated on kind?.trim(), matching the getFirstString convention you pointed at. Added { sessionUpdate: " " } to the malformed-discriminator cases; reverting to the bare kind check fails it.

Comment on lines +2596 to +2601
expect(state.blocks).toEqual([
expect.objectContaining({
kind: 'debug',
debugReason: 'unrecognized_event',
}),
]);

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] This round-trip test pins only the positive direction of the contract (normalizer event → block carries debugReason). The mirror invariant — a client-dispatched debug event must produce a block with no debugReason, which is exactly what keeps Web Shell's model-switch summary visible — is tested nowhere: the Web Shell tests construct blocks by hand and never route a client dispatch through appendStatusBlock. Probe-verified mutant: changing the spread in appendStatusBlock (transcript.ts) to debugReason: event.debugReason ?? 'unrecognized_event' survives all 409 tests in both suites (sdk-typescript daemon-UI + web-shell adapter), while the model-switch summary block would then carry unrecognized_event and be filtered out of the transcript. — Failure scenario: a future edit that defaults debugReason on debug events passes every test in this diff, tags the model-switch summary block unrecognized_event, and isUnrecognizedDaemonDebug silently removes the summary from the Web Shell transcript with both suites green.

Suggested companion test next to this one (the dispatch shape mirrors App.tsx):

it('keeps client-dispatched debug blocks free of debugReason', () => {
  const state = reduceDaemonTranscriptEvents(
    createDaemonTranscriptState({ now: 1 }),
    [
      {
        type: 'debug',
        text: 'Model switched to qwen3-coder-plus',
        source: 'model_switch_summary',
      },
    ],
  );

  expect(state.blocks).toHaveLength(1);
  expect(state.blocks[0]).toEqual(expect.objectContaining({ kind: 'debug' }));
  expect(state.blocks[0]).not.toHaveProperty('debugReason');
});
中文说明

这个往返测试只固定了契约的正向(normalizer 事件 → 块携带 debugReason)。镜像不变量——客户端派发的 debug 事件必须产生不带 debugReason 的块,而这正是 Web Shell 模型切换摘要保持可见的原因——没有任何测试覆盖:Web Shell 的测试手工构造块,从不把客户端派发经过 appendStatusBlock。变异探针已验证:把 appendStatusBlock(transcript.ts)中的展开改成 debugReason: event.debugReason ?? 'unrecognized_event' 后,两个套件共 409 个测试全部通过,而模型切换摘要块会被打上 unrecognized_event 并被过滤出 transcript。——失败场景:未来某次编辑给 debug 事件的 debugReason 加上默认值,本 diff 的所有测试仍然通过,摘要块被打上 unrecognized_event,isUnrecognizedDaemonDebug 在两个套件全绿的情况下把摘要从 Web Shell transcript 静默移除。

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

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.

Added in bc32742, and I reproduced your mutant first: debugReason: event.debugReason ?? "unrecognized_event" in appendStatusBlock did survive both suites. The new test dispatches the model-switch shape through the reducer and asserts the block has source: "model_switch_summary" and no debugReason property at all; with the mutant applied it is the only failure.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Qwen Code review timed out. Qwen review timed out after 10800 seconds (of the 180-minute budget). For large PRs, retry with a longer timeout by commenting: @qwen-code /review --timeout=360. See workflow logs.

@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

yiliang114
yiliang114 previously approved these changes Aug 9, 2026

@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

@qwen-code-ci-bot

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

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

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

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

Verification report

PR 8812 Deep Verification — fix(web-shell): stop rendering unrecognized daemon events in transcripts

Verdict: merge-ready — 25/25 scripted assertions passed (20 A/B cell assertions + 5 mutation-matrix rows), 0 fails. Verified head: 2736e7fea86f55c636519d86bea22f44c2f66c20 (git rev-parse HEAD^2), base f3ba99f545e97cff48ecb6af7ea1ea7971d8a6e4.

中文摘要
  • 结论: merge-ready。25/25 脚本化断言通过,0 失败。
  • A/B 结论: 在完全相同的帧序列上,base 构建的 Web Shell transcript 渲染出 2 行原始 JSON(a2uisome_future_event 转储,system 消息 5 条);head 构建为 0 行(system 消息 3 条)。被保留的三类内容在两臂完全一致:malformed 诊断(session_update: {}memory_changed 坏 payload)、客户端自派发的模型切换摘要、以及正常对话内容。原先靠文本前缀屏蔽的 language_changed / session_cwd_changed 在两臂均被屏蔽(删除前缀检查无回归)。
  • 变异矩阵: 5/5 守卫被其预期测试精确钉死(删过滤行 → 恰好 2 个过滤测试红;删 normalizer stamp → 2 红;删 reducer 透传 → 新加的 reducer 边界测试红;把无判别符帧误标为 unrecognized → 1 红;把 malformed 也过滤掉 → 保留侧测试红),无意外 collateral。
  • : sdk-typescript 全套 1486/1486、web-shell 全套 2944/2944(与 PR 描述数字一致)、两包 typecheck 干净、eslint 干净(见下方环境性说明)。
  • 一处描述修正: PR 风险段说 "rawEvent 仍保留原始事件信封",但 rawEvent 仅在 includeRawEvent: true 时由 normalizer 盖章,而 Web Shell 的 provider 默认 includeRawEvent = false。默认路径下可观测性实际由两处兜底:debug 块的 JSON 文本仍完整保留在 transcript state 中(仅渲染层过滤,普查证实),且原始帧仍在线上事件流中原样投递。非代码缺陷。
  • 未覆盖: 真实 daemon + Chrome 的端到端走查(审查者测试计划步骤 1–4 的浏览器部分);"帧仍在线上" 为构造性结论(normalizer 是纯投影,未触碰 serve 路由)。

Central claim + A/B

Central claim: unrecognized daemon frames (no normalizer case) no longer render as raw-JSON rows in Web Shell transcripts, while malformed_payload diagnostics and client-dispatched debug blocks keep rendering — keyed on a structured debugReason instead of text prefixes.

Harness (harness-ab.ts): real daemon wire envelopes → normalizeDaemonEventreduceDaemonTranscriptEventstranscriptBlocksToDaemonMessages — the exact production chain (live seam is DaemonSessionProvider.tsx:3121, pre-existing wiring; the SDK store's dispatch feeds the same reducer). Head arm loaded packages/... at the merge commit; base arm loaded sources from a git worktree at HEAD^1, with the loaded module realpaths asserted by the harness itself (tmp/base-tree/packages/sdk-typescript/src/daemon/ui/index.ts — no workspace symlink crossed; sdk runtime deps are zod + @modelcontextprotocol/sdk, lockfile untouched by this PR).

# Input frame Base rendered Head rendered
1 agent_message_chunk "Surface presented." assistant msg ✓ assistant msg ✓
2 session_update kind a2ui (the motivating shape) raw JSON row leaks filtered — unrecognized_session_update
3 unknown top-level some_future_event raw JSON row leaks filtered — unrecognized_event
4 language_changed filtered (text prefix) filtered (debugReason) — parity
5 session_cwd_changed filtered (text prefix) filtered (debugReason) — parity
6 session_update with update: {} (no discriminator) visible visible — malformed_payload
7 memory_changed with bad scope visible visible — malformed_payload
8 status Model switched: qwen3-coder-plus(openai) filtered (kept text check) filtered (kept text check)
9 client-dispatched debug model_switch_summary visible visible

Counts: system messages 5 (base) → 3 (head); raw-JSON rows 2 → 0; kept diagnostics 3 = 3. Base control asserts the JSON rows ARE rendered (they are), so the flip is proven, not assumed. See evidence/01-ab-head-filtered.png and evidence/02-ab-base-json-leak.png for the two cells as printed.

Classification boundary cells (head): 'a2ui'/'some_future_kind'unrecognized_session_update; null/42/''/missing discriminator → malformed_payload; whitespace-only ' 'unrecognized_session_update (truthy string — a string kind this client doesn't know, defensible under the PR's own taxonomy). Base prints (debug, no reason) for all eight — the field simply doesn't exist there.

Suppression observability (checked per method)

The filter is render-layer only: a census run shows all three debug blocks survive in transcript state with text + debugReason intact (3 blocks in state, 1 message rendered). Raw frames are also untouched on the wire (the normalizer is a pure projection; no serve route is in the diff). So "which frame was this" remains recoverable — with one description caveat below.

Corrections

  • Correction to the PR description (Risk & Scope): "rawEvent still carries the original envelope for debug panels" holds only when normalization runs with includeRawEvent: true. The normalizer stamps rawEvent conditionally (normalizer.ts createBase), and the Web Shell path's DaemonSessionProvider defaults includeRawEvent = false. In a default session, observability instead rests on the debug block's JSON text persisting in transcript state (census-verified) and the raw frame remaining on the SSE event stream. No code change requested — the PR's behavior is correct; only the risk-section wording is imprecise.

Findings

No blocking or non-blocking defects found in the changed code.

  • (Observation, severity: note) sessionUpdate: ' ' (whitespace-only) classifies as unrecognized_session_update and is therefore hidden. Consistent with the PR's taxonomy (it is a string kind no case handles), recorded so a future maintainer doesn't read it as a gap in the malformed branch.
  • (Observation, severity: note) The sandbox's head tree carries a leftover nested packages/sdk-typescript/node_modules/eslint@8.57.1 that makes npm run lint inside that package crash on rule loading (@typescript-eslint/no-unused-expressions TypeError). Proven environmental, not PR-caused: the PR touches no package.json/lockfile; a fresh base worktree (no nested install) lints clean with the same command; and the root eslint@9.29.0 passes cleanly on the head sdk package (same invocation shape the web-shell lint script uses), with a planted unused-variable probe confirming the gate bites.

Mutation matrix (vacuity of the new/changed tests)

All rows scripted (mutation-runner.mjs): apply mutation in place → run the catching suite with the JSON reporter → assert exactly the expected tests fail and nothing else → restore. Unmutated controls: daemonUi.test.ts 289/289 and transcriptToMessages.test.ts 115/115 green. See evidence/03-mutation-matrix.png.

Mutant Guard removed Suite Result
M1 delete the isUnrecognizedDaemonDebug filter line web-shell adapter killed 2/2 — exactly the two filter tests, no collateral (matches author's "two tests fail" claim)
M2 drop debugReason: 'unrecognized_event' stamp sdk daemonUi killed 2/2 (stamp test + reducer-boundary test)
M3 drop the debugReason spread in appendStatusBlock sdk daemonUi killed 1/1 — the new reducer-boundary test does its stated job
M4 always stamp unrecognized_session_update (commit 2's fix reverted) sdk daemonUi killed 1/1 — the discriminator-less-malformed test pins commit 2
M5 also filter malformed_payload (keep-side positive control) web-shell adapter killed 1/1 — the "keeps malformed visible" assertion is live

No survivors. Every guard the PR introduces is pinned by a test that fails with the behavioural assertion, and each kill set matched the intended test names exactly (zero unexpected failures).

Targeted gates (head)

Gate Result
packages/sdk-typescript full suite 1486/1486 pass (32 files)
packages/sdk-typescript test/unit/daemonUi.test.ts 289/289 pass
packages/web-shell full suite 2944/2944 pass (172 files) — matches the count claimed in the PR body
packages/web-shell transcriptToMessages.test.ts 115/115 pass
tsc --noEmit both packages clean
eslint both packages (root eslint 9) clean; liveness probe planted + caught + removed

Multi-commit note: the snapshot lists 2 commits but only HEAD^2 is reachable (depth-2 checkout; defbe4fb is beyond the shallow boundary). The aggregate HEAD^1..HEAD diff — which contains both commits — is what this round verified; M4 specifically exercises commit 2's discriminator fix.

Not covered

  • Reviewer Test Plan steps 1–4 in a real browser/daemon: the A/B exercises the identical normalize→reduce→adapter chain the live path uses, but no real qwen serve + Chrome session was driven (mock provider + a2ui MCP server setup was out of budget-scope). Steps 2–4 claims map to A/B cells pre-release: fix ci #1/OpenAI API Error: 401 Incorecct API Key provided #6–9; step 1's a2ui frame shape is A/B cell Where is the config saved? #2.
  • Step 3 ("frame still on the wire"): covered by construction only — the normalizer is a pure projection and the diff touches no serve route; no SSE capture was recorded. This verifies the shape (projection changed, frames untouched), not a live wire capture.
  • Per-commit attribution for defbe4fb (unreachable at depth 2 — see gates note).
  • Repo-wide lint/typecheck/test — only the two changed workspaces ran (per scope).
  • webui rendering was verified by code reading only (it unconditionally drops all kind === 'debug' blocks in transcriptAdapter.ts, so this PR cannot change its behavior).
  • npm run lint inside packages/sdk-typescript crashes on a sandbox-only nested-eslint artifact (see Findings); not re-run after removing the artifact since the root-eslint run + base A/A settle the question.

Methodology

Environment: CI verify container (node:22-bookworm), tree = refs/pull/8812/merge (depth 2), npm ci + npm run build pre-run at HEAD. Harnesses drove compiled TypeScript sources directly via tsx (type-only cross-package imports are erased, so the base arm provably loaded base-tree code — realpaths printed by each run). A/B: identical 9-event scenario (7 wire envelopes + 2 client-dispatched UI events) piped through normalizeDaemonEventreduceDaemonTranscriptEventstranscriptBlocksToDaemonMessages on both arms, with arm-conditional expectations encoded as assertions (base failing to render = control assertion passing). Mutation matrix: in-place mutation + vitest JSON reporter + restore, scripted in mutation-runner.mjs. Raw logs in logs/ (head-ab.log, base-ab.log, mutation-matrix.log, vitest JSON outputs); harnesses harness-ab.ts and mutation-runner.mjs are rerunnable. Base worktree removed after capture; tree left clean (git status empty).

Evidence images

01-ab-head-filtered

02-ab-base-json-leak

03-mutation-matrix

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

Qwen Code · sandboxed verification

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

Verified at head 2736e7f (adding substance to the existing approval). The classification is right: unrecognized_event / unrecognized_session_update for forward-compat noise, malformed_payload kept visible for frames this client knows that arrived broken, and the missing/empty/non-string discriminator case is correctly routed to malformed rather than unrecognized (with the rationale documented). The reducer carries debugReason onto status/debug blocks, and the new reducer-pass-through test catches the exact regression where both suites would stay green while production blocks lose the field. The Web Shell filter keys off debugReason instead of text prefixes, so future daemon kinds are covered automatically; client-dispatched debug blocks (no debugReason, e.g. model_switch_summary) still render, and the model.changed status filter stays text-keyed with the reason explained. Tests pin all three categories on both the normalizer and adapter sides. One CI note: the only red check on this head is review-pr failing on a runner worktree-cleanup error ('cannot delete branch worktree-triage used by worktree'), which is bot infrastructure, not this change. Nothing blocks merge.

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Found one backward-compatibility regression inline. I also independently reproduced the existing whitespace-discriminator finding: sessionUpdate: ' ' normalizes to unrecognized_session_update and is filtered instead of remaining visible as malformed_payload. I’m holding approval until these two classification holes are addressed.

Otherwise, the current head passed the focused SDK and Web Shell suites (289 + 115 tests), both package typechecks, changed-file ESLint/Prettier checks, and the workspace build.

Comment thread packages/web-shell/client/adapters/transcriptToMessages.ts Outdated
@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

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

Copy link
Copy Markdown
Collaborator

🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

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

@qwen-code-dev-bot

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

Copy link
Copy Markdown
Collaborator

AutoFix round 3 finishedview run. See this round's report below.

中文说明

AutoFix 第 3 轮已完成 —— 查看运行。本轮报告见下方。

…n split

Four review findings from #8812:

- `WebShellTranscript` is a public entry point taking already-projected
  blocks, so blocks from an SDK predating `debugReason` still arrive with
  no reason and started rendering again when the prefix checks were
  removed. Fall back to the stable ` (unrecognized daemon event): ` marker
  when no reason is present — which covers every unrecognized event type,
  not just the two previously suppressed by name. The old-shape fixture is
  restored (adding `debugReason` to it had hidden this path) and a
  dedicated legacy test now pins it.
- A whitespace-only discriminator is truthy, so `sessionUpdate: ' '` was
  classified unrecognized and hidden. Gate on `trim()`, matching the
  convention `getFirstString` already uses.
- Add the mirror invariant for the reducer: a client-dispatched debug
  event must produce a block with no `debugReason`. Defaulting the field
  in `appendStatusBlock` otherwise passes every other test while tagging
  the model-switch summary unrecognized.
- Guard the outermost public re-export. A type-only guard would not hold —
  vitest erases `export type` through esbuild and this package's tsconfig
  excludes `test/` — so ship the union as `DAEMON_UI_DEBUG_REASONS`,
  matching `DAEMON_ERROR_KINDS`, and assert it at runtime.
@zjunothing

Copy link
Copy Markdown
Collaborator

Follow-up verification on bc32742b5ecac86e873d0dd772b6aa527e33b42c.

The whitespace discriminator issue is fixed: sessionUpdate: " " and "\\t" now produce malformed_payload, and the focused SDK/Web Shell suites pass (290/290 and 116/116).

One usage-update compatibility issue remains blocking for the original “usage_update刷屏” scenario:

transcriptBlocksToDaemonMessages([
  {
    kind: 'debug',
    text: 'usage_update: {"used":1,"size":2}',
    // no debugReason: legacy/persisted block
  },
])

At this head this still returns a system message containing the raw usage_update payload. The new marker fallback correctly suppresses legacy top-level unrecognized_event blocks, but it cannot suppress legacy session_update-style usage_update blocks because that historical text has no marker. Since #8528 is the producer and #8790 only prevents new SDK transcript insertion, an already persisted/older-projected block can still reappear in Web Shell and continue the reported spam after upgrade.

Please add a backward-compatible filter/migration for this exact legacy usage_update: shape (while keeping malformed_payload and client-dispatched debug blocks visible), plus a regression test. The current comment documents this limitation, but the original user-visible issue is not fully closed until this path is handled.

Reproduction was run directly against the PR head; the ACP wire path and new valid usage_update suppression should remain unchanged.

…gReason

Follow-up verification on #8812 pointed out the marker fallback does not
close the original report. #8790 stopped the SDK inserting new
`usage_update` blocks, but `WebShellTranscript` renders whatever blocks its
caller passes, so a transcript persisted or projected before that still
holds them and the spam returns after upgrade.

The legacy `session_update` projection is `<kind>: <json>` with no marker to
key on, so match those by kind name instead. The list is closed on purpose —
`usage_update` and `a2ui`, the two known to have leaked — and requires the
`: {` shape, because a generic `<word>: {` rule would swallow legitimate
diagnostics. Blocks the normalizer classified still win on `debugReason`,
so `malformed_payload` and client-dispatched debug blocks stay visible.

Mutation-checked in both directions: dropping the fallback fails the legacy
test, and loosening the prefix to bare `usage_update:` fails the test that
pins prose and classified blocks staying visible.
@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

Reproduced exactly as you described and fixed in df0b757 — you are right that documenting the limitation did not close the original report.

At bc32742b5e your block returned a one-element system message with the raw payload. Confirmed before changing anything.

The session_update projection has no marker, so I matched by kind name instead — scoped to the two known to have leaked, usage_update and a2ui, and requiring the : { shape so a generic <word>: { rule cannot swallow real diagnostics:

const LEGACY_SUPPRESSED_SESSION_UPDATE_PREFIXES = ["usage_update: {", "a2ui: {"];

It only applies when debugReason is absent, so blocks the normalizer classified still win — malformed_payload and client-dispatched debug blocks stay visible.

Two regression tests, mutation-checked in both directions: dropping the fallback fails the legacy test, and loosening the prefix to bare usage_update: fails a test pinning that malformed_payload blocks and prose like usage_update: rejected by the proxy keep rendering.

What is still not recoverable, and I kept it as a code comment rather than widening the rule: a legacy block for some other unrecognized session-update kind. Matching those needs a generic shape rule that would hide legitimate content. New projections carry debugReason and are covered.

Web Shell suite 2947 passing, typecheck and lint clean. The ACP wire path is untouched.

@zjunothing

Copy link
Copy Markdown
Collaborator

Thanks — I independently verified c21818d5ec: all seven payload shapes are now suppressed, the status/quoted-marker negative cases remain visible, and Web Shell focused 120/120, sequential full 2949/2949, typecheck, lint, formatting, and production build all pass.

I opened #8823 to track the reducer behavior separately, with both reproductions, the shared root cause, and the acceptance criteria captured there. This keeps #8812 focused; I do not consider that pre-existing reducer issue a blocker for this PR.

Please feel free to use #8823 for the dedicated follow-up PR you offered.

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind main, so it merged current main in via update-branch and will retry on the next scan. A stale base (a dependency or symbol main already changed) can fail the build without being the fix's fault; if it still fails once current, it hands off to a human.

What I found before stopping:
Qwen failed during address-review: status 125.

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

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


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

@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

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

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

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

Verification report

PR 8812 Deep Verification (follow-up round) — fix(web-shell): stop rendering unrecognized daemon events in transcripts

Verdict: merge-ready — 64/64 scripted assertions passed, 0 fails (43 A/B cell assertions + 13 mutation-matrix rows incl. 3 unmutated controls + 8 gate assertions). Verified head: c9224e567de419ae56a22401de758bb52aa9c25f (git rev-parse HEAD^2), base 0a3d7bb5c19db6e4a490adb9d396ccbcb1ef966a (HEAD^1). This is a follow-up round: the previous round verified commits 1–2 (2736e7fe); four commits were added since, reworking the Web Shell legacy fallback for blocks projected or persisted by SDKs predating debugReason. Every carried-forward measurement was rebuilt and re-run at the new head; nothing was diffed from the old report.

中文 — 判定:✅ 通过 · 可合入(agent 判定)
  • 结论: merge-ready。64/64 脚本化断言通过,0 失败。
  • 上一轮发现的状态: 空白判别符 ' ' 被误判为 unrecognized 的 note —— 已修复(trim() 门,W10 + M7 钉死);嵌套 eslint 的 note —— 定性更正(不是沙箱残留,而是提交在 package.json 里的 eslint: ^8.57.0 devDep 与根 ^9.24.0 的正当嵌套安装,base 同样存在,与本 PR 无关);rawEvent 风险段措辞的更正 —— 依旧成立(代码未变)。见下方状态表。
  • A/B 结论(见 01-ab-head-filtered.png / 02-ab-base-json-leak.png): 21 个对照单元格中,base 泄漏 11 处原始 JSON 行(新类型线上帧 ×2、旧 SDK 遗留标记块、usage_update/a2ui 遗留块、5 种非对象 payload、pretty-print payload),head 全部过滤为 0;所有应保留的诊断(malformed、客户端自派发 debug、prose、引用标记的块、status 块)在两臂逐格一致。
  • 变异矩阵: 10/10 守卫被其预期测试精确钉死,含本轮新增的全部守卫(形状 shim、kind 守卫、整体投影锚定、非对象 payload、trim() 门、reducer 镜像不变量、闭合 kind 列表、公共面运行时导出)。0 幸存者。
  • : sdk-typescript 1501/1501、web-shell 2982/2982、两包 typecheck 干净、根 eslint 9 两包干净(探针证实门禁有效)。
  • 未覆盖: 真实 daemon + Chrome 端到端(审查者计划步骤的浏览器部分);"帧仍在线上" 为构造性结论;逐 commit 归因(depth-2 不可达)。

Previous-finding status (follow-up round)

# Previous finding (round 1 @​ 2736e7fe) Severity Status at new head c9224e56
1 sessionUpdate: ' ' (whitespace-only) classified unrecognized_session_update and hidden note fixed — commit bc32742b gates on trim(). Re-measured, not diffed: cell W10 renders visible with reason=malformed_payload on head; mutant M7 (restore truthiness gate) is killed by exactly the discriminator test.
2 npm run lint inside packages/sdk-typescript crashes; attributed to a "leftover nested eslint artifact" of the sandbox note superseded (characterization corrected) — a fresh container reproduces it, so it is not sandbox residue: npm installs eslint@8.57.1 nested because the committed packages/sdk-typescript/package.json declares "eslint": "^8.57.0" while the root has ^9.24.0. Pre-existing at base (PR touches no package.json/lockfile/eslint config — verified from the diff file list). Conclusion unchanged: not PR-caused; gate demonstrated with root eslint 9 instead.
3 Correction: PR Risk section says "rawEvent still carries the original envelope" but rawEvent is stamped only with includeRawEvent: true, which Web Shell never sets correction stands — re-verified at new head: normalizer.ts:607 still conditional; no includeRawEvent anywhere in packages/web-shell/client/. Description text is unchanged. No code change requested.

Central claim + A/B

Central claim (carried): unrecognized daemon frames no longer render as raw-JSON rows in Web Shell transcripts; malformed_payload diagnostics and client-dispatched debug blocks keep rendering — keyed on structured debugReason.
Delta claim (new this round): blocks that arrive without a debugReason — projected or persisted by an SDK older than this field — are still filtered, by shape: the anchored whole legacy projection <event-type> (unrecognized daemon event): <payload> plus a closed kind-name list (usage_update: {, a2ui: {), scoped to debug blocks only; while anything that merely quotes a marker, any status block, prose, and classified blocks all keep rendering.

Harness (harness-ab.ts, rerunnable): real wire envelopes → normalizeDaemonEventreduceDaemonTranscriptEventstranscriptBlocksToDaemonMessages (the production chain), plus legacy cells feeding already-projected blocks directly into transcriptBlocksToDaemonMessages (the WebShellTranscript public seam). Head arm loaded the merge-commit tree; base arm loaded a git worktree at HEAD^1 = 0a3d7bb5; each run prints the module URLs it loaded (logs/head-ab.log, logs/base-ab.log), proving the base arm executed base-tree code — no workspace symlink crossed (the adapter's @qwen-code/sdk/daemon import is type-only and erased; its only runtime import is relative). Lockfile untouched by the PR, so reusing the root node_modules is a clean control.

Section W — wire frames (normalize → reduce → adapter)

# Input frame Base Head
W1 agent_message_chunk "Surface presented." assistant msg ✓ assistant msg ✓
W2 session_update kind a2ui raw JSON row leaks filtered — unrecognized_session_update
W3 unknown top-level some_future_event raw JSON row leaks filtered — unrecognized_event
W4 language_changed filtered (old text prefix) filtered (debugReason) — parity
W5 session_cwd_changed filtered (old text prefix) filtered (debugReason) — parity
W6 session_update update: {} (no discriminator) visible visible — malformed_payload
W7 memory_changed bad scope visible visible — malformed_payload
W8 model.changed → status Model switched: … filtered (kept text check) filtered (kept text check)
W9 client-dispatched debug model_switch_summary visible, source+data intact visible, source+data intact, block has no debugReason
W10 sessionUpdate: ' ' (whitespace) visible visible — malformed_payload (round-1 note fixed by trim() gate)
W11 session_update kind usage_update zero blocks (#8790) zero blocks (#8790) — A/A parity

Section L — legacy/persisted blocks (no debugReason) into the adapter

# Block text (kind) Base Head
L1 language_changed (unrecognized daemon event): {"language":"en"} (debug) filtered (old prefix) filtered (shape shim) — parity
L2 some_future_event (unrecognized daemon event): {"a":1} (debug) renders filtered — flip
L3 usage_update: {"used":46351,…} (debug) renders filtered — flip
L4 a2ui: {"surfaceId":"s1",…} (debug) renders filtered — flip
L5 marker + non-object payloads 42 / true / null / plain string / empty ×5 all 5 render all 5 filtered — flip
L6 marker + realistic pretty-printed (2-space indent) payload renders filtered (prefix still matches)
L7 5 keep-negatives: status quoting marker; debug relaying marker mid-text; client summary quoting marker; status starting usage_update: {; prose usage_update: rejected by the proxy all 5 visible all 5 visible
L8 collision probe: client-dispatched debug (source set, no reason) whose text starts a2ui: {… renders filtered — inherent shim boundary (see Findings)
L9 char-class probe: marker with space in event type (weird type (…)) renders renders — parity (see Findings)
L10 legacy malformed shape session_update: {"update":{}} (debug) visible visible — closed list does not swallow old malformed diagnostics

Counts: 11 targeted leak observables on base (W2, W3, L2, L3, L4, L5×5, L6) → 0 on head; the documented collision probe L8 also flips (render → filter, inherent shim boundary); all 13 parity/keep cells (W1, W4–W11, L1, L7, L9, L10) are identical across arms. Census on head: 3 debug blocks survive in transcript state, 1 renders — the filter is render-layer only, so "which frame was this" remains recoverable from state and from the wire. Witness images: 01-ab-head-filtered.png, 02-ab-base-json-leak.png.

Corrections

  • Correction to round 1's characterization of the sdk lint crash (carried finding Where is the config saved? #2 above): round 1 called the nested eslint@8.57.1 a "leftover sandbox artifact". A fresh container with a pristine npm ci reproduces it, so it is the legitimate npm outcome of the committed eslint: ^8.57.0 devDependency in packages/sdk-typescript/package.json conflicting with the root ^9.24.0. It is pre-existing repo state, identical at base, and unrelated to this PR — but it is not environmental flotsam. This changes no verdict; it fixes the record.
  • The round-1 correction to the PR description's rawEvent wording stands unchanged (see status table row 3).

Findings

No blocking or non-blocking defects found in the changed code. Two boundary probes, recorded so a future maintainer doesn't misread them as gaps:

  • (note) Shim collision is inherent and unreachable to fix at this layer (cell L8): a client-dispatched debug block with no debugReason whose text starts with exactly a2ui: { / usage_update: { (or the whole legacy projection shape) is indistinguishable from a persisted legacy block, so it is filtered. The only known client dispatcher in this repo is Web Shell's model_switch_summary, whose text never takes these shapes; the shim is anchored, debug-scoped, and closed-list precisely to keep this surface minimal. The alternative (not filtering no-reason blocks) reopens the original spam for every persisted transcript. Documented tradeoff, not a defect.
  • (note) Event types outside [A-Za-z0-9_.-] escape the shape shim (cell L9): e.g. a type containing a space renders on head — exactly as on base (parity), and every new projection carries debugReason regardless, so only blocks persisted by old SDKs with exotic type strings could slip through. Daemon event types are wire-protocol identifiers; not reachable in practice.

Mutation matrix (vacuity of the new/changed tests)

Scripted (mutation-runner.mjs): mutate in place → run catching suite with vitest JSON reporter → assert the failed set matches the intended tests exactly → restore. Unmutated controls green: adapter 120/120, daemonUi.test.ts 290/290, daemon-public-surface.test.ts 14/14. Witness: 03-mutation-matrix.png.

Mutant Guard removed / inverted Suite Result
M1 delete the isUnrecognizedDaemonDebug filter call (whole feature) adapter killed 5/5 — exactly the five filter tests
M2 disable the legacy shape shim only (reason branch intact) adapter killed 3/3 — exactly the three legacy tests (reason-classified filtering survives, as designed)
M3 drop the kind === 'debug' guard (shim reaches status blocks) adapter killed 1/1 — "only matches the legacy shape…" (status cell usage_update: { drops)
M4 restore substring marker match (unanchored) adapter killed 1/1 — "only matches the legacy shape…" (relayed/quoted-marker cells drop)
M5 restore the leading-char class [{"[] on the legacy payload adapter killed 1/1 — "filters legacy projections whose payload is not an object"
M6 default debugReason in appendStatusBlock (?? 'unrecognized_event') sdk killed 1/1 — the mirror invariant test ("leaves client-dispatched debug blocks without a debugReason"); confirms the author's claim that only that test pins it
M7 drop the trim() gate (truthy ' ' → unrecognized) sdk killed 1/1 — "classifies a session_update with no usable discriminator as malformed"
M8 loosen prefixes to bare usage_update: / a2ui: adapter killed 1/1 — "does not let the legacy prefixes swallow prose…"
M9 drop the DAEMON_UI_DEBUG_REASONS value re-export from the public entry sdk killed 1/1 — "pins the union shipped by @​qwen-code/sdk/daemon" fails on the runtime assertion (import resolves undefined; the test does exactly the job its comment describes)
PC positive control: isIgnoredWebShellStatus returns false (pre-existing pin) adapter killed 1/1 — "filters SDK model switch status noise"

10/10 killed, 0 survivors, zero collateral failures — every kill set matched the intended test names exactly. (The runner's log prints M9 as "MISMATCH" only because this round's expectation predicted an import-level file failure; the actual failure is the intended test's runtime assertion, adjudicated as killed.)

Targeted gates (head c9224e56)

Gate Result
packages/web-shell full suite 2982/2982 pass, 173 files (round 1: 2944/172 — delta is this PR's 8 adapter tests + tests merged from main)
packages/sdk-typescript full suite 1501/1501 pass, 32 files (round 1: 1486 — delta is this PR's 7 sdk tests + tests merged from main)
tsc --noEmit both packages clean (exit 0)
eslint (root 9.x, scoped to each package) clean on both; liveness probe (planted unused variable) caught on both packages before the clean runs
npm run lint inside sdk package crashes on nested eslint@​8.57.1 — pre-existing, committed-dependency conflict, identical at base (see Corrections); not used as the gate

Witness: 04-gates-suite-counts.png. Multi-commit note: the snapshot lists 7 commits but the checkout is depth-2 (git rev-list HEAD^1..HEAD^2 returns 1, the shallow-boundary artifact), so per-commit attribution is out of reach; the aggregate HEAD^1..HEAD diff — containing all seven — is what this round verified. The branch already merged current main (bot commit c9224e56), and HEAD is the clean merge into base tip 0a3d7bb5, so the merge itself is verified by construction.

Not covered

  • Reviewer Test Plan in a real browser/daemon: steps map to harness cells — step 1 (unrecognized event) → W2/W3; step 2 (JSON row gone, conversation intact) → W1–W3; step 4 (model-switch summary survives) → W9 — but no live qwen serve + Chrome session was driven. The A/B exercises the identical normalize→reduce→adapter chain the live path uses; this reproduces the shape, not the end-to-end trigger.
  • Step 3 ("frame still on the wire"): by construction only — the normalizer is a pure projection and the diff touches no serve route; no SSE capture recorded.
  • Per-commit attribution for the four delta commits (depth-2 checkout; verified in aggregate).
  • Repo-wide lint/typecheck/test — only the two changed workspaces ran (per scope).
  • webui rendering: verified by code reading only (it unconditionally drops all kind === 'debug' blocks, so this PR cannot change its behavior).
  • verify-capture.mjs ran cleanly; no image pipeline gaps this round.

Methodology

Environment: CI verify container (node:22-bookworm), tree = refs/pull/8812/merge (depth 2), npm ci + npm run build pre-run at HEAD. Harnesses drove compiled TypeScript sources directly via tsx; each arm printed the module URLs it loaded so the base arm's isolation is evidenced in the logs, not assumed (logs/head-ab.log, logs/base-ab.log). A/B: 21 cells (11 wire frames + 10 legacy/boundary blocks) piped through the production chain on both arms, arm-conditional expectations encoded as assertions (a base cell leaking JSON is a control assertion that passes when base leaks). Mutation matrix: in-place mutation + vitest JSON reporter + restore, 10 mutants + positive control, scripted in mutation-runner.mjs. Gates: full workspace suites, tsc --noEmit, root eslint with planted liveness probes. Raw logs in logs/; harnesses harness-ab.ts and mutation-runner.mjs are rerunnable. Base worktree removed; tree left clean (git status empty).

Evidence images

01-ab-head-filtered

02-ab-base-json-leak

03-mutation-matrix

04-gates-suite-counts

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

Qwen Code · sandboxed verification

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix review round — no code changes needed

All feedback in this round was triaged against head c9224e567d (the merge of main into the PR branch). Every inline finding is already resolved in the code by the earlier fix commits on this branch (2736e7fea8bc32742b5edf0b757c3c98bc115808c21818d5ec). This round re-verified each one against the exact code at head, re-read the full diff as a skeptical reviewer, and re-ran the complete verification gate after the merge from main. No new defect was found and nothing was changed.

Findings re-verified as resolved in the code

Thread Finding Resolution present at head
normalizer.ts — discriminator-less session_update (Critical) A missing/empty/non-string discriminator was stamped unrecognized_session_update and hidden debugReason: kind?.trim() ? 'unrecognized_session_update' : 'malformed_payload' keeps broken frames visible; test pins {}, { sessionUpdate: 42 }, { sessionUpdate: '' }, { sessionUpdate: ' ' }
normalizer.ts — default-case comment (Suggestion) Comment still told adapters to pattern-match the text prefix Comment now directs adapters to branch on debugReason; the prefix is called out as diagnostic wording
transcript.ts — reducer boundary (Suggestion) No test that debugReason survives the reducer carries debugReason through the reducer onto the transcript block normalizes an unknown event and reduces it through reduceDaemonTranscriptEvents
daemon/index.ts — public surface (Suggestion) The DaemonUiDebugReason re-export had no guard The union ships as the closed DAEMON_UI_DEBUG_REASONS value re-exported through both barrels, pinned by a runtime assertion in daemon-public-surface.test.ts (a type-only guard cannot hold under esbuild + the package's test/-excluding tsconfig)
normalizer.ts — whitespace discriminator (Suggestion) sessionUpdate: ' ' is truthy and was classified unrecognized/hidden Same kind?.trim() gate, matching the getFirstString convention; the whitespace case is pinned in the test
daemonUi.test.ts — mirror invariant (Suggestion) Nothing tested that client-dispatched debug blocks carry no debugReason leaves client-dispatched debug blocks without a debugReason dispatches the model-switch shape through the reducer and asserts the property is absent
transcriptToMessages.ts — pre-debugReason blocks (Critical) Removing the prefix fallbacks would make old/persisted blocks render again A legacy shape fallback applies only when debugReason is absent, covering old blocks of any event type
transcriptToMessages.ts — fallback scope (Critical) The fallback matched substrings and status blocks, hiding real diagnostics kind === 'debug' guard + whole-projection anchored match (never a substring) + closed usage_update: { / a2ui: { session-update list; negative tests cover a quoted marker in malformed/client/status blocks and prose like usage_update: rejected by the proxy

Issue-level items: the primitive-payload gap (stringifyJson returns strings verbatim and primitives bare, so a leading-{ anchor let non-object legacy projections through) was fixed in c21818d5ec — the pattern no longer keys on the payload's first character, and the regression test covers object, array, string, number, boolean, null, and empty payloads; the reporter independently re-verified that commit. The non-blocking reducer-state finding (hidden blocks still consume maxBlocks and finalize the active assistant block) is deliberately not addressed in this PR and is tracked in #8823 with the reporter's explicit agreement.

No failed checks and no still-red checks were reported for this round.

Verification

Commands actually run at head c9224e567d (post-merge):

  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0)
  • npm run lint — passed (exit 0)
  • npx vitest run test/unit/daemonUi.test.ts test/unit/daemon-public-surface.test.ts (packages/sdk-typescript, touched files) — 304 passed
  • npx vitest run client/adapters/transcriptToMessages.test.ts (packages/web-shell, touched file) — 120 passed
  • npx vitest run (packages/sdk-typescript full suite) — 32 files, 1501 passed
  • npx vitest run (packages/web-shell full suite) — 173 files, 2982 passed
中文说明

Autofix 评审轮次 — 无需任何代码改动

本轮所有反馈均基于 head c9224e567dmain 合入 PR 分支后的合并提交)逐一分类。所有行内发现均已由本分支更早的修复提交(2736e7fea8bc32742b5edf0b757c3c98bc115808c21818d5ec)在代码中解决。本轮针对 head 上的确切代码逐一复核了每个发现,以怀疑者视角重新通读了完整 diff,并在合入 main 之后重跑了完整验证门禁。未发现新缺陷,未做任何改动。

已复核确认在代码中解决的发现

讨论串 发现 head 上已存在的解决方式
normalizer.ts — 无判别符的 session_update(Critical) 缺失/空/非字符串判别符被打上 unrecognized_session_update 并被隐藏 debugReason: kind?.trim() ? 'unrecognized_session_update' : 'malformed_payload' 使损坏帧保持可见;测试钉死 {}{ sessionUpdate: 42 }{ sessionUpdate: '' }{ sessionUpdate: ' ' }
normalizer.ts — default 分支注释(Suggestion) 注释仍引导适配器去匹配文本前缀 注释现改为要求适配器基于 debugReason 分支,并说明前缀只是诊断措辞
transcript.ts — reducer 边界(Suggestion) 没有测试证明 debugReason 能穿过 reducer carries debugReason through the reducer onto the transcript block 归一化一个未知事件并经 reduceDaemonTranscriptEvents 归约后断言
daemon/index.ts — 公开面(Suggestion) DaemonUiDebugReason 的再导出无守护 该联合类型以闭合常量值 DAEMON_UI_DEBUG_REASONS 形式经两个 barrel 导出,并由 daemon-public-surface.test.ts 中的运行时断言钉死(esbuild 会擦除 export type、且本包 tsconfig 不含 test/,纯类型守护在此无法成立)
normalizer.ts — 纯空白判别符(Suggestion) sessionUpdate: ' ' 为真值,曾被归为 unrecognized 而隐藏 同一 kind?.trim() 门禁,与 getFirstString 惯例一致;空白样例已被测试钉死
daemonUi.test.ts — 镜像不变量(Suggestion) 没有测试覆盖客户端派发的 debug 块不带 debugReason leaves client-dispatched debug blocks without a debugReason 将模型切换形态经 reducer 派发并断言该属性不存在
transcriptToMessages.ts — debugReason 出现之前的旧块(Critical) 删除前缀回退会让旧的/持久化的块重新渲染 仅在 debugReason 缺失时应用旧形态回退,覆盖任意事件类型的旧块
transcriptToMessages.ts — 回退范围(Critical) 回退曾以子串匹配且作用于 status 块,会隐藏真实诊断 kind === 'debug' 守卫 + 锚定整个投影形态的匹配(绝不做子串匹配)+ 闭合的 usage_update: { / a2ui: { session-update 列表;负例测试覆盖 malformed/client/status 块中引用标记的情形以及 usage_update: rejected by the proxy 这类普通文本

议题级条目:原始值 payload 缺口(stringifyJson 对字符串原样返回、对原始值裸输出,导致以 { 开头的锚定放过了非对象旧投影)已在 c21818d5ec 修复——模式不再依赖 payload 首字符,回归测试覆盖对象、数组、字符串、数字、布尔、null 与空 payload;报告者已独立复核该提交。非阻断的 reducer 状态发现(被隐藏的块仍会消耗 maxBlocks 并结束当前 assistant 块)有意不在本 PR 处理,已在 #8823 单独跟踪,报告者明确表示不阻塞本 PR。

本轮没有报告失败的检查,也没有持续红色的检查。

验证

在 head c9224e567d(合并后)实际执行的命令:

  • npm run build — 通过(exit 0)
  • npm run typecheck — 通过(exit 0)
  • npm run lint — 通过(exit 0)
  • npx vitest run test/unit/daemonUi.test.ts test/unit/daemon-public-surface.test.ts(packages/sdk-typescript,触及文件)— 304 通过
  • npx vitest run client/adapters/transcriptToMessages.test.ts(packages/web-shell,触及文件)— 120 通过
  • npx vitest run(packages/sdk-typescript 全套件)— 32 个文件,1501 通过
  • npx vitest run(packages/web-shell 全套件)— 173 个文件,2982 通过

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed — no blockers. Suggestions are inline.

中文说明

已审查——无阻断问题。 建议见行内评论。

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

case 'status':
case 'debug': {
const statusBlock = block;
if (isUnrecognizedDaemonDebug(statusBlock)) break;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-1: This filter leaves behind a now-dead, duplicated copy of the legacy marker match: isMidTurnInjectedDebugMessage in packages/web-shell/client/components/MessageList.tsx:650-652 still branches on message.content?.startsWith('mid_turn_message_injected (unrecognized daemon event):'). Probe-verified at this head: no message reaching MessageList can carry that prefix anymore — new blocks are dropped via debugReason === 'unrecognized_event', legacy blocks via LEGACY_UNRECOGNIZED_EVENT_PATTERN (which matches mid_turn_message_injected (unrecognized daemon event): ), and the dedicated normalizer case emits a status event whose text (Inserted message: …) never starts with the marker. — Concrete cost: the SDK comment this PR adds declares the diagnostic wording "changes without notice"; when it does, this orphaned shim silently stops matching, and no production data flows through it (the MessageList.test.ts fixtures exercise only the source branch). Fix, in MessageList.tsx (outside this diff):

const isMidTurnInjectedDebugMessage = (message: DaemonMessage): boolean =>
  message.source === 'mid_turn_message_injected';
中文说明

[建议] 该过滤器使得旧版标记匹配的另一个副本变成了死代码:packages/web-shell/client/components/MessageList.tsx:650-652 中的 isMidTurnInjectedDebugMessage 仍然基于 message.content?.startsWith('mid_turn_message_injected (unrecognized daemon event):') 分支。在此 head 上经探针验证:到达 MessageList 的消息不再可能携带该前缀——新区块通过 debugReason === 'unrecognized_event' 被丢弃,旧版区块通过 LEGACY_UNRECOGNIZED_EVENT_PATTERN(会匹配 mid_turn_message_injected (unrecognized daemon event): )被丢弃,而专门的 normalizer 分支发出的是 status 事件,其文本(Inserted message: …)从不以该标记开头。— 具体代价:本 PR 新增的 SDK 注释声明诊断措辞"随时可能变化,恕不通知";一旦措辞变化,这个孤立的兜底分支会悄悄失效,而没有任何生产数据流经它(MessageList.test.ts 的 fixture 只覆盖 source 分支)。修复方式(位于本 diff 未触及的 MessageList.tsx):删除 isMidTurnInjectedDebugMessage 中的 content?.startsWith(...) 分支,仅保留 message.source === 'mid_turn_message_injected'

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

Comment on lines +943 to +944
/** Mirrors `DaemonUiStatusEvent.debugReason`; only set on `debug` blocks. */
debugReason?: DaemonUiDebugReason;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-2: The new renderer-facing closed enum debugReason / DAEMON_UI_DEBUG_REASONS is undocumented in docs/developers/daemon-ui/README.md, where its sibling closed enums are documented ("Error categorization (PR-A)" for errorKind — "Renderers should branch on errorKind" — and "Tool provenance dispatch"). The doc's "Forward-compat principles" bullet still says "Unknown daemon event types → debug event with the raw type name", with no mention that these projections now carry a debugReason renderers must branch on; MIGRATION.md documents DaemonErrorKind for renderer authors and is likewise untouched. — Concrete cost: an adapter author following that doc either renders the raw-JSON spam this PR exists to remove, or pattern-matches the text prefix — the exact brittle coupling the new normalizer comment forbids ("the text prefix is diagnostic wording and changes without notice") — so their filter silently breaks the next time the wording changes. Suggested fix: add a short section beside "Error categorization" documenting DaemonUiDebugReason (the three values, the unrecognized-vs-malformed semantics, and "branch on debugReason, not the text prefix"), and extend the "Unknown daemon event types" bullet to note the stamp.

中文说明

[建议] 新的面向渲染器的封闭枚举 debugReason / DAEMON_UI_DEBUG_REASONS 未在 docs/developers/daemon-ui/README.md 中记录,而该文档正是记录其同类封闭枚举的地方(errorKind 的 "Error categorization (PR-A)"——"Renderers should branch on errorKind"——以及 "Tool provenance dispatch")。文档中 "Forward-compat principles" 一条仍写着 "Unknown daemon event types → debug event with the raw type name",没有提到这些投影现在携带渲染器必须据以分支的 debugReasonMIGRATION.md 为渲染器作者记录了 DaemonErrorKind,同样未被更新。— 具体代价:按该文档实现的适配器作者要么渲染出本 PR 要消除的原始 JSON 刷屏,要么去匹配文本前缀——正是新 normalizer 注释所禁止的脆弱耦合("文本前缀是诊断措辞,随时可能变化,恕不通知")——他们的过滤器会在下次措辞变化时悄悄失效。建议修复:在 "Error categorization" 旁增加一小节,记录 DaemonUiDebugReason(三个取值、unrecognized 与 malformed 的语义,以及"基于 debugReason 分支,而不是文本前缀"),并扩充 "Unknown daemon event types" 条目说明该标记。

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

Comment on lines +178 to +183
if (block.debugReason !== undefined) {
return (
block.debugReason === 'unrecognized_event' ||
block.debugReason === 'unrecognized_session_update'
);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-3: This check enumerates two exact debugReason values, while the SDK's own contract — the doc comment on DAEMON_UI_DEBUG_REASONS this PR adds — defines the semantics by wildcard-named category: unrecognized_* is forward-compat noise to hide, malformed_* is a defect signal to keep visible. Probe-verified at this head: a block stamped unrecognized_tool_frame renders as raw JSON (even with marker-shaped text the legacy regex would otherwise catch), because the defined-reason short-circuit runs before the legacy fallback; the category-prefix variant below hides it without disturbing any currently-covered shape. Adding a fourth union member compiles silently against the two-literal comparison, so neither typecheck nor any existing test catches it. — Failure scenario: a future SDK release adds such a reason and stamps it in the normalizer → the exact match returns false → raw JSON dumps render in conversations again — the exact spam this PR removes returns silently, with both suites green.

Suggested change
if (block.debugReason !== undefined) {
return (
block.debugReason === 'unrecognized_event' ||
block.debugReason === 'unrecognized_session_update'
);
}
if (block.debugReason !== undefined) {
return block.debugReason.startsWith('unrecognized_');
}

(Alternatively, keep the enumeration with a comment noting each new unrecognized_* reason requires a Web Shell update.)

中文说明

[建议] 该检查精确枚举了两个 debugReason 取值,而 SDK 自身的契约——本 PR 新增的 DAEMON_UI_DEBUG_REASONS 文档注释——是按通配命名的类别定义语义的:unrecognized_* 是应隐藏的前向兼容噪音,malformed_* 是应保持可见的缺陷信号。在此 head 上经探针验证:打上 unrecognized_tool_frame 的区块会渲染出原始 JSON(即使其文本是旧版正则可以捕获的标记形状),因为携带 reason 的短路分支先于旧版兜底执行;改用下面的类别前缀匹配即可将其隐藏,且不影响当前已覆盖的任何形状。给联合类型新增第四个成员时,与两个字面量的比较仍能通过编译,因此 typecheck 和现有测试都无法捕获该问题。— 失败场景:未来某个 SDK 版本新增这样一个 reason 并在 normalizer 中打上 → 精确匹配返回 false → 原始 JSON 转储再次出现在对话中——本 PR 消除的刷屏悄悄回归,而两个测试套件全绿。

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

The debugReason filter enumerated the two current `unrecognized_*` values,
but the SDK contract this PR adds names reasons by category: `unrecognized_*`
is forward-compat noise to hide, `malformed_*` a defect signal to keep
visible. A reason a newer SDK adds would compile silently against the
two-literal comparison and render raw JSON again with both suites green.

Match the category prefix instead. Also drop the now-dead marker branch in
MessageList's mid-turn hide check: every block carrying that prefix is
filtered upstream in the adapter (reason-stamped via `debugReason`, legacy
via the anchored pattern), and the dedicated normalizer case emits a status
event keyed by `source`. Document `DaemonUiDebugReason` beside the sibling
closed enums in the daemon-ui docs, whose forward-compat bullet still
described the unstamped projection.

Regression test pins both directions of the category contract with reasons
outside the current enum.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round — PR #8812

All three automated-reviewer suggestions (R2-1, R2-2, R2-3) were verified
against this head, accepted, and addressed in one commit
(fix(web-shell): hide debug blocks by the unrecognized_ reason category).
No conflict resolution was needed (--conflict false); origin/main was not
merged.

Feedback points and dispositions

R2-1 — dead duplicated legacy marker match in MessageList.tsx — RESOLVED

Verified: after this PR no message reaching MessageList can carry the
mid_turn_message_injected (unrecognized daemon event): prefix —
reason-stamped blocks are dropped via debugReason, legacy blocks via the
anchored LEGACY_UNRECOGNIZED_EVENT_PATTERN (which matches that exact
prefix), and the normalizer's dedicated case emits a status event keyed by
source with Inserted message: … text. Client-side system messages (recap,
model-switch summary) never carry the prefix either.

Fix: isMidTurnInjectedDebugMessage in
packages/web-shell/client/components/MessageList.tsx now checks only
message.source === 'mid_turn_message_injected', dropping the dead branch
and the content field from its structural parameter. All three call sites
pass the full message object; existing MessageList.test.ts fixtures already
exercise the source branch. This also removes the brittle coupling to
diagnostic wording the PR itself declares unstable.

R2-2 — debugReason enum undocumented — RESOLVED

Added a "Debug reason categorization" section to
docs/developers/daemon-ui/README.md beside the sibling closed-enum sections
(Error categorization, Tool provenance dispatch): the three current values,
the unrecognized_* vs malformed_* category semantics, "branch on
debugReason, not the text prefix" guidance with a code example, and the
note that status events and client-dispatched debug events carry no reason
and must keep rendering. The stale "Forward-compat principles" bullet now
records that unknown daemon event types are stamped with an unrecognized_*
debugReason.

Scope note: MIGRATION.md was deliberately left untouched — it is the
versioned v1→v2 migration recipe, while the README is the living reference
where both sibling closed enums are documented; the finding's suggested fix
targets the README and the forward-compat bullet.

R2-3 — filter enumerated two exact reasons instead of the category — RESOLVED

Verified: the SDK contract (the doc comment on DAEMON_UI_DEBUG_REASONS this
PR adds) defines semantics by wildcard-named category, and a future union
member would compile silently against the two-literal comparison.

Fix: isUnrecognizedDaemonDebug in
packages/web-shell/client/adapters/transcriptToMessages.ts now returns
block.debugReason.startsWith('unrecognized_') when a reason is present —
fewer lines, and it implements the documented category contract directly.
malformed_* reasons and client-dispatched blocks (no reason) still render.
The function's doc comment was updated to describe the category rule.

Added a regression test that pins both directions with reasons outside the
current enum: a hypothetical unrecognized_tool_frame block is hidden and a
hypothetical malformed_tool_frame block keeps rendering.

Checks

  • No conflict resolution performed (flag was false).
  • No settings source changed, so no schema regeneration needed.
  • No bundled-CLI/integration-harness behavior changed (Web Shell UI + docs
    only), so no integration run needed.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run client/adapters/transcriptToMessages.test.ts client/components/MessageList.test.ts (in packages/web-shell) — 2 files, 252 passed
  • npx vitest run (entire packages/web-shell package) — 173 files, 2983 passed
中文说明

Autofix 审查轮次 — PR #8812

自动化审查器的三条建议(R2-1、R2-2、R2-3)均已在当前 head 上核实、采纳,并通过一个提交(fix(web-shell): hide debug blocks by the unrecognized_ reason category)一并处理。无需解决冲突(--conflict false),未合并 origin/main

反馈点与处置

R2-1 — MessageList.tsx 中失效且重复的旧版标记匹配 — 已解决

已核实:本 PR 之后,到达 MessageList 的消息不可能再携带 mid_turn_message_injected (unrecognized daemon event): 前缀——带 reason 标记的区块通过 debugReason 被丢弃,旧版区块通过锚定的 LEGACY_UNRECOGNIZED_EVENT_PATTERN(恰好匹配该前缀)被丢弃,而 normalizer 的专门分支发出的是以 source 为键、文本为 Inserted message: …status 事件。客户端侧的 system 消息(recap、模型切换摘要)也从不携带该前缀。

修复:packages/web-shell/client/components/MessageList.tsx 中的 isMidTurnInjectedDebugMessage 现在只检查 message.source === 'mid_turn_message_injected',删除了失效分支及其结构化参数中的 content 字段。三个调用点均传入完整消息对象;现有 MessageList.test.ts fixture 已覆盖 source 分支。这也移除了对本 PR 自身声明"随时可能变化"的诊断措辞的脆弱耦合。

R2-2 — debugReason 枚举缺少文档 — 已解决

docs/developers/daemon-ui/README.md 中同类封闭枚举章节(Error categorization、Tool provenance dispatch)旁新增 "Debug reason categorization" 一节:当前三个取值、unrecognized_*malformed_* 的类别语义、"基于 debugReason 分支而非文本前缀"的指引及代码示例,并说明 status 事件与客户端自发 debug 事件不携带 reason、必须继续渲染。过时的 "Forward-compat principles" 条目现已注明未知 daemon 事件类型会打上 unrecognized_*debugReason

范围说明:MIGRATION.md 有意未改动——它是 v1→v2 的版本化迁移指南,而 README 才是记录两个同类封闭枚举的现行参考文档;该发现的建议修复也只针对 README 与 forward-compat 条目。

R2-3 — 过滤器枚举两个精确取值而非按类别匹配 — 已解决

已核实:SDK 契约(本 PR 新增的 DAEMON_UI_DEBUG_REASONS 文档注释)按通配命名的类别定义语义,且未来新增的联合成员面对两个字面量的比较会静默通过编译。

修复:packages/web-shell/client/adapters/transcriptToMessages.ts 中的 isUnrecognizedDaemonDebug 在存在 reason 时改为返回 block.debugReason.startsWith('unrecognized_')——代码更少,并直接实现了文档化的类别契约。malformed_* reason 与客户端自发区块(无 reason)仍会渲染。函数文档注释已同步更新为类别规则。

新增回归测试,用当前枚举之外的 reason 钉住两个方向:假想的 unrecognized_tool_frame 区块被隐藏,假想的 malformed_tool_frame 区块保持渲染。

检查

  • 未执行冲突解决(标志为 false)。
  • 未改动 settings 源,无需重新生成 schema。
  • 未改动打包 CLI / 集成测试覆盖的行为(仅 Web Shell UI 与文档),无需集成测试。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx vitest run client/adapters/transcriptToMessages.test.ts client/components/MessageList.test.ts(位于 packages/web-shell)— 2 个文件,252 通过
  • npx vitest run(整个 packages/web-shell 包)— 173 个文件,2983 通过

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

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


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run.

中文说明

🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。

@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

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

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

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

Verification report

PR 8812 Deep Verification (follow-up round 2) — fix(web-shell): stop rendering unrecognized daemon events in transcripts

Verdict: merge-ready — 131/131 scripted assertions passed, 0 fails (87 A/B cell assertions across both arms + 18 mutation-matrix checks incl. 4 unmutated controls + 19 suggested-fix probe assertions + 1 patched-suite check + 6 gate assertions). Verified head: 1d8a5d7ec6a50f80b355485f58de632ef12637b4 (git rev-parse HEAD^2), base 55e20db328248436ae65743986906ff1fbc5ea58 (HEAD^1). This is a follow-up round: the previous round verified head c9224e56; one substantive commit was added since — 8c9dbb0d ("hide debug blocks by the unrecognized_ reason category") — plus the merge of current main. Every carried-forward measurement was rebuilt and re-run at the new head; nothing was diffed from the old report. One new note-level finding (non-string debugReason throws) with a measured one-clause fix.

中文 — 判定:✅ 通过 · 可合入(agent 判定)
  • 结论: merge-ready。131/131 脚本化断言通过,0 失败。
  • 上一轮发现的状态: 空白判别符 note —— 维持 已修复(W10 重新测量 + M7 钉死);sdk lint 崩溃定性 —— 维持 已更正(本轮在新容器再次复现:提交在 packages/sdk-typescript/package.jsoneslint: ^8.57.0 与根 ^9.24.0 的嵌套安装冲突,base 同样存在);rawEvent 描述更正 —— 依旧成立。见状态表。
  • A/B 结论(见 01-ab-head-filtered.png / 02-ab-base-json-leak.png): base 臂 17 个对照单元格泄漏/渲染(其中 12 处原始 JSON 行 + 碰撞探针 L8 + 4 个本轮新增 category 单元格),head 臂全部过滤或按预期行为处理,0 泄漏;所有应保留的诊断(malformed、客户端自派发 debug、prose、引用标记的块、status 块)两臂逐格一致。
  • 本轮增量验证: 过滤改为按 unrecognized_ 类别前缀——未来 SDK 新增的 unrecognized_* reason 自动被隐藏(C1 单元格 + M10 变异钉死新测试),未来 malformed_* reason 保持可见(C2)。MessageList 被删除的 content-prefix 分支经 M12 变异证实为死代码(恢复它 0 个测试变化),且 PC2 阳性对照证明该套件对此函数是活的。
  • 新发现(note,不阻塞): debugReason 为非字符串(null/数字等)时,新的 startsWith 表达式抛 TypeError(base 渲染)——现实产生路径不可达,但违反同 PR 新增文档的 forward-compat 措辞;已在 scratch 副本测量单行修复(typeof === 'string'):良性输入字节级一致、恶意输入降级为可见、套件计数不变(121/121)。
  • 变异矩阵: 12 个变异/阳性对照全部按预期被精确钉死,2 个预测幸存者(M11 覆盖缺口:下划线边界无测试;M12 死代码)均有定性证据。0 意外幸存。
  • : web-shell 2983/2983、sdk-typescript 1501/1501、两包 typecheck 干净、根 eslint 9.29.0 两包干净(探针证实门禁有效)。
  • 未覆盖: 真实 daemon + Chrome 端到端;"帧仍在线上" 为构造性结论;逐 commit 归因(depth-2 不可达)。

Previous-finding status (follow-up round)

# Previous finding (round 2 @​ c9224e56) Severity Status at new head 1d8a5d7e
1 sessionUpdate: ' ' (whitespace-only) classified unrecognized and hidden note fixed (carried, re-measured) — cell W10 renders visible with reason=malformed_payload on head; mutant M7 (drop trim() gate) killed by exactly the discriminator test.
2 npm run lint inside packages/sdk-typescript crashes — committed eslint: ^8.57.0 devDep vs root ^9.24.0 note stands (re-measured) — fresh reproduction this round: nested eslint@8.57.1 installed, npm run lint exits 2, identical at base (PR touches no package.json/lockfile — verified from the diff file list). Pre-existing, not PR-caused; gate uses root eslint 9.29.0.
3 Correction: PR Risk section says "rawEvent still carries the original envelope" but rawEvent is stamped only with includeRawEvent: true, which Web Shell never sets correction stands — re-verified: normalizer.ts:607 still conditional; zero occurrences of includeRawEvent in packages/web-shell/client/. Description text unchanged. No code change requested.
4 Shim collision is inherent (cell L8): a client-dispatched debug block whose text starts exactly a2ui: { is filtered note stands (re-measured) — L8 flips render → filter exactly as before; shim unchanged by this round's delta. Documented tradeoff.
5 Event types outside [A-Za-z0-9_.-] escape the shape shim (cell L9) note stands (re-measured) — L9 renders on both arms (parity); new projections carry debugReason regardless.

Central claim + A/B

Central claim (carried): unrecognized daemon frames no longer render as raw-JSON rows in Web Shell transcripts; malformed_payload diagnostics and client-dispatched debug blocks keep rendering — keyed on structured debugReason, with a shape shim for legacy blocks carrying no reason.
Delta claim (this round): the reason filter matches the unrecognized_* category prefix (block.debugReason.startsWith('unrecognized_')) instead of the two enum literals, so a reason a newer SDK adds is hidden without a Web Shell change, while every other reason — including a future malformed_* — keeps rendering. The MessageList content-prefix branch for mid_turn_message_injected (unrecognized daemon event): was removed as dead.

Harness (harness-ab.ts, rerunnable): real wire envelopes → normalizeDaemonEventreduceDaemonTranscriptEventstranscriptBlocksToDaemonMessages (the production chain), plus legacy/category cells feeding already-projected blocks directly into the adapter (the WebShellTranscript public seam). Head arm loaded the merge-commit tree; base arm loaded a git worktree at HEAD^1 = 55e20db3; each run prints the module URLs it loaded (logs/head-ab.log, logs/base-ab.log) — the base log shows only tmp/base-tree/… URLs, so base executed base-tree code. The adapter's @qwen-code/sdk/daemon import is import type (erased); its only runtime import is relative. Lockfile untouched by the PR, so reusing the root node_modules is a clean control.

Section W — wire frames (normalize → reduce → adapter)

# Input frame Base Head
W1 agent_message_chunk "Surface presented." assistant msg ✓ assistant msg ✓
W2 session_update kind a2ui raw JSON row leaks filtered — unrecognized_session_update, block kept in state
W3 unknown top-level some_future_event raw JSON row leaks filtered — unrecognized_event
W4 language_changed filtered (old text prefix) filtered (debugReason) — parity
W5 session_cwd_changed filtered (old text prefix) filtered (debugReason) — parity
W6 session_update update: {} (no discriminator) visible visible — malformed_payload
W7 memory_changed bad scope visible visible — malformed_payload
W8 model_switched → status Model switched: … filtered (kept text check) filtered (kept text check)
W9 client-dispatched debug model_switch_summary visible, source+data intact visible, source+data intact, block has no debugReason
W10 sessionUpdate: ' ' (whitespace) visible visible — malformed_payload (round-1 note stays fixed)
W11 session_update kind usage_update zero blocks (#8790) zero blocks (#8790) — A/A parity
W12 mid_turn_message_injected well-formed visible, keyed by source visible, keyed by source — parity (dedicated normalizer case)
W13 mid_turn_message_injected {} (malformed) visible visible — malformed_payload (shim does not match the fallback text)

Section L — legacy/persisted blocks (no debugReason) into the adapter

# Block text (kind) Base Head
L1 language_changed (unrecognized daemon event): {"language":"en"} (debug) filtered (old prefix) filtered (shape shim) — parity
L2 some_future_event (unrecognized daemon event): {"a":1} (debug) renders filtered — flip
L3 usage_update: {"used":46351,…} (debug) renders filtered — flip
L4 a2ui: {"surfaceId":"s1",…} (debug) renders filtered — flip
L5 marker + non-object payloads 42 / true / null / plain string / empty ×5 all 5 render all 5 filtered — flip
L6 marker + pretty-printed (2-space indent) payload renders filtered (prefix still matches)
L7 5 keep-negatives: status quoting marker; debug relaying marker mid-text; client summary quoting marker; status starting usage_update: {; prose usage_update: rejected by the proxy all 5 visible all 5 visible
L8 collision probe: client-dispatched debug (source set, no reason) whose text starts a2ui: {… renders filtered — inherent shim boundary (carried note)
L9 char-class probe: marker with space in event type (weird type (…)) renders renders — parity (carried note)
L10 legacy malformed shape session_update: {"update":{}} (debug) visible visible — closed list does not swallow old malformed diagnostics
L11 new: legacy mid_turn_message_injected (unrecognized daemon event): … (debug) renders (old MessageList branch only collapsed it) filtered upstream — proves the removed MessageList branch's target is handled by the adapter

Section C — debugReason category cells (this round's delta)

# Block (kind debug) Base Head
C1 reason unrecognized_tool_frame (outside this build's enum) renders (field ignored) filtered by category prefix — the delta claim
C2 reason malformed_tool_frame (future defect signal) renders rendersmalformed_* category keeps rendering
C3 reason unrecognized (no trailing underscore) renders renders — category boundary, visible by design
C4 reason '' renders renders — parity
C5 reason null renders throws TypeError: Cannot read properties of null (reading 'startsWith') — see Findings
C6 reason 42 renders throws TypeError: …startsWith is not a function — see Findings
C7 reason unrecognized_tool_frame + text quoting the marker renders filtered — classified reason wins over the shim

Counts: head 47/47, base 40/40 (base arm has fewer reason-stamp checks). 17 base-arm CONTROL cells leak or render: 12 raw-JSON leaks (W2, W3, L2, L3, L4, L5×5, L6, L11), the collision probe L8, and the 4 category cells (C1, C7 filtered on head as intended; C5/C6 throw on head — the finding probe, predicted and encoded as passing assertions; C2–C4 keep-negatives). All parity/keep cells (W1, W4–W13 except W2/W3, L1, L7×5, L9, L10, C2, C3, C4) are identical across arms. The filter is render-layer only: W2-head asserts the block survives in transcript state with its reason, so "which frame was this" remains recoverable from state and from the wire. Witness images: 01-ab-head-filtered.png, 02-ab-base-json-leak.png.

Corrections

No new corrections this round. The round-2 correction of the rawEvent description stands (status table row 3), and the round-2 characterization of the sdk lint crash as a committed-dependency conflict (not sandbox residue) was re-confirmed (row 2).

Findings

  • (note, new this round) The category-prefix expression is not total on degenerate debugReason values. The delta changed the reason branch from === 'unrecognized_event' || === 'unrecognized_session_update' (total) to block.debugReason.startsWith('unrecognized_') guarded only by !== undefined — so a block carrying debugReason: null / 42 / true / {} now throws a TypeError inside transcriptBlocksToDaemonMessages (cells C5/C6; base rendered them). That function runs on every transcript render via useMessages, and Web Shell's only containment is the root ErrorBoundary (main.tsx:153RootErrorFallback) — so one such block replaces the entire app view with the error fallback screen. Reachability is low: every producer in this system writes string-or-absent (the normalizer stamps literals; the reducer's carry-over is truthy-gated; the typed public API excludes null), so triggering it requires a hand-edited persisted transcript or an out-of-system producer. It is still a robustness regression introduced by this round's delta, and it contradicts the forward-compat wording the same PR adds to docs/developers/daemon-ui/README.md — whose example (reason?.startsWith('unrecognized_') ?? false) is null-safe via ?., i.e. the documented pattern is more defensive than the shipped code.

    Measured suggested fix (scratch copy, not applied to the PR): guard with typeof

    -  if (block.debugReason !== undefined) {
    +  if (typeof block.debugReason === 'string') {
         return block.debugReason.startsWith('unrecognized_');
       }

    Three measured results (logs/fix-probe.log, fix-verify.json): (1) hostile fixtures go clean — null/42/true/{} no longer throw and degrade to visible, the safe default; (2) benign fixtures come out byte-identical — 11 string/absent-reason shapes produce identical message JSON on original vs patched; (3) the affected suite's counts are unchanged — adapter file 121/121 green both with and without the patch, so the fix should ship with its fixture: a block with debugReason: null asserting no throw + visible (no current test pins this axis). 19/19 probe assertions + 1 suite check passed.

  • (note, carried) Shim collision is inherent (cell L8, unchanged): a client-dispatched debug block with no reason whose text starts exactly a2ui: { / usage_update: { is indistinguishable from a persisted legacy block and is filtered. The only known client dispatcher (model_switch_summary) never produces these shapes; the alternative reopens the original spam for every persisted transcript. Documented tradeoff, not a defect.

  • (note, carried) Event types outside [A-Za-z0-9_.-] escape the shape shim (cell L9, unchanged): parity with base, and new projections carry debugReason regardless.

Mutation matrix (vacuity of the new/changed tests)

Scripted (mutation-runner.mjs): mutate in place → run catching suite with vitest JSON reporter → assert the failed set matches the intended tests exactly → restore via git checkout. Unmutated controls green: adapter 121/121, MessageList 131/131, daemonUi.test.ts 290/290, daemon-public-surface.test.ts 14/14. Witness: 03-mutation-matrix.png.

Mutant Guard removed / inverted Suite Result
M1 delete the isUnrecognizedDaemonDebug filter call (whole feature) adapter killed 6/6 — exactly the six filter tests (incl. the new category test)
M2 disable the legacy shape shim only (reason branch intact) adapter killed 3/3 — exactly the three legacy tests
M3 drop the kind === 'debug' guard (shim reaches status blocks) adapter killed 1/1 — "only matches the legacy shape…"
M4 restore substring marker match (unanchored) adapter killed 1/1 — "only matches the legacy shape…"
M5 restore the leading-char class [{"[] on the legacy payload adapter killed 1/1 — "filters legacy projections whose payload is not an object"
M8 loosen prefixes to bare usage_update: / a2ui: adapter killed 1/1 — "does not let the legacy prefixes swallow prose…"
M10 REVERT the category prefix to the two-literal enum comparison (pre-delta code) adapter killed 1/1 — exactly the new test "keys the filter off the unrecognized_ category prefix, not the enum": the delta's central test is non-vacuous
M11 loosen the prefix to startsWith('unrecognized') (no underscore) adapter SURVIVED (predicted) — coverage gap: no test pins the trailing-underscore boundary (behavior matches the documented unrecognized_* convention; a reason named without the underscore would render — the safe default)
PC1 positive control: isIgnoredWebShellStatus returns false adapter killed 1/1 — "filters SDK model switch status noise"
M6 default debugReason in appendStatusBlock (?? 'unrecognized_event') sdk killed 1/1 — the mirror invariant test
M7 drop the trim() gate sdk killed 1/1 — "classifies a session_update with no usable discriminator as malformed"
M9 drop the DAEMON_UI_DEBUG_REASONS value re-export from the public entry sdk killed 1/1 — "pins the union shipped by @​qwen-code/sdk/daemon" (runtime assertion; import resolves undefined)
M12 RESTORE the removed MessageList content-prefix branch MessageList SURVIVED (predicted) — dead code: no message reaching MessageList can carry that content (the adapter's shape shim filters every such block upstream; the only other system-message producer is source: 'recap'), so restoring the branch changes nothing. This is the evidence the removal is behavior-preserving
PC2 positive control: isMidTurnInjectedDebugMessage returns false MessageList killed 2/2 — "classifies mid-turn status…" + "hides mid-turn injected debug rows…" — proves the suite is live for this function, so M12's survival means exactly "the removed branch contributed nothing"

12 killed with exact test-set matches, 2 predicted survivors both adjudicated (1 coverage gap, 1 dead code), 0 unexpected survivors, zero collateral failures. Both survivors carry positive controls (PC1/PC2) proving the harness can fail the suites.

Targeted gates (head 1d8a5d7e)

Gate Result
packages/web-shell full suite 2983/2983 pass, 173 test files (round 2: 2982 — delta is this round's 1 new category test)
packages/sdk-typescript full suite 1501/1501 pass (unchanged — no sdk test deltas this round)
tsc --noEmit both packages clean (exit 0, re-run live inside 04-gates-suite-counts.png)
eslint (root 9.29.0 flat config, scoped packages/web-shell/client + packages/sdk-typescript/src + test) clean (exit 0); liveness probe (planted unused variable) reported @typescript-eslint/no-unused-vars on both packages before the clean run
npm run lint inside sdk package exits 2 on nested eslint@​8.57.1 — pre-existing committed-dependency conflict, identical at base (see status table); not used as the gate

Witness: 04-gates-suite-counts.png. Multi-commit note: the snapshot lists 9 commits but the checkout is depth-2 (git rev-list HEAD^1..HEAD^2 returns 1, the shallow-boundary artifact), so per-commit attribution is out of reach; the aggregate HEAD^1..HEAD diff is what this round verified. Merge verified by construction: the PR head 1d8a5d7e is itself a merge of 8c9dbb0d with the current base tip 55e20db3, so the CI merge commit is conflict-free; main's only delta (packages/core/src/tools/workflow/*, #8694) is outside this PR's surface.

Not covered

  • Reviewer Test Plan in a real browser/daemon: steps map to harness cells — step 1 (unrecognized event) → W2/W3/C1; step 2 (JSON row gone, conversation intact) → W1–W3; step 4 (model-switch summary survives) → W9 — but no live qwen serve + Chrome session was driven. The A/B exercises the identical normalize→reduce→adapter chain the live path uses; this reproduces the shape, not the end-to-end trigger.
  • Step 3 ("frame still on the wire"): by construction only — the normalizer is a pure projection and the diff touches no serve route; no SSE capture recorded.
  • Per-commit attribution for the delta commit (depth-2 checkout; verified in aggregate).
  • Repo-wide lint/typecheck/test — only the two changed workspaces ran (per scope).
  • webui rendering: verified by code reading only (it unconditionally drops all kind === 'debug' blocks, so this PR cannot change its behavior).
  • Reason-stamped status blocks: impossible by construction (the normalizer stamps only debug events and the reducer only carries the field for them), so no cell was built for one.
  • The C5/C6 suggested fix is measured in a scratch copy only; it is not applied to the PR tree.

Methodology

Environment: CI verify container (node:22-bookworm), tree = refs/pull/8812/merge (depth 2), npm ci + npm run build pre-run at HEAD. Harnesses drove TypeScript sources directly via tsx; each A/B arm printed the module URLs it loaded so the base arm's isolation is evidenced in the logs, not assumed (logs/head-ab.log, logs/base-ab.log); the base arm ran from git worktree tmp/base-tree at HEAD^1, reusing root node_modules (lockfile untouched by the PR; the adapter's only runtime import is relative and its SDK import is type-only/erased). A/B: 31 cells (13 wire frames + 11 legacy blocks + 7 category blocks; L5's five non-object payloads are separate assertions) piped through the production chain on both arms, arm-conditional expectations encoded as assertions (a base cell leaking JSON is a control assertion that passes when base leaks). Suggested-fix evidence came from a scratch copy of packages/web-shell/client: the probe's "original" side was reconstructed from git show HEAD: (byte-verified identical) because the copy was made while the mutation runner owned the tree; the "patched" side's integrity is established by the probe itself — its 11 byte-identity assertions compare it against that proven-clean original across every pre-fix behavior (reason branch, shim, prefixes, status kind), so any stray state would have surfaced as a divergence. Mutation matrix: in-place mutation + vitest JSON reporter + git checkout restore, 14 mutants/controls + 4 unmutated controls, scripted in mutation-runner.mjs; the matrix was re-run live inside the capture for 03-mutation-matrix.png. Gates: full workspace suites (JSON reporter artifacts gate-web-shell.json, gate-sdk.json), tsc --noEmit, root eslint 9.29.0 with planted liveness probes. Raw logs in logs/; harnesses harness-ab.ts, mutation-runner.mjs, scratch/fix-probe.ts, and gate-summary.sh are rerunnable. Base worktree removed after the last base-arm run; tree left clean (git status empty).

Evidence images

01-ab-head-filtered

02-ab-base-json-leak

03-mutation-matrix

04-gates-suite-counts

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

Qwen Code · sandboxed verification

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix review round: no action needed

The feedback batch for this round contained no actionable items:

  • Reviews: none newer than the last evaluation.
  • Inline comments: none.
  • Issue-level comments: only the CI bot status comment announcing that sandboxed verification is still running — a notification, not a change request.
  • Failed / still-red checks: none. All completed checks are green (SUCCESS) or SKIPPED; the automated review-pr check is simply still in progress.

No code changes were made this round. The branch remains at its current head, and no commit was created. Once the in-progress verification/review run completes, any findings it produces will be triaged in a subsequent round.

中文说明

Autofix 复查轮次:无需处理

本轮收到的反馈中没有需要处理的事项:

  • Review(审查意见): 自上次评估以来没有新的审查意见。
  • 行内评论: 无。
  • Issue 级评论: 仅有 CI 机器人发布的状态评论,告知沙箱验证仍在运行中——这是一条状态通知,并非修改请求。
  • 失败 / 持续失败的检查: 无。所有已完成的检查均为通过(SUCCESS)或跳过(SKIPPED);自动化的 review-pr 检查只是仍在运行中。

本轮未做任何代码改动。分支保持在当前提交,未创建新的提交。待正在运行的验证/审查完成后,其产生的任何发现都将在后续轮次中进行分类处理。

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


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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review — no blockers.

My independent proposal for this problem was exactly the shape this PR took: stamp a classification on normalizer-produced debug events, mirror it onto transcript blocks, have Web Shell hide the unrecognized_* category while keeping malformed_* and client-dispatched blocks visible, and carry a narrow shim for pre-debugReason transcripts. The PR matches it, and the review rounds hardened the parts I'd have been most worried about. Verified at the head commit:

  • All seven debug-producing sites in the normalizer stamp a reason; the reducer mirrors debugReason onto the block in appendStatusBlock, and a test pins that boundary specifically (the gap where both suites could pass while the field is dropped in transit).
  • The malformed/unrecognized split in the session_update default branch is type-safe: kind comes from getString(update, 'sessionUpdate') (string | undefined), so kind?.trim() correctly keeps missing/empty/whitespace/non-string discriminators visible as malformed_payload — broken frames keep their only diagnostic.
  • The legacy shim is disciplined: anchored to the whole projection, scoped to debug blocks, payload deliberately unconstrained (stringifyJson returns strings verbatim and primitives bare), with negative tests for a status line quoting the marker, a malformed payload relaying one, and prose prefixes. The closed usage_update/a2ui session-update list is justified — those are the kinds known to exist in old transcripts, and a generic <word>: { rule would swallow real diagnostics.
  • Dropping the content-prefix branch in MessageList.tsx is covered: every message reaching it flows through transcriptBlocksToDaemonMessages, where legacy mid_turn_message_injected (unrecognized daemon event): blocks are caught by the anchored pattern, and the normalizer's dedicated case keys by source.
  • webui needs no change (its transcriptAdapter.ts drops all debug blocks), the only client-dispatched debug producer is Web Shell's model_switch_summary, and it keeps rendering — pinned by tests on both sides of the reducer. The public-surface test asserts the union at runtime, which is right: the type-only guard would be erased by the esbuild transpile.
  • Fail-open throughout: any block without a debugReason renders exactly as today, so old SDK / old daemon pairings carry no new regression.

Non-blocking observations: (1) the web-shell visuals harness has no scenario that seeds an unrecognized frame, so that check cannot see this change — a follow-up scenario in screenshots.spec.ts would pin the surface; (2) legacy session-update kinds other than the two listed still render from old transcripts — deliberate and documented, fine.

Testing — this is an unattended run: no PR code was built or executed here; evidence is the PR's own CI on the reviewed commit, fetched via the API, plus the thread's review record. All checks green on 1d8a5d7, including the full unit suite, the web-shell E2E smoke, and both Desktop Shell platforms; macOS/Windows unit legs and the CLI integration job are skipped per this repo's CI routing. The one still-running check (review-pr) is bot orchestration, not PR CI.

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

The suite pins the change rather than passing identically without it — the new tests assert debugReason values and filtering behavior that don't exist on base. The live before/after in a real browser session is the author's own evidence (real daemon + Chrome, build with no case 'a2ui'), not independently re-run here; @zjunothing independently verified the suppression behavior and full gate at the earlier c21818d5ec (all seven payload shapes suppressed, negative cases visible, focused and full suites green). Sandboxed verification would settle the remainder: @qwen-code /verify — A/B proof on this head that the category filter, not the removed prefix checks, is what suppresses each payload shape end-to-end, since the visuals harness has no scenario reaching this state.

中文说明

代码审查——无阻塞问题。

我对这个问题的独立方案与本 PR 的形态一致:normalizer 产生的 debug 事件打上分类标记、镜像到 transcript 块、Web Shell 隐藏 unrecognized_* 类别但保留 malformed_* 与客户端派发的块,并为 pre-debugReason 的旧 transcript 保留一个窄 shim。PR 与此一致,且 review 各轮恰好加固了我最担心的部分。已在 head 提交上核实:

  • normalizer 全部七个 debug 产生点都打上 reason;reducer 在 appendStatusBlock 中把 debugReason 镜像到块上,并有测试专门钉住这个边界(否则字段在传输中被丢弃时两边测试都还会绿)。
  • session_update 默认分支的 malformed/unrecognized 划分是类型安全的:kind 来自 getStringstring | undefined),kind?.trim() 正确地把缺失/空/纯空白/非字符串判别符保留为可见的 malformed_payload——坏帧保留了它唯一的诊断信息。
  • 旧版 shim 有纪律:锚定整个投影形状、仅作用于 debug 块、刻意不约束 payload 形状(stringifyJson 对字符串原样返回、原始值裸输出),并有负例测试(引用标记的 status 行、转述标记的 malformed payload、散文前缀)。usage_update/a2ui 的封闭列表是合理的——只有这两种确实存在于旧 transcript,通用的 <word>: { 规则会吞掉真实诊断。
  • 删除 MessageList.tsx 的内容前缀分支是被覆盖的:到达它的每条消息都经过 transcriptBlocksToDaemonMessages,旧格式块会被锚定模式拦下,normalizer 的专门分支按 source 归类。
  • webui 无需改动(其 adapter 丢弃所有 debug 块);唯一的客户端派发 debug 产生点是 Web Shell 的 model_switch_summary,它继续渲染——reducer 两侧都有测试钉住。公开接口测试在运行时断言枚举值是对的:纯类型守卫会被 esbuild 转译擦除。
  • 全程 fail-open:没有 debugReason 的块渲染行为与今天完全一致,旧 SDK / 旧 daemon 组合没有新回归。

非阻塞观察:(1) web-shell 视觉测试场景没有注入 unrecognized 帧的用例,该检查看不到本改动——后续可在 screenshots.spec.ts 补一个场景;(2) 列表中两种之外的旧 session-update 类型在旧 transcript 里仍会渲染——刻意且已文档化,可接受。

测试——本次为无人值守运行:未构建或执行任何 PR 代码;证据是通过 API 获取的 PR 自身 CI(见上表),以及线程中的 review 记录。1d8a5d7 上全部检查通过,包括完整单测、web-shell E2E smoke、两个 Desktop Shell 平台;macOS/Windows 单测与 CLI 集成测试按本仓库 CI 路由跳过。唯一仍在运行的 review-pr 是机器人编排任务,不是 PR CI。

新测试断言的 debugReason 值与过滤行为在 base 上不存在——套件钉住了改动本身。真实浏览器会话中的 before/after 是作者自己的证据(真实 daemon + Chrome),未在此独立复跑;@zjunothing 曾在较早的 c21818d5ec 上独立验证过抑制行为与完整门禁(七种 payload 形状全部被抑制、负例可见、聚焦与全量测试通过)。如需沙箱验证收尾:@qwen-code /verify——在当前 head 上 A/B 证明是类别过滤器(而非被删除的前缀检查)端到端地抑制了每种 payload 形状,因为视觉测试场景覆盖不到这个状态。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean across every stage; three rounds of skeptical human review burned everything flammable out of this, and what's left is the minimal classification fix with a pinning test at every boundary.

Stepping back: the approach matches my independent proposal, and the hard questions all resolve in its favour. The problem is observed and recurring (three per-symptom patches already), the fix attacks the classification instead of adding a fourth patch, and the SDK surface change is additive and documented. Every edit in the diff earns its place — the growth across the rounds is exactly what reviewers asked for: the discriminator-less/whitespace frames staying visible, the legacy shim anchored and payload-shape-agnostic, the reducer boundary tested, the docs written. The one reservation I'd normally carry into a merge — "the suite is green but does it pin anything?" — doesn't apply: the new tests fail on base by construction, and the fail-open invariant means the worst case for an unforeseen block is rendering exactly as it does today.

The only thing no one can show from CI is the live browser transcript, and the visuals harness has no scenario reaching this state — named in the Stage 2 comment with the lane that would settle it. That gap is small here (the change is a pure block→message mapping, independently verified by @zjunothing at the penultimate head, with the author's real-daemon evidence on top), so it is a follow-up, not a hold.

Approving, pinned to the reviewed commit — CI on it is fully green. ✅

中文说明

置信度:5/5——各阶段全部干净;经过三轮严格的人工审查,所有可质疑的点都已消除,留下的是最小的分类修复,每个边界都有钉住它的测试。

退一步看:方案与我的独立提议一致,所有难题都站在它这一边。问题是已观测且反复出现的(此前已打过三次按症状的补丁),修复攻击的是分类本身而不是第四次补丁,SDK 接口改动是增量且有文档的。diff 中每一处改动都有存在价值——各轮增加的内容恰好是 reviewer 要求的:无判别符/空白判别符帧保持可见、旧版 shim 有锚点且不依赖 payload 形状、reducer 边界有测试、文档补齐。我通常会在合并前保留的一点疑虑——"测试绿了但它钉住什么了吗?"——在这里不成立:新测试在 base 上必然失败,且 fail-open 不变式保证了未见过的块最坏也只是按今天的表现渲染。

唯一无法从 CI 展示的是真实浏览器中的 transcript,而视觉测试场景覆盖不到这个状态——已在 Stage 2 评论中点名,并给出可收尾的沙箱验证通道。这个缺口在此很小(改动是纯粹的块→消息映射,@zjunothing 已在倒数第二个 head 上独立验证,另有作者的真实 daemon 证据),因此是后续事项,不是拦阻理由。

批准,钉在所审查的提交上——该提交上的 CI 全绿。✅

Qwen Code · qwen3.8-max

Reviewed at 1d8a5d7ec6a50f80b355485f58de632ef12637b4 · 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. ✅

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

Re-review at head 1d8a5d7 after the two follow-up commits — both are improvements. The legacy shim handles exactly the backward-compat gap: WebShellTranscript is a public entry point taking already-projected blocks, so blocks projected or persisted by an SDK older than debugReason arrive with no reason; they are now shape-matched, and only shape-matched — the unrecognized-event regex is anchored at the start (a block merely quoting the marker stays visible), the payload is deliberately unconstrained since DaemonEvent.data is unknown and keying on a leading '{' would miss non-object payloads, and the legacy session_update prefixes are scoped to the two kinds known to have leaked (usage_update, a2ui) with the ': {' requirement so prose is never hidden. Switching the reason filter to the unrecognized_ prefix makes the category a contract: a reason a newer SDK adds under it is covered without a Web Shell change, while malformed_* and client-dispatched blocks stay visible by construction, and the README now documents that contract. Dropping the text-prefix fallback in MessageList's isMidTurnInjectedDebugMessage is the same cleanup. Tests cover the legacy shapes on both commits. CI green on this head. Nothing blocks merge.

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the full 11-file diff at head 1d8a5d7ec6a50f80b355485f58de632ef12637b4. No blocking findings remain. I traced every debugReason write/read/caller site and both public barrels, checked all downstream transcript consumers (SDK renderers, WebUI, and Web Shell), and re-audited the classification boundary for unknown top-level frames, unknown and malformed session_update payloads, malformed known events, client-dispatched debug events, and persisted pre-debugReason blocks. The legacy matching is now shape-scoped and quote-safe, future unrecognized_* reasons are handled by category, malformed diagnostics remain visible, and the stale MessageList text-prefix branch is gone. The previously reported compatibility and false-suppression defects are fixed on this exact head. Focused Web Shell adapter tests pass 121/121, git diff --check is clean, and the substantive Ubuntu, Web Shell smoke/visual, and desktop CI checks are green. Approving.

@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. Not explored to full depth (tool budget reached): Change summary: This PR adds a structured debugReason t...: Web Shell Playwright/e2e specs not run against the mutation (unit + adapter suites are the PR's declared guard and the seam both new test suites claim to cover)….

中文说明

已审查。 建议见行内评论。 未探索到全部深度(达到工具调用预算):Change summary: This PR adds a structured debugReason t...:Web Shell Playwright/e2e specs not run against the mutation (unit + adapter suites are the PR's declared guard and the seam both new test suites claim to cover)…

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

Comment on lines +1292 to +1294
// arrive with no reason. They must keep being filtered — and not only the
// two event types that used to be suppressed by name.
const legacy = (id: string, text: string) =>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-1: The five inline block factories added by these tests (three legacy closures, two block closures, plus bare literals) duplicate this file's existing statusBlock helper, whose overrides: Partial<DaemonStatusTranscriptBlock> spread already supports { kind: 'debug', debugReason, source, data } — each spells the base shape out behind an as DaemonTranscriptBlock assertion. Probe-verified during this review: adding a required field to DaemonTranscriptBlockBase makes the typed helper fail to compile while the as-cast shapes compile with no diagnostic. (Both packages' typecheck configs exclude test files, so today this drift is caught by IDE checking only — that mitigates but does not remove the cost.) — Failure scenario: DaemonTranscriptBlockBase gains a required field → the typed helpers fail to compile but these as-cast literals keep compiling → the fixtures that exercise this filter silently stop tracking the real block shape.

The fix spans five sites, so no one-click suggestion — build the fixtures with the existing helper, e.g. statusBlock('legacy-1', 'language_changed (unrecognized daemon event): {"language":"en"}', 1, { kind: 'debug' }), passing debugReason/source/data through overrides; or add one top-level debugBlock factory next to statusBlock and use it in all five tests.

中文说明

[建议] R3-1:这些测试新增的 5 个内联区块工厂(3 个 legacy 闭包、2 个 block 闭包,另有裸字面量)重复了本文件已有的 statusBlock 辅助函数——其 overrides: Partial<DaemonStatusTranscriptBlock> 展开已支持 { kind: 'debug', debugReason, source, data }——每个工厂都在 as DaemonTranscriptBlock 断言背后手写完整的基础结构。本次评审中经探针验证:给 DaemonTranscriptBlockBase 添加一个必填字段后,带类型的辅助函数会编译失败,而这些 as 断言的写法却没有任何诊断地继续通过编译。(两个包的 typecheck 配置都排除了测试文件,所以目前这种漂移只会在 IDE 检查中暴露——这减轻了但并未消除代价。)— 失败场景:DaemonTranscriptBlockBase 增加必填字段 → 带类型的辅助函数编译失败,但这些 as 断言的字面量继续编译通过 → 覆盖该过滤器的 fixture 悄悄脱离真实的区块结构。

修复涉及 5 处,无法一键 suggestion——请用现有辅助函数构造 fixture,例如 statusBlock('legacy-1', 'language_changed (unrecognized daemon event): {"language":"en"}', 1, { kind: 'debug' }),通过 overrides 传入 debugReason/source/data;或在 statusBlock 旁新增一个顶层 debugBlock 工厂并在这 5 个测试中统一使用。

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

Comment on lines +851 to +853
// `getSessionUpdatePayload` accepts any record, so `kind` is
// `undefined` for a payload whose discriminator is missing, empty or
// not a string. That is a broken frame, not a kind from a newer

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-2: This comment says kind is undefined for a payload whose discriminator is "missing, empty or not a string", but getString returns '' for an empty string — only a missing or non-string discriminator yields undefined. Runtime classification is correct in every case (''?.trim() is falsy → malformed_payload, pinned by the { sessionUpdate: '' } test); only the explanation is wrong. — Failure scenario: a maintainer tracing a malformed block whose projected text starts with ": {…}" (the ${kind ?? 'session_update'} fallback does NOT fire because '' is not nullish) is told here that kind should be undefined there, and the rationale paragraph built on that mechanism misleads the diagnosis.

Suggested fix: reword to "…so kind is undefined when the discriminator is missing or not a string, and '' when it is empty. Either way the frame is broken…" — the trim() sentence that follows already covers the whitespace-only case correctly.

中文说明

[建议] R3-2:该注释称当 payload 的判别字段「缺失、为空或不是字符串」时 kindundefined,但 getString 对空字符串返回的是 ''——只有缺失或非字符串的判别字段才会得到 undefined。运行时分类在所有情况下都是正确的(''?.trim() 为假 → malformed_payload{ sessionUpdate: '' } 测试已固定该行为);只有解释文字是错的。— 失败场景:维护者追查一个投影文本以 ": {…}" 开头的 malformed 区块时(由于 '' 不是 nullish,${kind ?? 'session_update'} 兜底不会触发),会被这段注释告知此处 kind 应为 undefined,而基于该机制构建的理由段落会把诊断引偏。

建议修复:改写为「……因此当判别字段缺失或不是字符串时 kindundefined,为空时则为 ''。无论哪种情况帧都是坏的……」——后面的 trim() 一句已经正确覆盖了纯空白的情形。

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

Comment on lines 1195 to 1197
type: 'debug',
debugReason: 'malformed_payload',
text: `${event.type}: ${stringifyRedactedJson(event.data)}`,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-3: Four of the six malformed_payload stamping sites have no test pinning the reason: normalizeSessionUpdate's !update branch (~686), both normalizePermissionRequest malformed branches (~1150, ~1162), and normalizePermissionResolved (anchored here). Mutation-verified twice during this review: flipping all four to debugReason: 'unrecognized_event' leaves the SDK suites (304 tests) and the Web Shell adapter suite (121 tests) fully green. — Failure scenario: a future edit flips one of these reasons → Web Shell silently hides the defect-signal blocks for broken permission_request / permission_resolved / session_update envelopes → this PR's documented "malformed_payload stays visible" guarantee breaks with no test failing.

Suggested fix: extend the existing 'stamps debugReason on malformed payloads of known events' test to also cover a permission_request with non-record data and one missing requestId, a permission_resolved missing requestId, and a session_update envelope with no usable update field, each asserting debugReason: 'malformed_payload'.

中文说明

[建议] R3-3:6 个 malformed_payload 打点位置中有 4 个没有测试固定其 reason:normalizeSessionUpdate!update 分支(约 686 行)、normalizePermissionRequest 的两个 malformed 分支(约 1150、1162 行)、以及 normalizePermissionResolved(锚点所在位置)。本次评审中两次变异验证:把这 4 处全部翻转为 debugReason: 'unrecognized_event' 后,SDK 套件(304 个测试)与 Web Shell 适配器套件(121 个测试)仍然全绿。— 失败场景:未来某次改动翻转其中一处的 reason → Web Shell 悄悄隐藏损坏的 permission_request / permission_resolved / session_update 信封所产生的缺陷信号区块 → 本 PR 文档承诺的「malformed_payload 保持可见」被破坏,却没有任何测试失败。

建议修复:扩充现有的 'stamps debugReason on malformed payloads of known events' 测试,增加:data 非 record 的 permission_request、缺 requestIdpermission_request、缺 requestIdpermission_resolved、以及没有可用 update 字段的 session_update 信封,各自断言 debugReason: 'malformed_payload'

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

Comment on lines +136 to +138
* scoped to the kinds known to have leaked into transcripts before the
* normalizer suppressed them at the source: `usage_update` (#8790, the
* original spam report) and `a2ui`, whose command JSON the bridge splits out

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-5: This comment says both kinds were suppressed "at the source" by the normalizer, but that is true only for usage_update (case 'usage_update': return []). The SDK normalizer has no a2ui case at all — current daemons actively emit a2ui frames (the acp-bridge republishes them), which the default branch still projects into debug blocks tagged unrecognized_session_update, hidden only at render time by the debugReason filter above. — Failure scenario: a future maintainer reads "suppressed at the source", believes the 'a2ui: {' legacy prefix is dead weight and deletes it from LEGACY_SUPPRESSED_SESSION_UPDATE_PREFIXES as cleanup → transcripts persisted or projected by pre-debugReason SDKs re-render raw a2ui: {…} JSON spam in Web Shell — the exact regression #8790 addressed. (The deletion would fail the legacy-filter test, but this rationale block is precisely what a future reader trusts.)

Suggested fix: reword to "…usage_update, which the normalizer suppresses at the source, and a2ui, which the current normalizer still projects as an unrecognized_session_update debug block (hidden via debugReason above); this prefix covers blocks produced before debugReason existed."

中文说明

[建议] R3-5:该注释称这两种类型都被 normalizer「在源头屏蔽」,但这只对 usage_update 成立(case 'usage_update': return [])。SDK normalizer 完全没有 a2ui 分支——当前 daemon 仍在主动发出 a2ui 帧(acp-bridge 会重新发布它们),default 分支仍会将其投影为带 unrecognized_session_update 标记的 debug 区块,只是由上方的 debugReason 过滤器在渲染时隐藏。— 失败场景:未来某位维护者读到「在源头屏蔽」,认为 'a2ui: {' 这条旧版前缀是死代码而作为清理删除 → 由 debugReason 出现之前的 SDK 持久化或投影的 transcript 会重新在 Web Shell 中渲染出原始 a2ui: {…} JSON 刷屏——正是 #8790 处理过的那个回归。(删除会导致 legacy 过滤测试失败,但这段理由说明恰恰是未来读者会信任的内容。)

建议修复:改写为「……usage_update——normalizer 已在源头屏蔽;以及 a2ui——当前 normalizer 仍会将其投影为 unrecognized_session_update debug 区块(由上方 debugReason 隐藏);此前缀用于覆盖 debugReason 存在之前产生的区块。」

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

Comment on lines 159 to 161
DaemonUiAuthDeviceFlowThrottledEvent,
DaemonUiDebugReason,
DaemonUiErrorEvent,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-6 (1 of 2): The new DaemonUiDebugReason type re-export here is ungated by any runtime test — test-efficacy probe (harness validated): reverting this hunk alone leaves every test green, because the only test reference is import type + expectTypeOf() in daemon-public-surface.test.ts, which vitest transpiles away without type-checking. The sibling value export DAEMON_UI_DEBUG_REASONS IS runtime-pinned by that test (its hunks were killed by the probe); the type-only export is not. — Failure scenario: a future barrel reshuffle drops this re-export → the whole runtime suite stays green → SDK consumers doing import type { DaemonUiDebugReason } from this entry break at compile time only after release, caught only if a typecheck runs over the consumer.

Suggested fix: accept the workspace typecheck as the gate for type-only exports (it covers them today), or note in daemon-public-surface.test.ts that the expectTypeOf half is enforced by npm run typecheck, not by the suite, so a future editor does not assume the test pins both halves.

中文说明

[建议] R3-6(共 2 处,第 1 处):此处新增的 DaemonUiDebugReason 类型再导出没有任何运行时测试把关——测试效力探针(harness 已验证)显示:单独回退这个 hunk 后所有测试仍为绿色,因为唯一的测试引用是 daemon-public-surface.test.ts 里的 import type + expectTypeOf(),vitest 转译时会将其擦除而不做类型检查。同层的值导出 DAEMON_UI_DEBUG_REASONS 被该测试在运行时固定(其 hunk 被探针杀死);类型导出则没有。— 失败场景:未来某次 barrel 重组删掉了这个再导出 → 整个运行时套件仍然全绿 → 通过该入口 import type { DaemonUiDebugReason } 的 SDK 使用者只在发布后才会在编译期报错,且只有对使用方运行 typecheck 才能发现。

建议修复:接受 workspace 的 typecheck 作为类型导出的把关(目前确实覆盖),或在 daemon-public-surface.test.ts 中注明 expectTypeOf 那一半由 npm run typecheck 而非测试套件强制执行,避免未来的编辑者误以为测试同时固定了两半。

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

Comment on lines 85 to 87
DaemonUiAssistantDoneEvent,
DaemonUiDebugReason,
DaemonUiErrorEvent,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R3-6 (2 of 2): Same gap on this barrel: the DaemonUiDebugReason type re-export is ungated by any runtime test — reverting this hunk alone left every test green in the test-efficacy probe (harness validated), since the only reference is import type + expectTypeOf(), which vitest never type-checks. — Failure scenario: a future barrel reshuffle drops this re-export → the whole runtime suite stays green → SDK consumers doing import type { DaemonUiDebugReason } from @qwen-code/sdk/daemon/ui break at compile time only after release.

Suggested fix: same as the daemon/index.ts comment — accept the workspace typecheck as the gate, or document in the surface test that its expectTypeOf half is enforced by npm run typecheck, not by the suite.

中文说明

[建议] R3-6(共 2 处,第 2 处):这个 barrel 上存在同样的缺口:DaemonUiDebugReason 类型再导出没有任何运行时测试把关——测试效力探针(harness 已验证)中单独回退这个 hunk 后所有测试仍为绿色,因为唯一引用是 import type + expectTypeOf(),vitest 从不做类型检查。— 失败场景:未来某次 barrel 重组删掉这个再导出 → 整个运行时套件仍然全绿 → 通过 @qwen-code/sdk/daemon/uiimport type { DaemonUiDebugReason } 的 SDK 使用者只在发布后才会在编译期报错。

建议修复:与 daemon/index.ts 上的评论相同——接受 workspace 的 typecheck 作为把关,或在 surface 测试中注明其 expectTypeOf 那一半由 npm run typecheck 而非测试套件强制执行。

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

@ytahdn

ytahdn commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Review 总结

结论:LGTM。 用结构化 debugReason 分类替代逐类型字符串屏蔽,是根因修复而非第四个症状补丁。已逐项核对:

SDK 侧(sdk-typescript)

  • normalizer 全部 7 处 debug 产生点均已打上 reason(对照 PR 分支源码逐一确认,无遗漏);
  • 分类准确且保守:session_update 判别符缺失/空白归为 malformed_payload 而非 unrecognized(有注释说明,避免把真缺陷信号藏进"未知帧"类别),trim() 约定与 getFirstString 一致;
  • debugReason 经 reducer 镜像到 transcript block;字段可选、类型导出完整(含 DAEMON_UI_DEBUG_REASONS),忽略它的旧消费者行为不变,向后兼容。

Web Shell 侧

  • 过滤按 unrecognized_ 类别前缀匹配而非枚举逐值比对——新 SDK 增加的 reason 自动被覆盖,无需再改 Web Shell;
  • legacy shim 设计克制且安全:锚定整体的正则 ^[A-Za-z0-9_.-]+ \(unrecognized daemon event\): 、闭合的 kind 前缀列表(usage_update: { / a2ui: {)、仅作用于 debug 块——只引用了标记文本的块、status 块、散文式内容都不会被误吞;正则字符集不匹配的极端情况是"旧块仍然渲染",fail-safe;
  • malformed_payload 与客户端派发的 debug(如 model-switch summary,无 reason)保持可见,符合设计意图;
  • MessageList.tsx 的简化是安全的mid_turn_message_injected 的文本前缀分支之所以能删,是因为这类 unrecognized 块要么在适配器被 isUnrecognizedDaemonDebug 提前拦截(debugReason 或 legacy 正则都能命中),要么带 source 字段走保留路径;且确认 transcriptBlocksToDaemonMessages(经 useMessages)是 Web Shell 唯一的 transcript→message 路径。

测试与验证

  • normalizer 6 个新用例(三种 reason、判别符边界、reducer 透传、客户端派发无 reason)+ 适配器 9 个新用例(新旧两种匹配路径、malformed/client-dispatched 保留、各类负例)与声明的覆盖一一对应;
  • CI 全绿:Test (ubuntu-latest, Node 22.x)、web-shell E2E smoke、visual capture、Desktop Shell(ubuntu/windows);
  • PR 附带真实 daemon + Web Shell 的前后截图,且验证构建故意不含 case 'a2ui',证明的是分类修复本身。

文档(daemon-ui README 的 debug reason categorization 一节)同步到位。无阻塞问题。

@ytahdn ytahdn 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 — structured debugReason classification replaces per-kind string suppression; all 7 normalizer debug sites stamped, legacy shape-shim anchored and fail-safe, malformed/client-dispatched debug kept visible, MessageList simplification backed by the upstream adapter filter. CI green, thorough tests.

@ytahdn
ytahdn added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit b314d01 Aug 10, 2026
151 of 152 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.9.

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

Labels

autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants