Skip to content

fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping - #6433

Closed
DennisYu07 wants to merge 13 commits into
mainfrom
fix/auth-url-osc8-hyperlink
Closed

fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping#6433
DennisYu07 wants to merge 13 commits into
mainfrom
fix/auth-url-osc8-hyperlink

Conversation

@DennisYu07

Copy link
Copy Markdown
Collaborator

What this PR does

When the Qwen OAuth device flow falls back to the non-interactive message (e.g., --no-browser mode or non-TUI contexts), the authentication URL was hard-wrapped at character boundaries to fit a fixed-width ASCII box. This broke the URL across multiple lines, making it impossible to click or copy-paste as a single link — especially over SSH.

This PR adds OSC 8 terminal hyperlink support to the fallback auth URL display. When the terminal supports OSC 8 (iTerm2, WezTerm, Kitty, VS Code, Windows Terminal, GNOME Terminal/VTE, Alacritty, JetBrains, etc.), the URL is emitted as a single clickable hyperlink that survives line wrapping. Terminals without OSC 8 support get the existing ASCII box with hard-wrapping as a fallback.

Why it's needed

User problem: Over SSH (common for remote development), the fallback auth message wraps the URL across 3-4 lines. Users must manually reassemble the URL, which is error-prone — a truncated URL fails silently.

Current workaround: Users are told to "copy the COMPLETE URL" but have no reliable way to do so when it's split across lines.

Who benefits: All users running Qwen Code over SSH or in non-TUI contexts (CI, headless servers) with a modern terminal.

Reviewer Test Plan

How to verify

  1. Run qwen --no-browser (or any command that triggers OAuth in non-interactive mode) in a terminal that supports OSC 8 (e.g., iTerm2, VS Code integrated terminal)
  2. The auth URL should appear as a single clickable link — clicking it opens the browser
  3. Run the same in a basic terminal or pipe to a file (qwen --no-browser 2>err.txt) — the URL should appear in the ASCII box with hard-wrapping (no escape sequences in the file)

Run tests:

cd packages/core && npx vitest run src/qwen/qwenOAuth2.test.ts

All 95 tests should pass, including 10 new OSC 8 tests.

Evidence (Before & After)

N/A — terminal rendering behavior, not capturable in screenshots

Tested on

OS Status
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

Environment (optional)

Local dev environment, Node.js 22, vitest

Risk & Scope

  • Main risk or tradeoff: OSC 8 escape sequences are emitted to stderr — this is safe because the fallback path is only reached in non-interactive/non-browser mode, and the detection logic refuses to emit escapes for non-TTY, CI, tmux (without FORCE_HYPERLINK), and terminals known to break on OSC 8.
  • Not validated / out of scope: The MCP OAuth path (oauth-provider.ts) already has its own OSC 8 handling via the OAUTH_AUTH_URL_EVENT event for UI consumers. This PR only fixes the Qwen OAuth device flow fallback.
  • Breaking changes: None — showFallbackMessage is newly exported but was previously private. The OSC 8 detection is additive (falls back to existing behavior when not supported).

Linked Issues

Fixes #6428

中文说明

此 PR 做了什么

当 Qwen OAuth 设备流回退到非交互模式消息时(如 --no-browser 或非 TUI 上下文),认证 URL 被按字符边界硬换行以适应固定宽度的 ASCII 框。这导致 URL 被拆成多行,无法作为单个链接点击或复制粘贴——在 SSH 上尤其严重。

此 PR 为回退认证 URL 显示添加了 OSC 8 终端超链接支持。当终端支持 OSC 8(iTerm2、WezTerm、Kitty、VS Code、Windows Terminal、GNOME Terminal/VTE、Alacritty、JetBrains 等)时,URL 作为单个可点击超链接输出。不支持的终端保持现有的 ASCII 框硬换行作为回退。

为什么需要

在 SSH 上(远程开发常见),回退认证消息将 URL 拆成 3-4 行。用户必须手动拼接 URL,容易出错——截断的 URL 会静默失败。

审阅者测试计划

如何验证

  1. 在支持 OSC 8 的终端(如 iTerm2、VS Code 集成终端)运行 qwen --no-browser
  2. 认证 URL 应显示为单个可点击链接——点击打开浏览器
  3. 在基本终端或管道到文件运行——URL 应出现在 ASCII 框中(文件中无转义序列)

运行测试:

cd packages/core && npx vitest run src/qwen/qwenOAuth2.test.ts

所有 95 个测试应通过,包括 10 个新的 OSC 8 测试。

证据(修改前 & 修改后)

N/A — 终端渲染行为,无法截图

测试环境

OS Status
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

环境(可选)

本地开发环境,Node.js 22,vitest

风险 & 范围

  • 主要风险或权衡:OSC 8 转义序列输出到 stderr——这是安全的,因为回退路径只在非交互/非浏览器模式下触发,且检测逻辑拒绝为非 TTY、CI、tmux(未设 FORCE_HYPERLINK)和已知会在 OSC 8 上崩溃的终端发出转义。
  • 未验证 / 超出范围:MCP OAuth 路径(oauth-provider.ts)已通过 OAUTH_AUTH_URL_EVENT 事件有自己的 OSC 8 处理。此 PR 仅修复 Qwen OAuth 设备流回退。
  • 破坏性变更:无——showFallbackMessage 是新导出的,但之前是私有的。OSC 8 检测是附加的(不支持时回退到现有行为)。

关联 Issue

Fixes #6428

When the Qwen OAuth device flow falls back to the non-interactive
message (--no-browser or non-TUI contexts), the auth URL was hard-wrapped
at character boundaries to fit a fixed-width ASCII box. This broke the
URL across multiple lines, making it impossible to click or copy-paste
as a single link — especially over SSH.

Add supportsOsc8Hyperlinks() to detect terminal OSC 8 support (iTerm2,
WezTerm, Kitty, VS Code, Windows Terminal, VTE, Alacritty, etc.) and
osc8Hyperlink() to wrap URLs in OSC 8 escape sequences. When supported,
the URL is emitted as a single clickable hyperlink; otherwise the
existing ASCII box with hard-wrapping is preserved as a fallback.

Fixes #6428

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@DennisYu07 DennisYu07 added priority/P3 Low - Minor, cosmetic, nice-to-fix issues type/feature-request New feature or enhancement request category/authentication Authentication and authorization scope/oauth OAuth authentication flows labels Jul 7, 2026
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR! (Re-run after fix commit f8a74c5)

Template looks good ✓

Problem: This is an observed, well-documented problem. Issue #6428 describes the real pain of URL wrapping over SSH, and Claude Code shipped an equivalent fix in v2.1.202. The problem is legitimate.

Direction: Aligned. OSC 8 hyperlinks for auth URLs in non-interactive mode is a clear UX win for SSH/headless users. The scope (Qwen OAuth device flow fallback only, not MCP OAuth) is correct.

Size: 76 production additions + 6 deletions (82 lines in qwenOAuth2.ts), 197 test additions (qwenOAuth2.test.ts). Well under thresholds.

Approach: The scope is tight — two functions + a conditional branch in showFallbackMessage. The code reuse concern from the prior review stands: the codebase already has a mature OSC 8 infrastructure in packages/cli/src/ui/utils/osc8.ts with version-gated detection, sanitizeForOsc() with bidi-control stripping, and wrapForMultiplexer() for DCS passthrough. This PR duplicates a simplified subset inline in packages/core. The detection gaps (no NO_COLOR/FORCE_COLOR respect, no mintty version gating, no Konsole detection, no DCS passthrough for tmux FORCE_HYPERLINK) are still present but are acceptable for this narrow use case — the URL is system-generated (low spoofing risk), and the common terminals are covered. Extraction to a shared location remains a good follow-up.

Moving on to code review. 🔍

中文说明

感谢贡献!(修复提交 f8a74c5 后重新运行)

模板完整 ✓

问题:已观测到的、有文档记录的真实问题。Issue #6428 描述了 SSH 下 URL 换行的痛点,Claude Code v2.1.202 也做了同等修复。

方向:对齐。为非交互模式的认证 URL 添加 OSC 8 超链接,对 SSH/headless 用户是明确的 UX 提升。

规模:76 行生产代码新增 + 6 行删除,197 行测试新增。远低于阈值。

方案:范围紧凑。上次评审提出的代码复用问题仍在——packages/cli/src/ui/utils/osc8.ts 有更完善的检测、消毒和多路复用器包装。此 PR 在 packages/core 中重复了一个简化子集。检测和消毒差距对此窄场景可接受(URL 为系统生成,欺骗风险低),提取到共享位置仍是好的后续改进。

进入代码审查 🔍

Qwen Code · qwen3.7-max

@DennisYu07
DennisYu07 marked this pull request as draft July 7, 2026 07:35
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.08% 83.08% 89.13% 82.36%
Core 87.13% 87.13% 88.71% 85.96%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.08 |    82.36 |   89.13 |   83.08 |                   
 src               |   84.12 |    80.67 |   88.88 |   84.12 |                   
  cli.ts           |   94.54 |    84.07 |     100 |   94.54 | ...86-487,497-498 
  gemini.tsx       |   73.89 |    76.49 |    82.6 |   73.89 | ...1183-1187,1308 
  ...ractiveCli.ts |   85.02 |    80.82 |   86.84 |   85.02 | ...2363,2369,2421 
  ...liCommands.ts |   88.34 |     83.6 |      90 |   88.34 | ...63,480,514,635 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   68.37 |    71.09 |   88.97 |   68.37 |                   
  acpAgent.ts      |   67.99 |    70.91 |   88.98 |   67.99 | ...31,10736-10738 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.04 |    95.71 |   93.33 |   97.04 |                   
  filesystem.ts    |   97.04 |    95.71 |   93.33 |   97.04 | ...21-122,238-239 
 ...ration/session |   91.65 |    85.67 |   95.97 |   91.65 |                   
  Session.ts       |   91.23 |    84.45 |   95.23 |   91.23 | ...8482,8509-8513 
  ...entTracker.ts |   91.87 |    89.18 |   88.88 |   91.87 | ...33,197,280-289 
  ...stop-guard.ts |     100 |    97.08 |     100 |     100 | 37,127,247        
  ...eplay-page.ts |   92.27 |    88.09 |     100 |   92.27 | ...83,108-118,121 
  ...y-replayer.ts |    98.5 |    95.38 |     100 |    98.5 | 229-231           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    86.76 |     100 |   89.76 | ...54-270,326-328 
  tasksSnapshot.ts |   94.26 |     87.5 |     100 |   94.26 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.68 |     93.7 |   96.66 |   95.68 |                   
  ...ageEmitter.ts |   95.34 |    94.11 |     100 |   95.34 | 52-59             
  PlanEmitter.ts   |     100 |    83.33 |     100 |     100 | 59                
  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.17 |    97.43 |     100 |   99.17 | 352-353           
 ...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/commands      |   88.97 |    73.18 |   64.51 |   88.97 |                   
  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        |   97.87 |      100 |      50 |   97.87 | 58                
  serve.ts         |   86.85 |     67.3 |     100 |   86.85 | ...32-635,649-653 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   86.92 |    87.05 |   90.44 |   86.92 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   79.66 |    84.61 |      80 |   79.66 | 36-39,48-51,62-65 
  ...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 |    94.2 |    85.09 |   97.82 |    94.2 | ...1155,1162-1163 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.49 |    96.51 |     100 |   98.49 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |   72.85 |      100 |      50 |   72.85 | 22-28,57-68       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   81.42 |    87.71 |     100 |   81.42 | ...70-174,234-236 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |   75.05 |    73.17 |   76.92 |   75.05 | ...31,537-540,552 
  ...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.82 |   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 |     90.9 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |      75 |    55.55 |     100 |      75 | ...27-131,133-137 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.17 |    84.39 |   83.33 |   90.17 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   92.59 |    83.87 |      80 |   92.59 | ...62-164,180-181 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   84.32 |     86.8 |   83.89 |   84.32 |                   
  agent-prompt.ts  |   90.88 |    92.78 |      96 |   90.88 | ...1259,1729-1798 
  capture-local.ts |   68.26 |    83.33 |      75 |   68.26 | 106-110,157-188   
  ...k-coverage.ts |   48.38 |    14.28 |   66.66 |   48.38 | ...21-226,239-249 
  cleanup.ts       |   87.36 |    82.35 |   83.33 |   87.36 | ...77-482,484-485 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   95.26 |    93.03 |    92.3 |   95.26 | ...1175,1203-1225 
  fetch-pr.ts      |   73.92 |    51.72 |      50 |   73.92 | ...97,331,401-406 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  parse-args.ts    |   99.25 |       96 |     100 |   99.25 | 341,413           
  plan-diff.ts     |   63.63 |      100 |   66.66 |   63.63 | 126-162           
  pr-context.ts    |   84.44 |    79.38 |   91.66 |   84.44 | ...29-910,939-941 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  submit.ts        |   76.74 |    82.05 |   81.81 |   76.74 | ...03-639,641-642 
  test-efficacy.ts |   80.68 |    69.41 |    92.3 |   80.68 | ...93-594,602-622 
 ...nds/review/lib |    95.6 |    92.94 |   94.89 |    95.6 |                   
  agent-briefs.ts  |   98.68 |      100 |       0 |   98.68 | 520-521           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  coverage.ts      |   95.47 |    94.25 |   95.45 |   95.47 | ...98,335,433-450 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  gh.ts            |    85.6 |    88.37 |   71.42 |    85.6 | ...20,257-258,285 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |    92.3 |    83.33 |   83.33 |    92.3 | 76-77             
  prompt-record.ts |   94.73 |    88.23 |     100 |   94.73 | ...28,151-152,156 
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  report.ts        |   94.38 |    93.75 |     100 |   94.38 | 173-177           
  roster.ts        |     100 |    93.02 |     100 |     100 | 114,128,173       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.27 |    93.18 |     100 |   96.27 | ...83,269-270,294 
  workspaces.ts    |   97.76 |     91.3 |     100 |   97.76 | 186-187,212-213   
 ...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.16 |    88.67 |    95.9 |   94.16 |                   
  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.28 |    88.14 |   84.84 |   88.28 | ...2365,2367-2375 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.04 |    88.28 |     100 |   83.04 | ...39,253,352-353 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   94.33 |    89.61 |   94.73 |   94.33 | ...35-639,655-656 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.74 |     100 |     100 | 47,160,220        
  keyBindings.ts   |   97.38 |       50 |     100 |   97.38 | 234-237           
  ...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.65 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   90.74 |    92.02 |   89.65 |   90.74 | ...72,974,976-977 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   93.35 |    94.11 |     100 |   93.35 | ...90-391,427-438 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |      80 |    76.31 |   81.35 |      80 |                   
  session.ts       |   84.08 |    75.27 |   93.61 |   84.08 | ...1007,1016-1026 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...24-625,628-629 
 ...active/control |   76.11 |    89.09 |      80 |   76.11 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.79 |    92.45 |   88.88 |   91.79 | ...49-367,387,390 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |   39.78 |    63.24 |   47.22 |   39.78 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   49.11 |    62.96 |   54.54 |   49.11 | ...63-568,570-575 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.14 |     94.4 |   95.23 |   98.14 |                   
  ...putAdapter.ts |   98.09 |    93.65 |   98.07 |   98.09 | ...1319,1422-1423 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 84-85,125-126     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |   87.47 |    83.46 |      91 |   87.47 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |    93.4 |    92.95 |     100 |    93.4 | ...19-320,323-325 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    97.87 |     100 |     100 | 628               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  ...nt-service.ts |   93.65 |    86.02 |     100 |   93.65 | ...52-454,461,463 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   85.85 |    91.78 |   95.83 |   85.85 | ...94-206,366-369 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   91.42 |    86.72 |     100 |   91.42 | ...26,732-736,748 
  ...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 |   96.49 |    86.37 |   96.72 |   96.49 | ...1253,1307-1311 
  ...e-grouping.ts |     100 |    94.11 |     100 |     100 | 69,132            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |   92.04 |    77.77 |     100 |   92.04 | ...36-445,470,508 
  daemon-logger.ts |    82.2 |    77.26 |   91.76 |    82.2 | ...1720,1747-1753 
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.37 |    90.06 |     100 |   98.37 | ...1041,1043-1044 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |    91.3 |       80 |     100 |    91.3 | ...24-127,205-212 
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.41 |    88.75 |     100 |   94.41 | ...24,702,718,728 
  fast-path.ts     |   90.33 |    80.23 |   95.45 |   90.33 | ...83-492,558-559 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...27-128,139-140 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   82.37 |    79.09 |   73.76 |   82.37 | ...6603,6608-6609 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   95.04 |    87.62 |     100 |   95.04 | ...07,511-512,552 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   93.93 |    93.52 |      75 |   93.93 | ...2044,2065-2069 
  ...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 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.34 |    76.57 |     100 |   93.34 | ...17,820,833-835 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |    86.66 |     100 |   91.07 | ...79-182,216-219 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...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 | ...17-518,524-525 
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...e-remember.ts |   98.14 |    88.92 |     100 |   98.14 | ...31,335-340,381 
  ...te-runtime.ts |   82.62 |    88.88 |     100 |   82.62 | ...48-156,216-237 
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
  ...lls-status.ts |     100 |    92.85 |     100 |     100 | 127               
  ...reconciler.ts |    91.6 |     83.9 |     100 |    91.6 | ...70-272,305-306 
 ...serve/acp-http |    76.7 |    77.99 |   93.04 |    76.7 |                   
  ...r-registry.ts |     100 |    95.45 |     100 |     100 | 191               
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |    98.2 |    88.62 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   71.11 |    73.69 |   95.23 |   71.11 | ...4685,4733-4739 
  index.ts         |   81.78 |    79.64 |   90.56 |   81.78 | ...2273,2343-2344 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |   85.64 |    78.41 |     100 |   85.64 |                   
  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.6 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.32 |    89.18 |     100 |   90.32 | 142-150           
  ...ile-system.ts |   85.14 |    76.25 |     100 |   85.14 | ...2073,2083-2084 
 src/serve/routes  |   86.13 |    79.88 |   95.52 |   86.13 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   85.22 |       88 |     100 |   85.22 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.45 |    83.33 |     100 |   85.45 | 98-105            
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   94.73 |     86.2 |     100 |   94.73 | 62-66,154         
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   86.78 |     81.9 |   95.65 |   86.78 | ...1195,1238-1239 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   86.27 |    81.47 |      95 |   86.27 | ...4295,4297-4298 
  sse-events.ts    |   84.45 |     87.5 |   77.77 |   84.45 | ...36,453-456,485 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   89.29 |    75.72 |     100 |   89.29 | ...91-392,411-412 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.41 |    78.89 |      90 |   83.41 | ...1024,1030,1033 
  ...extensions.ts |    87.2 |    72.76 |   94.11 |    87.2 | ...1822,1867-1868 
  ...-file-read.ts |   92.34 |    80.31 |     100 |   92.34 | ...96-597,600-601 
  ...file-write.ts |   84.44 |    64.51 |     100 |   84.44 | ...73-275,355-357 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    92.68 |     100 |     100 | 52,77,183         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |      97 |    91.66 |     100 |      97 | 133-135           
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...management.ts |   87.81 |    85.11 |     100 |   87.81 | ...1491,1511-1516 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   74.81 |    70.31 |     100 |   74.81 | ...47-658,664-665 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |   69.87 |    78.12 |     100 |   69.87 | ...59-284,290-324 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.42 |    64.78 |      80 |   78.42 | ...31-336,344-345 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   90.77 |     89.5 |   95.27 |   90.77 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |   85.45 |    76.57 |     100 |   85.45 | ...93,710,773-782 
  fs-factory.ts    |     100 |    92.72 |     100 |     100 | 34,42,103,159     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.11 |    95.14 |     100 |   95.11 | ...65-167,422-427 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   94.81 |    90.32 |     100 |   94.81 | 175-181           
  ...on-archive.ts |   89.61 |    90.56 |   88.23 |   89.61 | ...36-441,513-523 
  ...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.01 |    97.43 |     100 |   99.01 | ...13,627,769-771 
 src/serve/voice   |   83.35 |    92.22 |   90.47 |   83.35 |                   
  ...ice-config.ts |   84.61 |       30 |     100 |   84.61 | 90-99,103-104     
  voice-ws.ts      |   77.16 |    94.73 |   83.33 |   77.16 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |    89.4 |    85.59 |      90 |    89.4 |                   
  index.ts         |   88.94 |    85.16 |   88.57 |   88.94 | ...1211-1215,1218 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.17 |    88.31 |   97.82 |   92.17 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 104-117           
  ...killLoader.ts |   97.14 |    87.87 |     100 |   97.14 | 140,151-152       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   77.36 |    85.52 |   83.33 |   77.36 | ...43,168,210-211 
  ...mandLoader.ts |   97.36 |    92.68 |     100 |   97.36 | 153,160-161       
  ...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 |    93.75 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.29 |    86.11 |     100 |   88.29 | ...91-196,229-230 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.54 |    90.47 |    87.5 |   93.54 | 201-203,217-223   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.83 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   90.37 |    87.87 |     100 |   90.37 | ...80,287,352-357 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   90.46 |    82.19 |      96 |   90.46 | ...66-668,671-673 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |    86.29 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.24 |   94.73 |   88.28 | ...1352,1356-1363 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.04 |    83.33 |      80 |   94.04 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   71.09 |    72.95 |   66.66 |   71.09 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   72.22 |    69.85 |   66.66 |   72.22 | ...4022,4026-4030 
  ...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.22 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   62.73 |    47.22 |   66.66 |   62.73 | ...95-296,313-318 
  ...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   |    81.4 |    82.93 |    89.4 |    81.4 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |   92.46 |    83.63 |     100 |   92.46 | ...4-69,94-99,178 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   68.28 |    70.14 |   84.61 |   68.28 | ...66-599,610-611 
  copyCommand.ts   |   98.46 |    95.73 |     100 |   98.46 | ...72,272,313,319 
  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   |   91.13 |    83.72 |      90 |   91.13 | ...81-184,196-199 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   93.45 |    89.06 |     100 |   93.45 | ...68-169,196-206 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.27 |    83.01 |     100 |   86.27 | ...22-935,969-974 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   89.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.43 |      100 |      50 |    6.43 | 31-330            
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |   70.53 |    78.06 |   76.29 |   70.53 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   97.29 |     87.5 |   66.66 |   97.29 | 49                
  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 |   86.55 |    87.67 |     100 |   86.55 | ...00-302,353-357 
  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-597             
  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       |   75.11 |     61.4 |      50 |   75.11 | ...48-253,271-275 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   83.33 |    76.92 |     100 |   83.33 | 24-30             
  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 |   78.45 |    64.28 |     100 |   78.45 | ...98,501,504-510 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   82.49 |    80.33 |      80 |   82.49 | ...2178,2204,2278 
  ...Shortcuts.tsx |   20.65 |      100 |       0 |   20.65 | ...7,50-52,68-126 
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.82 |    92.53 |      50 |   95.82 | ...97,440-444,447 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   83.41 |    71.65 |     100 |   83.41 | ...69,971,976-992 
  ...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 |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   92.97 |    83.87 |     100 |   92.97 | ...43,246,273-275 
  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             
  ...criptView.tsx |   98.27 |    84.21 |     100 |   98.27 | 45,53             
  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 |   53.72 |    70.87 |   42.85 |   53.72 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   64.78 |    29.41 |   33.33 |   64.78 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |    82.2 |    81.36 |    90.9 |    82.2 |                   
  ...sksDialog.tsx |   77.53 |     76.9 |   80.76 |   77.53 | ...1781,1803-1809 
  ...TasksPill.tsx |   67.03 |     86.2 |     100 |   67.03 | ...02-122,130-138 
  ...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.14 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.28 |   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 |   86.99 |    81.37 |   91.89 |   86.99 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.04 |    61.53 |   70.58 |   40.04 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   89.95 |    86.14 |      87 |   89.95 |                   
  ...ionDialog.tsx |   89.23 |    84.27 |   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 |   96.71 |    97.77 |   91.66 |   96.71 | 223-233           
  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 |   76.52 |     42.1 |   66.66 |   76.52 | ...00,102,125,156 
  ...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 |   89.75 |     79.1 |     100 |   89.75 | ...33-635,642-644 
  ...upMessage.tsx |   98.32 |    95.16 |     100 |   98.32 | 184-187,414       
  ToolMessage.tsx  |   92.43 |    84.84 |   93.33 |   92.43 | ...56-961,988-990 
 ...ponents/shared |   85.73 |    82.03 |   94.05 |   85.73 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.86 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   88.51 |    85.11 |   81.81 |   88.51 | ...51-779,792,887 
  text-buffer.ts   |   85.94 |    81.67 |   97.91 |   85.94 | ...2651,2749-2750 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   69.81 |    72.64 |   61.11 |   69.81 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   83.59 |    81.27 |   86.11 |   83.59 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   92.45 |    62.79 |      50 |   92.45 | ...69-270,272-276 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |    85.1 |    84.53 |     100 |    85.1 | ...1583-1585,1591 
  ...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 | 151-152           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 234-235           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |    84.9 |    82.56 |   89.57 |    84.9 |                   
  ...dProcessor.ts |      84 |    84.12 |     100 |      84 | ...41-873,920-921 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...86-287,292-293 
  ...dProcessor.ts |   85.21 |     66.4 |   81.81 |   85.21 | ...1407,1428-1432 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      42 |       75 |     100 |      42 | 42-44,53-59,62-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.08 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.73 |    76.59 |     100 |   94.73 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   94.85 |    80.76 |     100 |   94.85 | ...54,229,292-295 
  ...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 |   78.53 |    88.57 |     100 |   78.53 | ...96-104,112-113 
  ...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.7 |     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 |   85.51 |    81.02 |   96.15 |   85.51 | ...3891,4053-4061 
  ...BranchName.ts |     100 |    91.66 |     100 |     100 | 30                
  ...oryManager.ts |   98.01 |    98.36 |     100 |   98.01 | 139-142           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |    96.77 |     100 |     100 | 75                
  ...delCommand.ts |     100 |       95 |     100 |     100 | 53                
  ...ouseEvents.ts |   94.31 |    97.43 |   83.33 |   94.31 | 76-80             
  ...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 |   91.16 |     90.9 |     100 |   91.16 | ...35-338,453-463 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...tleRepaint.ts |     100 |      100 |     100 |     100 |                   
  ...umeCommand.ts |   94.67 |    74.28 |     100 |   94.67 | ...19,174,233-238 
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   53.06 |       50 |   66.66 |   53.06 | ...53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    91.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   86.16 |    84.95 |   94.97 |   86.16 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   79.84 |     75.6 |     100 |   79.84 | ...66,270,328-329 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.38 |    81.91 |   95.23 |   92.38 | ...43-746,799-804 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   52.52 |    73.25 |   91.66 |   52.52 | ...23,626-635,638 
  commandUtils.ts  |   96.17 |    88.77 |     100 |   96.17 | ...77,179-180,323 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |    95.4 |    98.38 |     100 |    95.4 | 123-126           
  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 |    97.05 |     100 |      96 | 102-105           
  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 |   69.47 |       75 |   66.66 |   69.47 | ...24-129,157-158 
  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.59 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    73.77 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |     97.1 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   71.08 |    79.03 |   93.75 |   71.08 | ...03-525,656-657 
  ...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           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   95.97 |    93.22 |   94.44 |   95.97 | ...21-322,482-483 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   89.65 |       92 |     100 |   89.65 | ...83-184,217-218 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |    59.89 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   80.94 |    72.69 |   80.55 |   80.94 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   89.72 |    65.33 |   93.75 |   89.72 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |    68.42 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.36 |    87.02 |   92.49 |   81.36 |                   
  ...p-profiler.ts |   98.39 |    90.56 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       95 |     100 |     100 | 72                
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...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 | ...59,376-377,422 
  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 |   89.05 |    76.38 |     100 |   89.05 | ...86,302-303,340 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   74.38 |    69.56 |     100 |   74.38 | ...92-103,105-116 
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.67 |    56.93 |   76.92 |   45.67 | ...1034,1046-1069 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |     87.5 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...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.13 |    85.96 |   88.71 |   87.13 |                   
 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        |   89.98 |    83.97 |   94.02 |   89.98 |                   
  ...transcript.ts |   88.09 |    85.71 |     100 |   88.09 | ...97,605,611-615 
  ...ent-resume.ts |   84.58 |     76.2 |   78.26 |   84.58 | ...1678-1682,1685 
  ...ound-tasks.ts |   96.14 |     90.1 |   98.76 |   96.14 | ...1728,1748-1751 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.65 |    89.28 |     100 |   95.65 | ...12-413,485-489 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |    90.2 |     85.4 |   87.28 |    90.2 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   84.17 |    73.91 |   76.47 |   84.17 | ...2141,2187-2189 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    88.09 |   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.95 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.79 |    87.79 |   82.35 |   91.79 | ...1774,1823-1826 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...ow-sandbox.ts |   96.87 |    94.51 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   81.81 |    83.99 |    87.5 |   81.81 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   83.75 |    86.63 |   73.14 |   83.75 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   82.92 |    86.27 |   71.11 |   82.92 | ...7485,7489-7490 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.11 |    91.95 |      88 |   94.11 | ...25-426,429-430 
 ...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          |   91.55 |       88 |   92.79 |   91.55 |                   
  baseLlmClient.ts |   88.28 |    82.48 |   81.81 |   88.28 | ...47,660,666-668 
  client.ts        |   91.19 |    87.06 |   90.41 |   91.19 | ...3234,3330-3331 
  ...tGenerator.ts |   85.81 |     85.5 |   80.95 |   85.81 | ...25-426,471-477 
  ...lScheduler.ts |   89.71 |    86.07 |   95.83 |   89.71 | ...5353,5381-5392 
  geminiChat.ts    |   92.26 |    89.21 |   95.95 |   92.26 | ...4352,4400-4401 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |    95.83 |     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.33 |    83.33 |      50 |   93.33 | 46-47             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   95.19 |    89.47 |     100 |   95.19 | ...44-245,290-291 
  prompts.ts       |   93.57 |    91.42 |   83.33 |   93.57 | ...1187,1390-1391 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |   96.89 |    80.88 |   88.23 |   96.89 | ...10,117-118,123 
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-123        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...allIdUtils.ts |   98.41 |    93.02 |     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.49 |    91.17 |     100 |   98.49 | ...94,622-623,669 
 ...ntentGenerator |   96.18 |    87.11 |   95.38 |   96.18 |                   
  ...tGenerator.ts |   97.09 |    86.94 |   94.44 |   97.09 | ...1322,1351,1362 
  converter.ts     |   96.04 |    87.15 |     100 |   96.04 | ...,931,1086-1088 
  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.21 |    86.46 |    92.3 |   95.21 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.12 |     85.4 |   91.89 |   95.12 | ...1169-1170,1198 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.65 |    90.23 |   95.23 |   91.65 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   96.63 |    90.94 |     100 |   96.63 | ...1100,1108,1203 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.73 |    89.76 |   98.27 |   96.73 |                   
  dashscope.ts     |   97.48 |    91.91 |      95 |   97.48 | ...85-386,528-529 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   86.12 |    83.09 |   92.19 |   86.12 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   78.32 |    71.83 |     100 |   78.32 | ...1122,1168-1169 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |   80.39 |     87.5 |     100 |   80.39 | 50-59             
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.82 |    86.11 |   97.82 |   90.82 | ...1215-1221,1265 
  ...ionManager.ts |   80.59 |    78.06 |   80.23 |   80.59 | ...2577,2599-2600 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    84.61 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   88.58 |    82.13 |     100 |   88.58 | ...62,952-953,963 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    83.78 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |    80.61 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |   77.38 |    79.84 |    90.9 |   77.38 |                   
  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   |   65.26 |    62.63 |   71.42 |   65.26 | ...17-618,625-626 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 97                
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   93.15 |    86.93 |   95.91 |   93.15 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  goal-evidence.ts |   87.01 |    84.26 |   95.65 |   87.01 | ...86-587,610-613 
  ...projection.ts |   89.41 |    72.22 |   66.66 |   89.41 | ...28,131,135-137 
  ...ersistence.ts |   83.96 |       76 |      80 |   83.96 | ...0,93-94,97-106 
  goal-protocol.ts |     100 |      100 |     100 |     100 |                   
  goal-reducer.ts  |   91.24 |    81.14 |     100 |   91.24 | ...68,381,432-436 
  goal-runtime.ts  |   98.71 |    92.69 |     100 |   98.71 | ...38-639,662-663 
  goal-verifier.ts |   91.72 |    89.47 |     100 |   91.72 | ...63-166,179-181 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-27              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   87.41 |    85.73 |   88.38 |   87.41 |                   
  ...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.43 |     83.5 |   94.59 |   95.43 | ...1010-1011,1021 
  hookPlanner.ts   |    87.5 |    85.36 |   86.66 |    87.5 | ...21-225,232-243 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.48 |    72.04 |   66.66 |   62.48 | ...67-768,777-778 
  hookSystem.ts    |    87.5 |      100 |   70.21 |    87.5 | ...43-744,750-751 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  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     |   77.22 |    85.36 |     100 |   77.22 | ...57,261-267,273 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.24 |    96.12 |   88.88 |   94.24 | ...42-543,628-632 
  urlValidator.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.17 |    82.76 |   90.29 |   87.17 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.11 |    95.72 |   96.29 |   97.11 | ...85-287,361-362 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    81.81 |     100 |     100 | 126,136           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   91.48 |    75.75 |     100 |   91.48 | ...99,118-121,189 
  ...entPlanner.ts |   91.51 |    76.19 |     100 |   91.51 | ...04,113-116,290 
  ...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 |   82.27 |    77.92 |   83.33 |   82.27 | ...66,285,292-298 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   94.73 |    95.94 |     100 |   94.73 | ...35-336,357-358 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   89.85 |    82.92 |     100 |   89.85 | ...54-155,162-163 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    89.79 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   71.68 |    65.51 |   68.75 |   71.68 | ...90-394,397,403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |     79.1 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.54 |    88.91 |   91.13 |   92.54 |                   
  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,260           
  modelsConfig.ts  |   89.36 |    86.77 |   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.54 |    91.01 |   70.71 |   83.54 |                   
  autoMode.ts      |   97.64 |    93.13 |     100 |   97.64 | ...78-585,631,708 
  ...transcript.ts |      98 |    84.61 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.53 |    89.57 |      80 |   86.53 | ...1095,1201-1205 
  rule-parser.ts   |   94.14 |    91.89 |     100 |   94.14 | ...1335,1369-1371 
  ...-semantics.ts |   70.36 |    91.04 |   46.66 |   70.36 | ...2237,2300-2303 
  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.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.55 |    84.87 |   96.29 |   89.55 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.66 |    85.71 |     100 |   97.66 | ...95,118,487-488 
  ...ionService.ts |   96.71 |    95.79 |     100 |   96.71 | ...83,699,832-840 
  ...ingService.ts |   87.48 |    81.51 |   89.83 |   87.48 | ...1840,1867-1868 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.05 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.12 |    90.45 |      98 |   94.12 | ...1323,1726-1727 
  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 |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   92.22 |    86.11 |   91.66 |   92.22 | ...80-281,349-356 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.22 |    97.32 |     100 |   98.22 | ...63-664,711-712 
  ...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.27 |    91.22 |     100 |   97.27 | ...50-451,606-607 
  ...ttachments.ts |   97.74 |     90.8 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |   98.38 |    93.75 |   88.88 |   98.38 | 63-64             
  ...ipt-reader.ts |   94.49 |    89.16 |   97.95 |   94.49 | ...1038,1049-1050 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   76.81 |    73.71 |    92.1 |   76.81 | ...15-816,820-827 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.73 |     83.5 |    97.1 |   88.73 | ...2401,2471-2491 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |   84.35 |    78.37 |   97.14 |   84.35 | ...2472,2478-2483 
  ...pInhibitor.ts |   97.42 |    92.68 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    86.66 |     100 |     100 | 96-97             
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.03 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.03 |     100 |   99.41 | 244-245,677       
 ...s/visionBridge |    98.6 |    94.11 |     100 |    98.6 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.32 |    92.64 |     100 |   98.32 | ...23,647,660-661 
 src/skills        |   88.37 |    87.22 |   90.16 |   88.37 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   83.78 |    82.63 |   82.35 |   83.78 | ...1218,1225-1229 
  skill-paths.ts   |   89.65 |    86.95 |     100 |   89.65 | ...11-112,117-118 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |       98 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.63 |    88.64 |   96.55 |   87.63 |                   
  ...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.25 |    85.31 |   94.87 |   84.25 | ...1566,1643-1644 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   80.69 |    83.54 |   84.29 |   80.69 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.07 |    80.95 |     100 |   99.07 | 183,197           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |     100 |    90.47 |     100 |     100 | 49,76             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   55.35 |    71.56 |   63.46 |   55.35 | ...1350,1367-1387 
  metrics.ts       |   78.44 |    79.62 |   79.66 |   78.44 | ...1079,1082-1093 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,478-479,495 
  sdk.ts           |   79.22 |    89.18 |   63.63 |   79.22 | ...57-161,199-221 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.38 |    89.22 |   96.66 |   90.38 | ...1611,1642-1645 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   82.05 |    94.48 |   85.71 |   82.05 | ...1332,1336-1343 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   73.62 |    81.08 |   69.49 |   73.62 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   73.62 |     80.9 |   68.96 |   73.62 | ...1095,1133-1134 
 src/test-utils    |      94 |    98.24 |   78.94 |      94 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   92.57 |      100 |   75.75 |   92.57 | ...63,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   85.57 |    84.51 |   88.07 |   85.57 |                   
  ...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 |                   
  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 
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   83.21 |    86.66 |   80.95 |   83.21 | ...65-666,716-717 
  ...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.24 |    92.85 |     100 |   99.24 | 44                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   81.63 |       79 |   85.41 |   81.63 | ...3221,3223-3224 
  mcp-client.ts    |   79.83 |    85.09 |   89.47 |   79.83 | ...2233,2237-2240 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   95.43 |    93.89 |     100 |   95.43 | ...79-780,830-831 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.74 |    84.28 |   88.46 |   91.74 | ...93,606,804-809 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    90.24 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   95.65 |    88.88 |   86.66 |   95.65 | ...80,495,567-568 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |    90.9 |    86.71 |    87.5 |    90.9 | ...13-414,428-440 
  ripGrep.ts       |    95.9 |     88.4 |   94.73 |    95.9 | ...61-662,668-669 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |    81.2 |    89.74 |    62.5 |    81.2 | ...80-286,369-377 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   78.68 |    83.81 |   91.83 |   78.68 | ...4979,5042-5043 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.06 |    93.33 |   89.47 |   91.06 | ...71,475,520-542 
  ...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     |   93.92 |    83.13 |   92.85 |   93.92 | ...86-391,413-414 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.06 |    78.83 |   82.22 |   78.06 | ...37-938,946-947 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   92.74 |    91.52 |    91.3 |   92.74 | ...63-564,580-586 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.53 |    83.57 |      80 |   90.53 | ...1007,1065-1068 
  write-file.ts    |   85.66 |    85.04 |   85.71 |   85.66 | ...53-756,793-828 
 src/tools/agent   |   85.37 |    85.69 |   86.66 |   85.37 |                   
  agent.ts         |   85.22 |    85.48 |   86.17 |   85.22 | ...4155,4177-4187 
  fork-subagent.ts |   88.32 |       90 |    90.9 |   88.32 | ...05-123,200-201 
 ...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 |   87.46 |    79.41 |   85.71 |   87.46 |                   
  workflow.ts      |   87.46 |    79.41 |   85.71 |   87.46 | ...51-652,664-667 
 src/utils         |   92.63 |    89.56 |   96.76 |   92.63 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.11 |    89.28 |     100 |   91.11 | ...46-147,154-155 
  ...n-branches.ts |   95.81 |    93.95 |      95 |   95.81 | ...91-492,504-517 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.06 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   82.23 |     92.9 |    61.9 |   82.23 | ...56-372,376-382 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  fileUtils.ts     |    95.3 |    92.06 |   96.15 |    95.3 | ...1773,1798-1799 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |   81.81 |       75 |     100 |   81.81 | 15-16             
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,331-336 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  gitDiff.ts       |   95.12 |    81.03 |     100 |   95.12 | ...1073,1390-1391 
  gitDirect.ts     |   98.46 |    90.17 |     100 |   98.46 | 148,268,352       
  ...noreParser.ts |   94.59 |    92.59 |     100 |   94.59 | ...05-106,140-141 
  gitUtils.ts      |      75 |    89.47 |   83.33 |      75 | ...,78-79,103-154 
  github-prs.ts    |    99.3 |    90.62 |     100 |    99.3 | 204               
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...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 |   93.77 |    89.15 |     100 |   93.77 | ...13-319,406-407 
  ...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.61 |     100 |     100 | 206               
  pathReader.ts    |   97.77 |       90 |     100 |   97.77 | 93,121            
  paths.ts         |   93.95 |    92.79 |     100 |   93.95 | ...78-479,481-483 
  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 |   59.15 |    76.92 |     100 |   59.15 | ...5,89-90,96-101 
  ...noreParser.ts |   92.63 |    91.37 |     100 |   92.63 | ...72-173,192-193 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   97.73 |    93.24 |     100 |   97.73 | 85-86,107,262-263 
  readManyFiles.ts |   96.29 |     87.5 |     100 |   96.29 | 225,275,286-290   
  retry.ts         |   95.93 |    92.23 |     100 |   95.93 | ...33,524-525,543 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.65 |    96.96 |     100 |   97.65 | ...00,250-251,277 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   80.47 |     82.6 |    90.9 |   80.47 | ...75-380,384-387 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.61 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   94.77 |     94.2 |     100 |   94.77 | ...42,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.72 |    92.12 |     100 |   91.72 | ...36-539,615-616 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |     83.8 |     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.05 |    88.59 |     100 |   86.05 | ...2251,2258-2262 
  ...lAstParser.ts |   98.16 |    91.91 |     100 |   98.16 | ...1244-1246,1256 
  ...ContextEnv.ts |     100 |    90.47 |     100 |     100 | 46-48             
  ...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.82 |     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 |    30.76 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.11 |    96.22 |     100 |   96.11 | ...22-327,329-334 
  ...pt-records.ts |   85.78 |    83.63 |     100 |   85.78 | ...84-388,418-433 
  truncation.ts    |   90.44 |    89.09 |     100 |   90.44 | ...18-426,463-469 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.68 |    80.38 |   94.69 |   83.68 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   82.47 |    76.22 |      95 |   82.47 | ...1525,1559-1560 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Code Review

(Re-run after fix commit f8a74c5 — test beforeEach now clears CI and all relevant env vars.)

No critical correctness bugs or security holes. The core logic is sound — OSC 8 detection covers the common terminals, the fallback path is unchanged, and the test setup properly isolates each scenario. One remaining concern (not a blocker):

Missing wrapForMultiplexer: When FORCE_HYPERLINK=1 is set inside tmux, the PR emits bare OSC 8 without DCS passthrough wrapping. Confirmed via real-scenario testing (see below) — the escape bytes are present but tmux will strip or garble them without DCS wrapping. This only affects the narrow edge case of tmux + FORCE_HYPERLINK=1; tmux users without the override are correctly refused. The existing osc8Hyperlink() in packages/cli wraps with wrapForMultiplexer() for exactly this case. Not blocking — the edge case is small and users who force it likely know their setup.

Real-Scenario Testing

Tested via script(1) pseudo-TTY with cat -v to inspect escape sequences.

OSC 8 path (TERM_PROGRAM=iTerm.app, CI=, TTY)

+----------------- Qwen OAuth Device Authorization ------------------+^M
|                                                                    |^M
| Please visit the following URL in your browser to authorize:       |^M
|                                                                    |^M
| ^[]8;;https://chat.qwen.ai/device?user_code=WXYZ-1234&code=longtoken123^Ghttps://chat.qwen.ai/device?user_code=WXYZ-1234&code=longtoken123^[]8;;^G |^M
|                                                                    |^M
| Waiting for authorization to complete...                           |^M
|                                                                    |^M
+--------------------------------------------------------------------+^M

OSC 8 envelope correctly emitted: ESC]8;;URL BEL visible-URL ESC]8;; BEL. In a supporting terminal this renders as one clickable link. ✅

Fallback path (no OSC 8 terminal detected, TTY)

+----------------- Qwen OAuth Device Authorization ------------------+^M
|                                                                    |^M
| Please visit the following URL in your browser to authorize:       |^M
|                                                                    |^M
| https://chat.qwen.ai/device?user_code=WXYZ-1234&code=longtoken123  |^M
|                                                                    |^M
| Waiting for authorization to complete...                           |^M
|                                                                    |^M
+--------------------------------------------------------------------+^M

No escape sequences. URL rendered as plain text inside the ASCII box. Existing behavior preserved. ✅

tmux + FORCE_HYPERLINK=1

+----------------- Qwen OAuth Device Authorization ------------------+^M
|                                                                    |^M
| Please visit the following URL in your browser to authorize:       |^M
|                                                                    |^M
| ^[]8;;https://chat.qwen.ai/device?user_code=WXYZ-1234&code=longtoken123^Ghttps://chat.qwen.ai/device?user_code=WXYZ-1234&code=longtoken123^[]8;;^G |^M
|                                                                    |^M
| Waiting for authorization to complete...                           |^M
|                                                                    |^M
+--------------------------------------------------------------------+^M

Bare OSC 8 emitted without DCS passthrough wrapping (^[Ptmux;...^[\\]). In real tmux, this sequence won't reach the host terminal without DCS wrapping. Edge case — only triggers with explicit FORCE_HYPERLINK=1 inside tmux. ⚠️

Unit tests

 Tests  1 failed | 94 passed (95)
  • 1 failure: getQwenCachedCredentialPath — pre-existing on main, unrelated to this PR (path mismatch in CI environment)
  • All 10 OSC 8 tests pass ✅ (prior blocker fixed by f8a74c5)
中文说明

代码审查

(修复提交 f8a74c5 后重新运行——测试 beforeEach 现在清除 CI 及所有相关环境变量。)

无严重正确性 bug 或安全漏洞。核心逻辑正确。剩余一个非阻断问题:

缺少 wrapForMultiplexer 在 tmux 中设 FORCE_HYPERLINK=1 时,PR 发出裸 OSC 8 而无 DCS 透传包装。真实场景测试确认——转义字节存在但 tmux 会剥离或乱码。仅影响 tmux + FORCE_HYPERLINK=1 的窄边缘场景;不设覆盖的 tmux 用户被正确拒绝。非阻断。

真实场景测试

通过 script(1) 伪终端 + cat -v 检查转义序列。

OSC 8 路径:URL 以正确的 OSC 8 信封输出(ESC]8;;URL BEL visible-URL ESC]8;; BEL)。✅

回退路径:无转义序列,纯文本 URL。✅

tmux + FORCE_HYPERLINK=1:裸 OSC 8 无 DCS 透传包装。⚠️

单元测试:1 失败(预先存在的无关路径问题) / 94 通过。所有 10 个 OSC 8 测试通过。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

(Re-run after fix commit f8a74c5)

The prior blocker — 4 OSC 8 tests failing in CI due to the CI env var — is resolved. All 10 new tests pass. The only remaining test failure (getQwenCachedCredentialPath) is pre-existing and unrelated.

Real-scenario testing confirms the OSC 8 envelope is correctly emitted in supporting terminals and the fallback path is preserved for everyone else. The feature works as advertised, the motivation is real (URL wrapping over SSH is a genuine pain point), and the scope is tight.

The code duplication with packages/cli/src/ui/utils/osc8.ts and the missing wrapForMultiplexer for the tmux + FORCE_HYPERLINK edge case are noted but not blocking — the first is a maintenance concern better addressed as a follow-up (extracting shared OSC 8 utilities), and the second affects only users who explicitly opt into a known-unsupported configuration.

LGTM — approving. ✅

中文说明

(修复提交 f8a74c5 后重新运行)

上次阻断问题——4 个 OSC 8 测试因 CI 环境变量在 CI 中失败——已解决。所有 10 个新测试通过。唯一剩余失败为预先存在的无关测试。

真实场景测试确认 OSC 8 信封在支持终端中正确输出,回退路径为其他用户保持不变。功能如预期,动机真实(SSH 下 URL 换行是真实痛点),范围紧凑。

packages/cli 中 OSC 8 基础设施的代码重复和 tmux + FORCE_HYPERLINK 边缘场景的 wrapForMultiplexer 缺失已记录但非阻断——前者作为后续改进(提取共享 OSC 8 工具)更合适,后者仅影响显式选择进入已知不支持配置的用户。

批准。✅

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

4 of the 10 new OSC 8 tests fail in CI environments (CI=true short-circuits detection before terminal checks). The test beforeEach needs to clear CI and other hyperlink env vars. See my Stage 2 comment for details. 🙏

DennisYu07 and others added 3 commits July 7, 2026 15:55
supportsOsc8Hyperlinks() short-circuits on CI runners because the CI
env var is set, causing all OSC 8 detection tests to fail. Clear all
terminal-detection env vars in beforeEach so each test starts from a
known clean state.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@DennisYu07
DennisYu07 marked this pull request as ready for review July 7, 2026 08:33

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

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (force !== undefined) return force !== '0';
if (env['CI']) return false;
if (env['TMUX'] || env['STY']) return false;
if (env['WT_SESSION']) return true;

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] Missing NO_COLOR and FORCE_COLOR=0 checks.

The existing supportsHyperlinks() in packages/cli/src/ui/utils/osc8.ts honors both the no-color.org convention and FORCE_COLOR=0 as hard opt-outs (checked before FORCE_HYPERLINK). This implementation skips both — users with NO_COLOR=1 will still receive OSC 8 escape bytes from the OAuth fallback.

Suggested change
if (env['WT_SESSION']) return true;
if (env['QWEN_DISABLE_HYPERLINKS'] === '1') return false;
if (env['NO_COLOR'] !== undefined && env['NO_COLOR'] !== '') return false;
if (env['FORCE_COLOR'] === '0' || env['FORCE_COLOR'] === 'false') return false;
if (!process.stderr?.isTTY) return false;

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (env['KITTY_WINDOW_ID'] || env['TERM'] === 'xterm-kitty') return true;
if (env['DOMTERM']) return true;
if (env['GHOSTTY_RESOURCES_DIR'] || env['TERM'] === 'xterm-ghostty') {
return true;

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] FORCE_HYPERLINK parsing is more permissive than the existing implementation.

force !== '0' treats any non-"0" string as enabled — including "false", "no", "abc". The existing shouldForceHyperlinks() in packages/cli/src/utils/osc.ts only accepts empty strings and non-zero numeric values, matching the supports-hyperlinks npm package contract:

function shouldForceHyperlinks(value: string): boolean {
  if (value.length === 0) return true;
  const trimmed = value.trim();
  if (!/^[+-]?\d+$/.test(trimmed)) return false;
  return Number(trimmed) !== 0;
}

FORCE_HYPERLINK=false would unexpectedly enable hyperlinks here.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
switch (env['TERM_PROGRAM']) {
case 'iTerm.app':
case 'WezTerm':
case 'vscode':

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] Terminals accepted without version gating — older versions may render raw escape bytes as visible garbage.

The existing supportsHyperlinks() in osc8.ts version-gates via TERM_PROGRAM_VERSION:

  • iTerm.app: requires ≥ 3.1
  • WezTerm: requires ≥ 20200620
  • vscode: requires ≥ 1.72
  • mintty: requires ≥ 3.3 (and refuses when TERM_PROGRAM_VERSION is absent)

This implementation accepts all versions unconditionally. At minimum, mintty should require a version check — older mintty (bundled with older Git-for-Windows) is known to print escape bytes as visible garbage.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (env['VTE_VERSION']) {
const v = parseInt(env['VTE_VERSION'], 10);
if (Number.isFinite(v) && v >= 5000 && v !== 5000) return true;
}

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] v >= 5000 && v !== 5000 is logically equivalent to v > 5000. The compound condition is confusing without context.

Suggested change
}
// VTE 0.50.0 (packed as 5000) segfaults on OSC 8; accept > 0.50.0 only
if (Number.isFinite(v) && v > 5000) return true;

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
env['ALACRITTY_LOG'] !== undefined ||
env['ALACRITTY_WINDOW_ID'] !== undefined
) {
return true;

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] Alacritty detection is missing ALACRITTY_SOCKET.

The existing supportsHyperlinks() in osc8.ts checks four indicators: TERM === 'alacritty', ALACRITTY_LOG, ALACRITTY_WINDOW_ID, and ALACRITTY_SOCKET. This implementation checks only three. The test beforeEach even cleans up ALACRITTY_SOCKET, suggesting it was intended to be part of detection.

Suggested change
return true;
if (
env['TERM'] === 'alacritty' ||
env['ALACRITTY_LOG'] !== undefined ||
env['ALACRITTY_WINDOW_ID'] !== undefined ||
env['ALACRITTY_SOCKET'] !== undefined
) {
return true;
}

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
* are stripped from the URL to prevent breaking the OSC envelope.
*/
function osc8Hyperlink(url: string): string {
// eslint-disable-next-line no-control-regex

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] Two hardening gaps compared to the existing osc8Hyperlink() in packages/cli/src/ui/utils/osc8.ts:

  1. Sanitization: The regex strips C0/DEL/C1 but not Unicode bidi controls (U+200E, U+200F, U+202A–U+202E, U+2066–U+2069) or line separators (U+2028, U+2029). The existing sanitizeForOsc() strips these to prevent click-deception via RTL overrides. Low exploit risk here (URL from OAuth provider, label = target), but the existing code documents this threat explicitly.

  2. tmux DCS passthrough: supportsOsc8Hyperlinks() returns true when FORCE_HYPERLINK=1 inside tmux (line 723), but this function emits raw OSC 8 bytes without wrapForMultiplexer() DCS wrapping. tmux will swallow the sequence — the user sees nothing clickable.

Since core can't import from cli, consider inlining the DCS wrapping:

function osc8Hyperlink(url: string): string {
  const safeUrl = url.replace(
    /[\x00-\x1f\x7f\x80-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069\u2028\u2029]/g,
    '',
  );
  let seq = `\x1b]8;;${safeUrl}\x07${safeUrl}\x1b]8;;\x07`;
  if (process.env['TMUX']) {
    seq = `\x1bPtmux;${seq.replaceAll('\x1b', '\x1b\x1b')}\x1b\\`;
  }
  return seq;
}

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (useOsc8) {
process.stderr.write('| ' + osc8Hyperlink(url) + ' |\n');
} else {
for (const line of urlLines) {

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] OSC 8 branch doesn't pad the visible URL text to contentWidth, so the right | border is misaligned.

osc8Hyperlink() embeds invisible escape bytes around the visible URL. The terminal renders only the visible URL text, but the right | is placed at url.length + 4 instead of contentWidth + 4 (the box width). All other lines in the box have aligned right borders; this one won't.

Suggested change
for (const line of urlLines) {
if (useOsc8) {
const padding = ' '.repeat(Math.max(0, contentWidth - url.length));
process.stderr.write('| ' + osc8Hyperlink(url) + padding + ' |\n');
} else {

— qwen3.7-max via Qwen Code /review

iTerm.app and vscode version-gated detection requires
TERM_PROGRAM_VERSION to be set. The beforeEach cleanup
deletes it, causing supportsOsc8Hyperlinks() to return
false and the OSC 8 envelope to not be emitted.
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
* the OSC — more broadly supported than ST (ESC \\). Control characters
* are stripped from the URL to prevent breaking the OSC envelope.
*/
function osc8Hyperlink(url: string): string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] When FORCE_HYPERLINK=1 is set inside tmux, supportsOsc8Hyperlinks() returns true (the force check runs before the tmux bail-out), but this osc8Hyperlink() function emits raw \x1b]8;;...\x07 bytes without DCS passthrough wrapping.

The canonical osc8Hyperlink() in packages/cli/src/ui/utils/osc8.ts wraps every OSC 8 sequence through wrapForMultiplexer(), which adds the required DCS passthrough envelope (\x1bPtmux;<doubled-ESC-payload>\x1b\\) that tmux needs to forward escape sequences to the host terminal. Without it, tmux strips or garbles the raw sequences — the clickable link will not appear.

Note: the existing test ('respects FORCE_HYPERLINK=1 even in tmux') only asserts \x1b]8;; presence, not DCS wrapping, so this bug is invisible to the test suite.

Suggested change
function osc8Hyperlink(url: string): string {
function osc8Hyperlink(url: string): string {
// eslint-disable-next-line no-control-regex
const safeUrl = url.replace(/[\x00-\x1f\x7f\x80-\x9f]/g, '');
let seq = `\x1b]8;;${safeUrl}\x07${safeUrl}\x1b]8;;\x07`;
if (process.env['TMUX']) {
const escaped = seq.replaceAll('\x1b', '\x1b\x1b');
seq = `\x1bPtmux;${escaped}\x1b\\`;
} else if (process.env['STY']) {
seq = `\x1bP${seq}\x1b\\`;
}
return seq;
}

Or better: extract wrapForMultiplexer from packages/cli/src/utils/osc.ts into packages/core so both modules share it.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
// Write URL — as a single OSC 8 clickable hyperlink when supported,
// or hard-wrapped across lines as a fallback.
if (useOsc8) {
process.stderr.write('| ' + osc8Hyperlink(url) + ' |\n');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] Two issues in the OSC 8 rendering branch:

  1. No right-padding to contentWidth: every other line in the box uses ' '.repeat(contentWidth - line.length) to align the right | border. This line writes the OSC 8 hyperlink without padding, so the right border lands at column url.length + 4 instead of boxWidth, breaking the box visually.

  2. No length guard for long URLs: the non-OSC 8 path wraps via wrapText(url, contentWidth). The OSC 8 path writes the full URL on a single line. When url.length > contentWidth (plausible with long device codes or custom query parameters), the line overflows past the right border.

Suggested change
process.stderr.write('| ' + osc8Hyperlink(url) + ' |\n');
if (useOsc8 && url.length <= contentWidth) {
const link = osc8Hyperlink(url);
process.stderr.write('| ' + link + ' '.repeat(contentWidth - url.length) + ' |\n');
} else {
for (const line of urlLines) {
process.stderr.write(
'| ' + line + ' '.repeat(contentWidth - line.length) + ' |\n',
);
}
}

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (env['VTE_VERSION']) {
const v = parseInt(env['VTE_VERSION'], 10);
if (Number.isFinite(v) && v >= 5000 && v !== 5000) return true;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] parseInt(env['VTE_VERSION'], 10) only handles the packed-integer format (e.g., "7800" for VTE 0.78.0). It silently rejects dot-separated version strings like "0.60.0"parseInt("0.60.0", 10) returns 0, and 0 >= 5000 is false, so OSC 8 is incorrectly refused.

The canonical supportsHyperlinks() in osc8.ts uses parseVersion() which handles both formats via a ^\d{3,4}$ heuristic — if the string is 3-4 digits it parses as packed, otherwise it splits on ..

The VTE 0.50.0 segfault exclusion (v !== 5000) also becomes unreliable with dot format since parseInt("0.50.0") returns 0, not 5000.

Suggestion: port the parseVersion() helper from osc8.ts, or implement dual-format handling inline.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
}
if (env['TERMINAL_EMULATOR'] === 'JetBrains-JediTerm') return true;
if (env['TERM_PROGRAM']) {
switch (env['TERM_PROGRAM']) {

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] Missing Konsole detection. The canonical supportsHyperlinks() in packages/cli/src/ui/utils/osc8.ts detects Konsole >= 21.04 via KONSOLE_VERSION >= 210400. This implementation has no Konsole check at all — Konsole users (a significant KDE terminal) always fall through to return false, even on versions that fully support OSC 8.

Suggested change
switch (env['TERM_PROGRAM']) {
if (env['TERMINAL_EMULATOR'] === 'JetBrains-JediTerm') return true;
if (env['KONSOLE_VERSION']) {
const v = parseInt(env['KONSOLE_VERSION'], 10);
if (Number.isFinite(v) && v >= 210400) return true;
}

— qwen3.7-max via Qwen Code /review

}
}

/**

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 supportsOsc8Hyperlinks() and osc8Hyperlink() functions duplicate ~80 lines of logic already implemented in packages/cli/src/ui/utils/osc8.ts (supportsHyperlinks() + osc8Hyperlink() + sanitizeForOsc()). While the structural constraint is real (core cannot import from cli), every discrepancy found in this review — missing Konsole, different FORCE_HYPERLINK parsing, different VTE handling, missing DCS passthrough, missing NO_COLOR/FORCE_COLOR — stems from this duplication. Future terminal additions or bug fixes in osc8.ts will not propagate here.

Consider extracting the shared detection (supportsHyperlinks, sanitizeForOsc, parseVersion, shouldForceHyperlinks, HYPERLINK_ENV_KEYS) into packages/core/src/utils/osc8-detect.ts that both packages/cli and packages/core can import. This eliminates the entire class of "PR subset drifted from reference" bugs in one change.

— qwen3.7-max via Qwen Code /review

);
});
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] Two important test coverage gaps in the new showFallbackMessage test suite:

  1. VTE_VERSION branch — the v >= 5000 && v !== 5000 condition has three meaningful sub-branches (5000 excluded, 6000 accepted, non-numeric rejected) but zero test cases. This is the most subtle branch in the detection function.

  2. osc8Hyperlink() sanitization — no test passes a URL containing control characters (\x07, \x1b) to verify the sanitization regex strips them. This is a security measure that could silently regress.

Suggestion: add tests for VTE_VERSION=5000 (expect no OSC 8), VTE_VERSION=6000 (expect OSC 8), and a URL like https://example.com/\x01\x1bpath asserting control chars are stripped from the OSC 8 output.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
if (!process.stderr?.isTTY) return false;
const force = env['FORCE_HYPERLINK'];
if (force !== undefined) return force !== '0';
if (env['CI']) return false;

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] Missing TEAMCITY_VERSION check.

The canonical supportsHyperlinks() in packages/cli/src/ui/utils/osc8.ts includes if (env['TEAMCITY_VERSION']) return false; after the CI check. TeamCity build agents may not set CI=true (older versions pre-2018.2), but always set TEAMCITY_VERSION. Without this guard, OSC 8 escape sequences could leak into TeamCity build logs as visible garbage.

Suggested change
if (env['CI']) return false;
if (env['CI']) return false;
if (env['TEAMCITY_VERSION']) return false;

— qwen3.7-max via Qwen Code /review

expect(output).toContain('Please visit the following URL');
expect(output).toContain('Waiting for authorization');
});
});

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] Four additional test coverage gaps in the showFallbackMessage suite:

  1. Control character sanitization — no test passes a URL containing \x07 or \x1b to verify they're stripped from the OSC 8 envelope. This is a security-relevant sanitization boundary.

  2. FORCE_HYPERLINK=0 — only =1 is tested. The =0 path (which should disable hyperlinks) has no test.

  3. CI=true suppressionCI is deleted in beforeEach but no test asserts that CI=true suppresses OSC 8 output.

  4. FORCE_HYPERLINK=1 + non-TTY — the non-TTY test explicitly deletes FORCE_HYPERLINK, leaving the interaction untested. The code correctly guards non-TTY before the force check, but a regression test would prevent a future refactor from reordering these checks.

— qwen3.7-max via Qwen Code /review

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

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
*/
function osc8Hyperlink(url: string): string {
// eslint-disable-next-line no-control-regex
const safeUrl = url.replace(/[\x00-\x1f\x7f\x80-\x9f]/g, '');

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] Missing URL scheme validation in osc8Hyperlink(). The function embeds the URL directly into an OSC 8 envelope without checking if the URL scheme is safe. The canonical osc8Hyperlink() in packages/cli/src/ui/utils/osc8.ts uses isSafeOscScheme() to restrict targets to http:, https:, mailto:, ftp:, ftps:, sftp:, ssh:. A compromised OAuth endpoint returning a javascript: URL as verification_uri_complete would be rendered as a clickable OSC 8 hyperlink.

Suggested change
const safeUrl = url.replace(/[\x00-\x1f\x7f\x80-\x9f]/g, '');
function osc8Hyperlink(url: string): string {
// eslint-disable-next-line no-control-regex
const safeUrl = url.replace(/[\x00-\x1f\x7f\x80-\x9f]/g, '');
const scheme = safeUrl.match(/^[a-z][a-z0-9+.-]*:/)?.[0]?.toLowerCase();
const safeSchemes = new Set(['http:', 'https:', 'ftp:', 'ftps:', 'sftp:', 'ssh:', 'mailto:']);
if (scheme && !safeSchemes.has(scheme)) {
return safeUrl; // fall back to plain text for unsafe schemes
}
return `\x1b]8;;${safeUrl}\x07${safeUrl}\x1b]8;;\x07`;
}

— qwen3.7-max via Qwen Code /review

wenshao added a commit that referenced this pull request Jul 13, 2026
…new code?

Agent 5 asks whether a test EXISTS and whether its assertions look like they
check something. Agent 7 runs the suite and reports that it is GREEN. Neither
can see a test that protects nothing, and there are two ways to ship one:

- unreachable — the project's test command never collects the file.
- inert — it runs, it passes, and it would still pass with the change reverted.

#6486 shipped both, in one file. The new test lived in integration-tests/, which
is not an npm workspace, so `npm test --workspaces` never collected it; its CI
job was skipped, so CI never ran it either. The test executed nowhere — not in
CI, not in the review — and nothing in the pipeline noticed. Had it run it would
have passed anyway: it drove a kitty CSI-u sequence into a PTY that never
negotiated the kitty protocol, so the keypress was discarded before reaching the
handler under test. It could only ever have caught a startup crash. Agent 5 saw
a test file with plausible assertions and called coverage fine.

Both questions are decidable without judgment, which is why they are a
subcommand and not a prompt. Unreachability needs no execution at all — a path
against the root package.json workspace globs. Inertness needs one run: revert
the diff's source files to base, keep its tests, re-run them.

The classifier is asymmetric on purpose. Reverting source frequently breaks a
test's own compile — it imports a symbol the diff introduced — and the runner
exits non-zero having collected nothing. Scoring that as "the test caught the
revert" would hand back exactly the false assurance this command exists to
remove. `gated` therefore requires a real ASSERTION failure; a bare non-zero
exit with nothing collected is `inconclusive`, and `inconclusive` is never
reported as a finding.

Verdicts are per test FILE, not per run. One `vitest run` covers every probe,
and a run-level verdict lets one honest test cover for a useless one: the gating
test fails, the run reports failures, and the inert test beside it is scored
`gated` too — so every inert test with a working sibling would be invisible,
which is the exact defect this command exists to find. Found by running it
against a real repo; the unit tests for the run-level classifier all passed.

Two other limits are deliberate: a test-only diff is never probed (a new test for
old code is SUPPOSED to pass with nothing reverted, and flagging it would be a
false blocker on exactly the PRs we want people to write), and findings are
Suggestions, not Criticals — a test that does not gate is not itself wrong code;
what the finding must name is the behaviour now shipping unprotected.

Driven against real PRs: #6433 reports GATED (9 assertions fail on revert, no
finding); #6486 reports its integration test unreachable and its two unit tests
gated.
wenshao added a commit that referenced this pull request Jul 13, 2026
…new code?

Agent 5 asks whether a test EXISTS and whether its assertions look like they
check something. Agent 7 runs the suite and reports that it is GREEN. Neither
can see a test that protects nothing, and there are two ways to ship one:

- unreachable — the project's test command never collects the file.
- inert — it runs, it passes, and it would still pass with the change reverted.

#6486 shipped both, in one file. The new test lived in integration-tests/, which
is not an npm workspace, so `npm test --workspaces` never collected it; its CI
job was skipped, so CI never ran it either. The test executed nowhere — not in
CI, not in the review — and nothing in the pipeline noticed. Had it run it would
have passed anyway: it drove a kitty CSI-u sequence into a PTY that never
negotiated the kitty protocol, so the keypress was discarded before reaching the
handler under test. It could only ever have caught a startup crash. Agent 5 saw
a test file with plausible assertions and called coverage fine.

Both questions are decidable without judgment, which is why they are a
subcommand and not a prompt. Unreachability needs no execution at all — a path
against the root package.json workspace globs. Inertness needs one run: revert
the diff's source files to base, keep its tests, re-run them.

The classifier is asymmetric on purpose. Reverting source frequently breaks a
test's own compile — it imports a symbol the diff introduced — and the runner
exits non-zero having collected nothing. Scoring that as "the test caught the
revert" would hand back exactly the false assurance this command exists to
remove. `gated` therefore requires a real ASSERTION failure; a bare non-zero
exit with nothing collected is `inconclusive`, and `inconclusive` is never
reported as a finding.

Verdicts are per test FILE, not per run. One `vitest run` covers every probe,
and a run-level verdict lets one honest test cover for a useless one: the gating
test fails, the run reports failures, and the inert test beside it is scored
`gated` too — so every inert test with a working sibling would be invisible,
which is the exact defect this command exists to find. Found by running it
against a real repo; the unit tests for the run-level classifier all passed.

Two other limits are deliberate: a test-only diff is never probed (a new test for
old code is SUPPOSED to pass with nothing reverted, and flagging it would be a
false blocker on exactly the PRs we want people to write), and findings are
Suggestions, not Criticals — a test that does not gate is not itself wrong code;
what the finding must name is the behaviour now shipping unprotected.

Driven against real PRs: #6433 reports GATED (9 assertions fail on revert, no
finding); #6486 reports its integration test unreachable and its two unit tests
gated.
pull Bot pushed a commit to mcx/qwen-code that referenced this pull request Jul 13, 2026
… actually gate new code (QwenLM#6790)

* fix(review): stop rendering a maintainer's blocker as an endorsement

The Step 6 re-check exists to stop a review submitting `C=0` while a live
blocker still stands on the PR. On QwenLM#6486 it did exactly that, and the reason
was structural rather than a lapse of judgment.

`pr-context` quarantined a thread into the mandatory re-check section only if
its body contained the literal string `[Critical]` — a marker only /review
itself emits. A maintainer built the PR, drove the real CLI, and filed
"Finding 1 — Ctrl+F dual-fires ... (blocker)" as an ISSUE comment. Every issue
comment settled into "Already discussed — do NOT re-report" as a 240-character
snippet, and the first 240 characters of that one were its preamble: "I built
this PR from source and drove the real CLI ... to validate the model-toggle
hotkey before merge." That reads as an ENDORSEMENT. The blocker began 1143
characters past the cut. Three hours later /review reviewed the same commit —
the fix did not land until that evening — and submitted "no blockers".

Recognition is now semantic (`carriesBlockerSignal`) and matches assertion
patterns rather than word presence, with a negation guard. Blocker-bearing
bodies — inline threads and issue comments alike — are promoted into a
"Blockers to re-check" section and rendered in full.

Word presence was the first cut and it does not survive contact with a real
thread: on the live QwenLM#6486 discussion it promoted 8 of 15 issue comments, of
which one was a live blocker. The rest were the triage bot's own template line
"No critical blockers." (the word inside its own negation), the author's
"### Critical fixes" heading, and a comment quoting `[Critical]` while arguing
a finding away. Eight full bodies took the context file from 30 KB to 59 KB and
pushed the real blocker to character 43094 — past the 25000 one `read_file`
returns. The section held the right blocker and no agent could read it, which
is PR QwenLM#5738's failure reintroduced one section further down.

So the section is written FIRST, ahead of the description and the review
history: nothing in this file outranks the claims a `C=0` verdict may not be
reached without ruling on. On the live thread that moved the heading from
character 25961 to 569 and the blocker body from 43094 to 4421. A character
budget bounds the section even so; bodies past it degrade to snippets naming
their exact fetch, which the re-check already must run before ruling.

The fixture is the real comment body, byte for byte, so the regression is
pinned against the thread that produced it.

* fix(review): make "fixed by this diff" a verdict that has to be earned

The Step 6 re-check has three verdicts, and until now only two of them cost
anything:

  still stands       REQUEST_CHANGES — blocks the merge
  cannot tell        serialized into the body, caps the event at COMMENT
  fixed by this diff nothing. Silent, free, unrecorded.

An agent choosing among three answers where one is free and two are not drifts
toward the free one — and the free one is the only one that can ship a bug.

The bar for it also read "you read the lines and the fix is there", which
invites reading the diff's lines. That is precisely the reading that fails: a
fix's new lines are always in the diff, but whether they WORK routinely depends
on code outside it.

QwenLM#6486 is the case. The author answered a Ctrl+F dual-fire blocker by adding a
guard to the toggle handler — visible in the diff, and it reads like a fix. It
changed nothing. The second handler is text-buffer.ts:2663, in a file the PR
never touches, subscribed independently to a KeypressContext.broadcast() with
no stop-propagation; returning from one subscriber does not stop the other.
Read the diff and you see a guard and rule "fixed". Read text-buffer.ts:2663
and you cannot.

Determinism owns the evidence, judgment owns the ruling:

- pr-context extracts the evidence. A blocker's body names the code it is about
  — QwenLM#6486's named text-buffer.ts:2663 outright — so every promoted blocker now
  renders a "Referenced code" list. "Go read the untouched code" stops being a
  hope the agent might have and becomes a list it is handed.
- SKILL.md raises the bar on the ruling: name the mechanism, name what now
  stops it, and when the stopping condition lives outside the diff, read it
  there — or the verdict is `cannot tell`.

No new compose-review input: `cannot tell` already caps the event. The change
is to make wrong "fixed" rulings land there instead of passing silently.

* fix(review): a skipped CI check is not a passing CI check

GitHub reports a skipped job as `status: completed, conclusion: skipped`. The
classifier tested for failure conclusions and for pending statuses, and
`skipped` matched neither — so it fell through both branches and landed the run
in `all_pass`. A job that never ran was scored as a job that passed.

This is load-bearing. /review treats green CI as its licence to approve, and the
whole design delegates runtime truth to CI precisely because the LLM pipeline
reads code statically. If the delegation returns nothing and returns it wearing
a green badge, the delegation is worse than not having it.

On QwenLM#6486 the one job that would have exercised the new hotkey — "Integration
Tests (CLI, No Sandbox)" — was skipped, as were the macOS and Windows Test legs.
all_pass.

"Did it run" is a question about the check NAME, not about any single run: this
repo's routing workflows (authorize, review-pr, precheck-pr) routinely emit both
a skipped and a successful run of the same name, and reporting those as unrun
would bury the one skipped check that matters under a dozen that do not. A name
counts as executed if any of its runs reached a real conclusion.

Two deliberately different consequences:

- Some checks skipped -> a disclosure, not a downgrade. A docs-only PR
  legitimately skips the test matrix, and auto-downgrading on any skip would
  downgrade every review in this repo, which is how a gate gets ignored. So
  presubmit names them and Step 7 rules on them — whether a skipped check would
  have exercised THIS diff is a question about the diff, which presubmit cannot
  see and the reviewer can.
- Every check skipped -> a downgrade. Checks exist, not one ran: there is no
  green here to approve on, and no judgment is required to say so. A repo with
  no CI at all is a different claim (totalChecks === 0) and is not downgraded.

The check-run shapes in the tests are the real ones from 6486's head commit.

* feat(review): add a test-efficacy probe — does the new test gate the new code?

Agent 5 asks whether a test EXISTS and whether its assertions look like they
check something. Agent 7 runs the suite and reports that it is GREEN. Neither
can see a test that protects nothing, and there are two ways to ship one:

- unreachable — the project's test command never collects the file.
- inert — it runs, it passes, and it would still pass with the change reverted.

QwenLM#6486 shipped both, in one file. The new test lived in integration-tests/, which
is not an npm workspace, so `npm test --workspaces` never collected it; its CI
job was skipped, so CI never ran it either. The test executed nowhere — not in
CI, not in the review — and nothing in the pipeline noticed. Had it run it would
have passed anyway: it drove a kitty CSI-u sequence into a PTY that never
negotiated the kitty protocol, so the keypress was discarded before reaching the
handler under test. It could only ever have caught a startup crash. Agent 5 saw
a test file with plausible assertions and called coverage fine.

Both questions are decidable without judgment, which is why they are a
subcommand and not a prompt. Unreachability needs no execution at all — a path
against the root package.json workspace globs. Inertness needs one run: revert
the diff's source files to base, keep its tests, re-run them.

The classifier is asymmetric on purpose. Reverting source frequently breaks a
test's own compile — it imports a symbol the diff introduced — and the runner
exits non-zero having collected nothing. Scoring that as "the test caught the
revert" would hand back exactly the false assurance this command exists to
remove. `gated` therefore requires a real ASSERTION failure; a bare non-zero
exit with nothing collected is `inconclusive`, and `inconclusive` is never
reported as a finding.

Verdicts are per test FILE, not per run. One `vitest run` covers every probe,
and a run-level verdict lets one honest test cover for a useless one: the gating
test fails, the run reports failures, and the inert test beside it is scored
`gated` too — so every inert test with a working sibling would be invisible,
which is the exact defect this command exists to find. Found by running it
against a real repo; the unit tests for the run-level classifier all passed.

Two other limits are deliberate: a test-only diff is never probed (a new test for
old code is SUPPOSED to pass with nothing reverted, and flagging it would be a
false blocker on exactly the PRs we want people to write), and findings are
Suggestions, not Criticals — a test that does not gate is not itself wrong code;
what the finding must name is the behaviour now shipping unprotected.

Driven against real PRs: QwenLM#6433 reports GATED (9 assertions fail on revert, no
finding); QwenLM#6486 reports its integration test unreachable and its two unit tests
gated.

* fix(review): harden CI classification, path safety, and probe robustness

Five correctness fixes surfaced by a Codex $qreview pass on this PR. Each was
verified against the real code before applying; the review filed 30 Criticals,
of which these are the ones that actually reproduce a wrong result.

- presubmit: paginate `check-runs`. The single-page `ghApi` call saw only the
  first 30 runs — this PR's own head has 508 — so a failing or skipped job past
  the cut was invisible and could let a review approve past it. New
  `ghApiAllNested` streams `--paginate --jq '.check_runs[]'` as NDJSON (gh has
  no `--slurp`; the parse is split into a pure `parseNdjson` for testing).

- presubmit: treat `startup_failure` as a failure. It was absent from
  `FAIL_CONCLUSIONS`, so a workflow that could not start counted as an executed
  run that added no failed name — an `all_pass` on a commit whose CI never ran.

- presubmit: `waiting` and `requested` are active check-run statuses; add them
  to the pending set so a commit whose only check is waiting is not mislabeled
  `no_checks`.

- pr-context: `extractCodeRefs` rendered path tokens from an untrusted comment
  body into the trusted "read each at the reviewed commit" directive. A blocker
  citing `../../../../etc/passwd.sh` or `/root/.ssh/id_rsa.key` entered the read
  list. Drop any absolute, `~`, or `..`-segment path; a real in-repo reference
  is repository-relative.

- test-efficacy: raise the probe's `spawnSync` maxBuffer to 64 MiB (the ceiling
  the gh wrapper already uses). Vitest's JSON reporter on a large suite exceeds
  the 1 MiB default, returns ENOBUFS, and turns every probe `inconclusive`.

* fix(review): comma-clause negation, RegExp flag preservation, stale comment

Third self-review round. No blockers; these are the substantive suggestions.

- pr-context: the negation stop-set gained clause separators last round but not
  the comma, so "No other concerns, but auth is a blocker" let the negation
  reach across the comma and suppress a real blocker — a false negative, the
  costly direction, flagged independently by two reviewers. Adding `,,、` leaves
  recall 2/2 and false positives 6/36 on the 38-comment corpus, and still negates
  "No blockers found, ship it".

- pr-context: `carriesBlockerSignal` rebuilt each pattern with `new RegExp(re.
  source, 'g')`, dropping any flags the pattern carried. Harmless today (no
  pattern has flags) but a latent trap the moment one gains `i`/`u`. Preserve
  the pattern's flags and dedupe `g`.

- test-efficacy: the workspace-glob comment still described the old two-pass
  filter as a present defect; the code is single-pass ordered evaluation. Fixed
  the comment to match.

* fix(review): don't revert data fixtures; guard dirty worktree; CJK non-blocker

Fourth review round (Codex $qreview + qwen). No blockers survived verification;
these are the confirmed correctness issues.

- test-efficacy: `planTestEfficacy` reverted every `kind: source` file, but
  `classifyPath` labels non-executable data under a src tree `source` too —
  JSON fixtures, `.md` bodies, snapshots. This PR ships one such fixture that
  `pr-context.test.ts` loads; reverting it deleted the file and made that probe
  inconclusive because of the probe itself. Revert now gates on an
  executable-source extension.

- test-efficacy: refuse to run when the `--worktree` has uncommitted changes to
  a revert-set file. Safe on the pipeline's ephemeral worktree, but this is a
  public command and the checkout-over-revert would discard a user's staged or
  unstaged edits with no undo.

- pr-context: `非阻塞` / `并非阻塞` is the Chinese "non-blocking" — the CJK twin
  of the `non-blocking` lookbehind. Without a guard, "非阻塞问题" promoted and
  consumed the mandatory-review budget. Same class as the bilingual-negation fix
  two rounds ago; a guard was written for one language and not the other.

- DESIGN.md: sync the pattern list (bare `blocking`, not the noun forms) and the
  Referenced-code claim (only when the blocker names a file) to the code.

* fix(review): make the dirty-worktree guard fail closed

Fifth review round. One Critical and a vacuous test, both real.

- test-efficacy: the dirty-worktree guard added last round called `spawnSync`
  directly and read `(r.stdout ?? '')`, so a spawn failure produced an empty
  string, read as "clean", and let the probe proceed — the fail-OPEN outcome in
  a guard whose whole purpose is to prevent data loss. Route it through a
  `gitOut` helper that throws on `r.error`/non-zero, and apply the same
  `r.error` check to `existsAtRev`. Verified: a dirty worktree now refuses to
  run and the uncommitted change survives.

- pr-context.test: the comma-negation test's second assertion
  (`No blockers found, ship it` -> false) was vacuous — the plural `blockers`
  matches no pattern, so it proved nothing about the negation window. Replaced
  with `This is not a blocker`, which actually exercises it.

- test-efficacy.test: add the source-only case (`probes: []` with a non-empty
  revert set), the mirror of the existing test-only case.

* fix(review): NDJSON per-line tolerance, dedupe failed checks, GFM nesting

Sixth review round — three small confirmed issues, two of them my own from
earlier rounds.

- gh: `parseNdjson` threw the whole page away if any single line failed to
  parse. `gh` can print an update/deprecation notice to stdout, so parse
  line-by-line and skip a non-JSON line instead of losing the records already
  read.

- presubmit: `failedCheckNames` used `.push()` and so listed a matrix job once
  per failing platform ("Test, Test, Test"), while the `skippedCheckNames` I
  added dedupes via a Set. Dedupe `failedCheckNames` too.

- SKILL.md: a nested `**bold**` inside a `**bold**` span (introduced when I
  qualified the Referenced-code claim two rounds ago) breaks GFM — the inner
  `**` closes the outer span, mis-rendering an agent-facing instruction. Drop
  the inner emphasis.

* fix(review): redesign blocker negation; fail-closed parse; fixture-dir revert

Seventh review round (Codex). Six confirmed issues, four of them regressions
from my own earlier fixes — a sign the patch-on-patch approach to natural
language and to the probe's file selection had to be replaced, not extended.

- pr-context: replace the pile of per-pattern negation lookbehinds with one
  negation-window model. Each lookbehind fix had opened a hole in the other
  direction: `(?<!非)` suppressed `除非` ("unless", a real blocking condition);
  the adjacency-only guard missed `并非一个阻塞项`; the comma I added to the
  stop-set broke the coordinated list "No blocking, must-fix, or critical". The
  window now scans a negation word within ~40 clause chars, RESETS at an
  adversative (`but`/`但`) but not a bare comma, and breaks at `;`/`:`. Verified
  on an 11-case matrix and the 38-comment corpus: recall 2/2, false positives
  5/36 (down from 6). Patterns are now bare, negation is one mechanism.

- gh: `parseNdjson` is strict by default and `ghApiAllNested` uses strict. Last
  round I made it lenient to tolerate a `gh` update notice, but silently
  dropping a malformed check-runs line could hide a *failing* run — the
  fail-open the pagination fix closed. Leniency is now an explicit opt-in.

- test-efficacy: the revert set excludes fixture DIRECTORIES, not non-code
  extensions. The extension whitelist also dropped runtime-loaded sources a
  test gates — an executable `SKILL.md`, a settings-schema JSON — so a
  skill-only change produced no probe. Directory is the right discriminator.

- test-efficacy: the dirty-worktree guard adds `--ignored`, so a gitignored
  revert-set path recreated locally is not read as clean and overwritten.

* fix(review): ReDoS, un-replied blocker promotion, status pagination, path guard

Eighth review round (Codex). Several confirmed defects, and one I got wrong last
round.

- pr-context: **ReDoS in `CODE_REF_RE`** — I rejected this as a hallucination
  after testing the wrong input shape. Codex's exact shape (`"(blocker)\n" +
  "a".repeat(n)`) reproduces: the two overlapping greedy quantifiers
  `[\w./@-]*[\w-]+\.` backtrack catastrophically when `\.ext` fails, ~7s at 80k
  chars on an untrusted comment body. Replaced with a single bounded class
  `[\w./@-]{0,200}[\w-]\.` — 0 ms at 80k, same matches.

- pr-context: **an un-replied blocker root was never promoted.** Only *replied*
  roots ran through `carriesBlockerSignal`; a fresh `[Critical]` with no reply
  went straight into "Open inline comments" as a 240-char snippet — the exact
  read-window failure this change exists to close, left open for the un-replied
  half. Open blocker roots now join the re-check section, rendered first and in
  full.

- pr-context: the negation window resets at a space-surrounded hyphen (` - ` /
  ` -- `), an informal clause separator, without touching `must-fix` /
  `non-blocking`.

- presubmit: paginate the legacy combined-status endpoint (same first-page-only
  gap as check-runs — a failing status on page 2 was invisible).

- test-efficacy: reject a revert path that escapes the worktree (the report JSON
  is untrusted and these become git pathspecs / fs targets), and exit non-zero
  on a restore failure so a caller cannot mistake a base-code tree for a clean
  run.

* fix(review): don't let the efficacy probe delete through a PR-controlled symlink

A reviewer reproduced a P0. The efficacy probe reverts the PR's source to base
in the shared worktree and restores it afterward, deleting files with
`rmSync(join(worktree, p), { force: true })`. `rmSync` follows symlinks in the
path prefix, and the revert set is PR-controlled, so:

  1. base has a real `dir/victim`;
  2. PR head replaces `dir` with a symlink to an outside directory and deletes
     `dir/victim`;
  3. the probe restores HEAD (the `dir` symlink), then deletes the `dir/victim`
     path — which now resolves through the link and removes the OUTSIDE file.

The lexical `escapes the worktree` guard added last round cannot catch this:
`dir/victim` is lexically inside the tree; the escape is a runtime symlink
traversal. Confirmed by driving the real handler — the outside file was deleted.

Both delete sites (reverting an added file, restoring a deleted one) now go
through `safeRmWithin`, which walks every path component from the worktree root
and refuses when an ANCESTOR is a symlink. The final component being a symlink is
still fine — that unlinks the link itself, which is what reverting an added
symlink should do. A refusal fails closed: it sets the restore-failure disclosure
and the non-zero exit, so the tree is never silently left mutated.

Verified: the P0 repro now leaves the outside file intact and exits non-zero; a
legit no-symlink PR still restores cleanly (exit 0, worktree back at HEAD).

The deeper fix the reviewer suggested — run the probe in a disposable isolated
worktree — also addresses the concurrent-read Critical and is tracked as a
follow-up; this closes the file-deletion vector now.
@wenshao

wenshao commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

@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 Jul 22, 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

Copy link
Copy Markdown
Collaborator

🤖 Could not address the latest feedback automatically (round 1/100). A human should take over this PR.

⚠️ This change was NOT pushed — any commit referenced below was made only in the runner workspace and has been discarded. What the agent reported:

Review Feedback Summary

All 16 inline findings were triaged. 15 were implemented; 1 was declined with reason.

Critical findings (all fixed)

rc ID Finding Action
rc:3540972913 Missing tmux/screen DCS passthrough in osc8Hyperlink() Fixed — added DCS wrapping for tmux (\x1bPtmux;<doubled-ESC>\x1b\\) and screen (\x1bP<seq>\x1b\\), matching wrapForMultiplexer() in packages/cli/src/utils/osc.ts
rc:3540972917 No right-padding to contentWidth + no length guard for long URLs Fixed — OSC 8 branch now pads with ' '.repeat(contentWidth - url.length) and falls back to wrapped text when url.length > contentWidth
rc:3540972920 parseInt for VTE_VERSION doesn't handle dot-separated versions Fixed — ported parseVersion() logic as parseOsc8Version(), handling both packed integer (5000) and dot-separated (0.60.0) formats
rc:3540972928 Missing test coverage for VTE_VERSION and sanitization Fixed — added tests for VTE 5000 (excluded), 6000 (accepted), dot-format 0.60.0/0.50.0, non-numeric rejection, and control character stripping

Suggestions (implemented)

rc ID Finding Action
rc:3535029420 Missing NO_COLOR and FORCE_COLOR=0 checks Fixed — added both as hard opt-outs before the TTY guard, matching the reference
rc:3535029440 FORCE_HYPERLINK parsing too permissive Fixed — ported `shouldForceHyperli

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


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

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

No changes were made this round.

Why: There is no new actionable feedback on this PR. The review scan found no reviews, no inline comments, and no issue-level comments newer than the last evaluation (2026-07-11T04:26:32Z), so there is nothing to classify or address.

The only failed check listed for this round is review-address, which is this autofix bot's own previous address-review job (its check name encodes the bot's run parameters: 6433, fix/auth-url-osc8-hyperlink, 6433, 0, 2026-07-07T07:29:02Z, ...). It is not a CI failure on the PR's code and provides no code-level defect to fix. The PR's actual CI checks are green — Test (ubuntu-latest, Node 22.x), review-pr, Classify PR, and coverage all reported SUCCESS — and there are no persisting ("still-red") checks.

The current change (emitting the OAuth device-authorization URL as a single OSC 8 clickable hyperlink instead of hard-wrapping it, with a wrapped-URL fallback for unsupported terminals) therefore stands as-is, with its existing focused Vitest coverage in packages/core/src/qwen/qwenOAuth2.test.ts.

中文说明

Autofix 审查轮次 — 未采取任何操作

本轮未做任何更改。

原因: 本 PR 没有新的可处理反馈。审查扫描未发现任何比上次评估时间(2026-07-11T04:26:32Z)更新的评审(reviews)、行内评论(inline comments)或 issue 级评论(issue-level comments),因此没有内容可供分类或处理。

本轮唯一列出的失败检查是 review-address,它是本 autofix 机器人自己上一轮的 address-review 任务(其检查名称中编码了机器人的运行参数:6433, fix/auth-url-osc8-hyperlink, 6433, 0, 2026-07-07T07:29:02Z, ...)。它并不是 PR 代码本身的 CI 失败,也没有提供任何可在代码层面修复的缺陷。本 PR 的实际 CI 检查均为绿色 —— Test (ubuntu-latest, Node 22.x)review-prClassify PR 以及覆盖率均报告 SUCCESS —— 并且没有持续失败("still-red")的检查。

因此,当前的改动(将 OAuth 设备授权 URL 以单个 OSC 8 可点击超链接的形式输出,而不是硬换行拆分;对于不支持的终端则回退为换行输出的 URL)保持原样,并继续在 packages/core/src/qwen/qwenOAuth2.test.ts 中由现有的聚焦 Vitest 测试覆盖。

Base-conflict check: no conflict with main.


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix Review — No Action Needed

No actionable review feedback was found on PR #6433.

  • Reviews: none
  • Inline comments: none
  • Issue-level comments: none
  • Failed checks: all listed checks (review-config, authorize, ack-review-request, delay-automatic-review, resolve-pr, review-pr) have status CANCELLED, which indicates workflow cancellation rather than real failures.
  • Still-red checks: none

No code changes were made.

中文说明

Autofix 审查 — 无需操作

PR #6433 上没有发现需要处理的审查反馈。

  • 审查意见:
  • 行内评论:
  • Issue 级别评论:
  • 失败的检查: 所有列出的检查(review-configauthorizeack-review-requestdelay-automatic-reviewresolve-prreview-pr)状态均为 CANCELLED,表示工作流被取消,而非真正的失败。
  • 持续失败的检查:

未进行任何代码更改。

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


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

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment on lines +711 to +713
function supportsOsc8Hyperlinks(): boolean {
const env = process.env;
if (env['QWEN_DISABLE_HYPERLINKS'] === '1') return false;

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] supportsOsc8Hyperlinks() duplicates ~80 lines of logic already implemented in packages/cli/src/ui/utils/osc8.ts (supportsHyperlinks() + osc8Hyperlink() + sanitizeForOsc()).

Concrete drift already exists in this initial commit: missing ALACRITTY_SOCKET detection, NO_COLOR/FORCE_COLOR opt-outs, KONSOLE_VERSION detection, mintty version-gating, and TEAMCITY_VERSION CI guard. Two parallel implementations will drift further over time.

Since packages/cli depends on packages/core, moving the shared helpers into packages/core and importing from both sites eliminates the duplication.

— qwen3.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.test.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
@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 轮)。改动内容与我反驳保留之处如下:

Review feedback addressed

[Critical] rc:3638749553 — Missing DCS passthrough wrapping in tmux/screen

Decision: Fixed.

osc8Hyperlink() now wraps the OSC 8 sequence in a DCS passthrough envelope when running inside tmux (\x1bPtmux; with ESC doubling) or screen (\x1bP without doubling), matching the reference wrapForMultiplexer() in packages/cli/src/utils/osc.ts. Without this, tmux strips or garbles the raw escape sequences when FORCE_HYPERLINK=1 is set.

The existing tmux test now also asserts DCS wrapping (\x1bPtmux; and \x1b\\), and a new test covers screen (STY) wrapping.

[Suggestion] rc:3638749571 — Code duplication with packages/cli osc8.ts

Decision: Declined the full refactor (moving shared helpers into packages/core); fixed the concrete drift items inline instead.

Moving osc8.ts from packages/cli into packages/core is a significant architectural change that goes beyond this PR's scope. However, the specific drift items called out have been addressed:

  • ALACRITTY_SOCKET detection — added to the Alacritty check.
  • NO_COLOR / FORCE_COLOR opt-outs — added before the TTY guard, matching the reference order.
  • KONSOLE_VERSION detection — added with version gate >= 210400.
  • TEAMCITY_VERSION CI guard — added after the CI check.
  • mintty version-gating — see rc:3638749578 below.

[Suggestion] rc:3638749578 — mintty version gating

Decision: Fixed.

The mintty case now gates on TERM_PROGRAM_VERSION >= 3.3, matching the reference. Missing version returns false (very old build — refuse rather than guess). This prevents raw escape bytes appearing as visible garbage on older mintty builds bundled with some Git-for-Windows distros.

Three new tests cover: mintty 3.3.0 (passes), mintty 3.1.0 (refused), mintty without version (refused).

[Suggestion] rc:3638749589 — Missing test for control character sanitization

Decision: Fixed.

Added a test that passes a URL containing \x07 (BEL) and \x1b (ESC) control characters and verifies they are stripped from the OSC 8 envelope output.

[Suggestion] rc:3638749596 — FORCE_HYPERLINK parsing too permissive

Decision: Fixed.

Replaced force !== '0' with a shouldForceHyperlinks() helper matching the reference: empty string enables, numeric non-zero enables, non-numeric strings (e.g. "false", "abc") disable. Two new tests cover FORCE_HYPERLINK=false and FORCE_HYPERLINK=0.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • cd packages/core && npx vitest run src/qwen/qwenOAuth2.test.ts — 103 passed, 1 failed (pre-existing environment-specific failure in getQwenCachedCredentialPath — same failure on base branch, unrelated to this change)
中文说明

已处理的评审反馈

[Critical] rc:3638749553 — tmux/screen 中缺少 DCS 透传包装

决定: 已修复。

osc8Hyperlink() 现在在 tmux(\x1bPtmux; 并对 ESC 进行双写)或 screen(\x1bP 不双写)中运行时,将 OSC 8 序列包装在 DCS 透传信封中,与 packages/cli/src/utils/osc.ts 中的参考实现 wrapForMultiplexer() 保持一致。如果没有此包装,当设置 FORCE_HYPERLINK=1 时,tmux 会剥离或弄乱原始转义序列。

现有的 tmux 测试现在也断言 DCS 包装(\x1bPtmux;\x1b\\),并新增了一个覆盖 screen(STY)包装的测试。

[Suggestion] rc:3638749571 — 与 packages/cli osc8.ts 的代码重复

决定: 拒绝完整重构(将共享辅助函数移入 packages/core);改为在内联修复具体的差异项。

osc8.tspackages/cli 移入 packages/core 是一项重大的架构变更,超出了本 PR 的范围。但其中指出的具体差异项已得到修复:

  • ALACRITTY_SOCKET 检测 — 已添加到 Alacritty 检查中。
  • NO_COLOR / FORCE_COLOR 退出选项 — 已在 TTY 守卫之前添加,与参考实现的顺序一致。
  • KONSOLE_VERSION 检测 — 已添加,版本门槛为 >= 210400
  • TEAMCITY_VERSION CI 守卫 — 已在 CI 检查之后添加。
  • mintty 版本门控 — 见下方 rc:3638749578。

[Suggestion] rc:3638749578 — mintty 版本门控

决定: 已修复。

mintty 分支现在以 TERM_PROGRAM_VERSION >= 3.3 为门槛,与参考实现一致。缺少版本号时返回 false(非常旧的构建——拒绝而非猜测)。这可以防止在某些 Git-for-Windows 发行版中捆绑的旧版 mintty 构建上将原始转义字节显示为可见乱码。

新增三个测试覆盖:mintty 3.3.0(通过)、mintty 3.1.0(拒绝)、mintty 无版本号(拒绝)。

[Suggestion] rc:3638749589 — 缺少控制字符清理测试

决定: 已修复。

新增了一个测试,传入包含 \x07(BEL)和 \x1b(ESC)控制字符的 URL,并验证它们从 OSC 8 信封输出中被剥离。

[Suggestion] rc:3638749596 — FORCE_HYPERLINK 解析过于宽松

决定: 已修复。

force !== '0' 替换为与参考实现一致的 shouldForceHyperlinks() 辅助函数:空字符串启用,非零数字启用,非数字字符串(如 "false""abc")禁用。新增两个测试覆盖 FORCE_HYPERLINK=falseFORCE_HYPERLINK=0

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • cd packages/core && npx vitest run src/qwen/qwenOAuth2.test.ts — 103 通过,1 失败(getQwenCachedCredentialPath 中预先存在的环境相关失败——在基础分支上同样失败,与本次更改无关)

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-preview

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Review feedback addressed

1. [Critical] OSC 8 URL line omits right-padding (rc:3639573471)

Decision: Implemented.

Changes: Added osc8Padding computed from contentWidth - url.length (the visible URL length, not the escape-sequence length) and inserted it before the right | border in the OSC 8 branch of showFallbackMessage. The right border now aligns at column boxWidth (70) on all terminals, matching every other content line in the box.

Files: packages/core/src/qwen/qwenOAuth2.ts (line ~900)

2. [Suggestion] Sanitization regex omits Unicode bidi controls (rc:3639573481)

Decision: Implemented.

Changes: Extended the sanitization regex in osc8Hyperlink from /[\x00-\x1f\x7f\x80-\x9f]/g to /[\x00-\x1f\x7f\x80-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069\u2028\u2029]/g, matching the existing sanitizeForOsc() in packages/cli/src/ui/utils/osc8.ts. This strips bidi override/embedding/isolate characters (CVE-2021-42574 class) and Unicode line separators that could fracture the OSC envelope.

Files: packages/core/src/qwen/qwenOAuth2.ts (line ~791)

3. [Suggestion] Plain-text fallback path writes unsanitized URL (rc:3639573487)

Decision: Implemented.

Changes: Moved sanitization to the top of showFallbackMessageconst url = verificationUriComplete.replace(...) — so both the OSC 8 path and the plain-text fallback path use the sanitized URL. The osc8Hyperlink function retains its own sanitization as defense-in-depth (idempotent).

Files: packages/core/src/qwen/qwenOAuth2.ts (line ~818)

Tests added

  • strips bidi override characters from URL — verifies \u202e is stripped from the OSC 8 envelope
  • right-pads OSC 8 URL line to align the box border — strips OSC sequences and asserts the visible line is exactly boxWidth (70) chars ending with |
  • sanitizes control characters in plain-text fallback path — verifies \x07 and \x1b are stripped in the non-TTY fallback

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint (changed files) — passed
  • npx prettier --check (changed files) — passed
  • vitest run src/qwen/qwenOAuth2.test.ts (packages/core) — 106 passed, 1 failed (pre-existing environment-specific failure in getQwenCachedCredentialPath, confirmed failing on base branch without these changes)
中文说明

已处理的审查反馈

1. [Critical] OSC 8 URL 行缺少右侧填充 (rc:3639573471)

决定: 已实现。

更改:showFallbackMessage 的 OSC 8 分支中,根据 contentWidth - url.length(URL 的可见长度,而非转义序列长度)计算 osc8Padding,并将其插入右侧 | 边框之前。右侧边框现在在所有终端上对齐到第 boxWidth(70)列,与框中其他所有内容行一致。

文件: packages/core/src/qwen/qwenOAuth2.ts(约第 900 行)

2. [Suggestion] 清理正则表达式遗漏 Unicode 双向控制字符 (rc:3639573481)

决定: 已实现。

更改:osc8Hyperlink 中的清理正则从 /[\x00-\x1f\x7f\x80-\x9f]/g 扩展为 /[\x00-\x1f\x7f\x80-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069\u2028\u2029]/g,与 packages/cli/src/ui/utils/osc8.ts 中现有的 sanitizeForOsc() 保持一致。这会剥离双向覆盖/嵌入/隔离字符(CVE-2021-42574 类别)以及可能破坏 OSC 信封的 Unicode 行分隔符。

文件: packages/core/src/qwen/qwenOAuth2.ts(约第 791 行)

3. [Suggestion] 纯文本回退路径写入未清理的 URL (rc:3639573487)

决定: 已实现。

更改: 将清理逻辑移至 showFallbackMessage 顶部 — const url = verificationUriComplete.replace(...) — 使 OSC 8 路径和纯文本回退路径都使用已清理的 URL。osc8Hyperlink 函数保留自身的清理作为纵深防御(幂等操作)。

文件: packages/core/src/qwen/qwenOAuth2.ts(约第 818 行)

新增测试

  • strips bidi override characters from URL — 验证 \u202e 从 OSC 8 信封中被剥离
  • right-pads OSC 8 URL line to align the box border — 剥离 OSC 序列后断言可见行恰好为 boxWidth(70)个字符,以 | 结尾
  • sanitizes control characters in plain-text fallback path — 验证非 TTY 回退路径中 \x07\x1b 被剥离

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint(变更文件)— 通过
  • npx prettier --check(变更文件)— 通过
  • vitest run src/qwen/qwenOAuth2.test.ts(packages/core)— 106 通过,1 失败(getQwenCachedCredentialPath 中的预存环境特定失败,已确认在未包含这些更改的基础分支上同样失败)

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-preview

@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.7-max via Qwen Code /review

Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.test.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.ts Outdated
Comment thread packages/core/src/qwen/qwenOAuth2.test.ts Outdated
…#6433)

Address review feedback on the OAuth device-flow OSC 8 hyperlink path:

- Fix VTE_VERSION detection misreading dot-format versions (e.g. 0.60.0
  parsed as 0 and refused) by reusing the reference parseVersion heuristic
  that understands both packed (5000/7800) and dot-separated forms, while
  still excluding the segfaulting 0.50.0.
- Version-gate iTerm.app (>= 3.1), WezTerm (>= 20200620) and VS Code
  (>= 1.72) instead of accepting them unconditionally, so old builds that
  predate OSC 8 don't render raw escape bytes.
- Add the win32 fallback guard so leaked env vars (e.g. TERM=alacritty over
  SSH into cmd.exe/conhost) can't produce visible garbage.
- Gate the clickable envelope behind an allowlisted URL scheme as
  defense-in-depth against a compromised provider returning javascript:/file:.
- Widen the box for verification URLs longer than the default width so the
  single-line link and its closing border stay aligned instead of overflowing.
- Extract a single sanitizeForOsc helper so the control/bidi-stripping regex
  lives in one place rather than being duplicated across both call sites.
- Strengthen the tmux DCS-passthrough test to assert the doubled ESC prefix
  and add coverage for the VTE, version-gate, scheme, and long-URL paths.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Review feedback addressed

All seven inline suggestions from the automated reviewer were implemented. They all move the OAuth device-flow OSC 8 path closer to the reference implementation in packages/cli/src/ui/utils/osc8.ts, and one of them (VTE parsing) fixes a genuine detection bug. No feedback was declined.

  • rc:3640199122 — duplicated sanitization regex (implemented). Extracted a single module-local sanitizeForOsc() helper and now call it from both showFallbackMessage and osc8Hyperlink, so the control/bidi-stripping regex lives in exactly one place. osc8Hyperlink keeps sanitizing its own input (matching the reference), so the helper stays safe to call standalone.

  • rc:3640199125 — long-URL box overflow (implemented). In OSC 8 mode the box width now grows to url.length + 4 when the verification URL is longer than the default content width, so the single-line clickable link and its closing | border stay aligned instead of overflowing the frame. The URL stays on one clickable line (the SSH copy-paste case the PR targets); it is not downgraded to wrapped plain text.

  • rc:3640199131 — VTE detection bug + missing tests (implemented). The old parseInt(VTE_VERSION) check misread dot-format versions: 0.60.0 parsed to 0 and a capable terminal was refused. Replaced it with the reference parseVersion() heuristic, which understands both the packed form (5000, 7800) and the dot-separated form, while still excluding the segfaulting 0.50.0. Added four tests: packed 5000 (refused), packed 7800 (accepted), dot-format 0.60.0 (accepted — would have caught the bug), and dot-format 0.50.0 (refused).

  • rc:3640199135 — unconditional terminal acceptance (implemented). iTerm.app, WezTerm, and VS Code are now version-gated to match the reference (iTerm ≥ 3.1, WezTerm ≥ 20200620, VS Code ≥ 1.72) via the shared parseVersion(), so pre-OSC-8 builds no longer receive raw escape bytes. Added tests for iTerm 3.0.10 (refused) and VS Code 1.71.0 (refused).

  • rc:3640199139 — no URL scheme validation (implemented). Added an isSafeOscScheme() allowlist (http:, https:, mailto:, ftp:, ftps:, sftp:, ssh:) mirroring the reference; the clickable envelope is only emitted for allowlisted schemes, otherwise the URL falls back to plain text. Added a test asserting a javascript: URL is not wrapped.

  • rc:3640199145 — missing win32 guard (implemented). Added if (process.platform === 'win32') return false; before the final fall-through, matching the reference, so leaked env vars (e.g. TERM=alacritty over SSH into cmd.exe/conhost) cannot produce visible garbage. Windows Terminal still matches earlier via WT_SESSION.

  • rc:3640199152 — weak tmux assertion (implemented). The tmux DCS-passthrough test now asserts the exact doubled-ESC prefix \x1bPtmux;\x1b\x1b]8;;, so it fails if the ESC-doubling (replaceAll('\x1b', '\x1b\x1b')) is ever removed — the previous toContain('\x1bPtmux;') would have kept passing.

Three existing tests that set TERM_PROGRAM=iTerm.app without a version now set TERM_PROGRAM_VERSION=3.5.0; with the new (reference-matching) version gate, iTerm without a version is correctly refused, so those tests needed a realistic supported version to keep exercising the OSC 8 path.

Conflict notes

--conflict false: no merge of origin/main was performed; the branch applied cleanly.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx eslint packages/core/src/qwen/qwenOAuth2.ts packages/core/src/qwen/qwenOAuth2.test.ts — passed (no errors)
  • npx vitest run src/qwen/qwenOAuth2.test.ts -t "showFallbackMessage" (in packages/core) — 29 passed
  • npx vitest run src/qwen/qwenOAuth2.test.ts (in packages/core) — 114 passed, 1 failed: getQwenCachedCredentialPath > should return correct path to cached credentials. This failure is pre-existing and unrelated to this change — it reproduces on the clean tree (verified via git stash) and is an environment-specific os.homedir() path mismatch in this sandbox; it asserts a credential-file path and has no connection to the OSC 8 work.

No settings source changed, so npm run generate:settings-schema was not required. The changed behavior is a unit-testable function in packages/core fully covered by the focused Vitest run above, so no bundled-CLI integration test was needed.

中文说明

已处理的评审反馈

自动评审机器人提出的七条内联建议已全部实现。它们都使 OAuth 设备授权流程的 OSC 8 路径更接近参考实现 packages/cli/src/ui/utils/osc8.ts,其中一条(VTE 版本解析)修复了一个真实的终端检测缺陷。没有任何反馈被拒绝。

  • rc:3640199122 — 重复的清洗正则(已实现)。 抽取了一个模块内的 sanitizeForOsc() 辅助函数,并在 showFallbackMessageosc8Hyperlink 两处都调用它,使控制字符/bidi 剥离正则只存在于一个地方。osc8Hyperlink 仍然会对自己的输入做清洗(与参考实现一致),因此该函数单独调用时依然是安全的。

  • rc:3640199125 — 超长 URL 撑破边框(已实现)。 在 OSC 8 模式下,当验证 URL 长于默认内容宽度时,边框宽度现在会扩展到 url.length + 4,使单行可点击链接及其右侧 | 边框保持对齐,而不会溢出框外。URL 仍保持在单一可点击行上(即本 PR 针对的 SSH 复制粘贴场景),不会被降级为换行纯文本。

  • rc:3640199131 — VTE 检测缺陷 + 缺失测试(已实现)。 旧的 parseInt(VTE_VERSION) 检查会误读点分格式版本:0.60.0 被解析成 0,导致一个支持 OSC 8 的终端被拒绝。已替换为参考实现的 parseVersion() 启发式逻辑,它同时理解紧凑格式(50007800)和点分格式,同时仍然排除会段错误崩溃的 0.50.0。新增了四个测试:紧凑格式 5000(拒绝)、紧凑格式 7800(接受)、点分格式 0.60.0(接受——本可提前发现该缺陷)、点分格式 0.50.0(拒绝)。

  • rc:3640199135 — 无条件接受某些终端(已实现)。 iTerm.app、WezTerm 和 VS Code 现在通过共享的 parseVersion() 按版本进行门控,与参考实现一致(iTerm ≥ 3.1、WezTerm ≥ 20200620、VS Code ≥ 1.72),使得 OSC 8 之前的旧版本不会再收到原始转义字节。新增了 iTerm 3.0.10(拒绝)和 VS Code 1.71.0(拒绝)的测试。

  • rc:3640199139 — 缺少 URL 协议校验(已实现)。 新增了与参考实现一致的 isSafeOscScheme() 白名单(http:https:mailto:ftp:ftps:sftp:ssh:);只有白名单内的协议才会输出可点击的 OSC 8 包裹,否则 URL 回退为纯文本。新增了一个测试,断言 javascript: URL 不会被包裹。

  • rc:3640199145 — 缺少 win32 守卫(已实现)。 在最终的 fall-through 之前新增了 if (process.platform === 'win32') return false;,与参考实现一致,使得泄漏的环境变量(例如通过 SSH 带入 cmd.exe/conhost 的 TERM=alacritty)不会产生可见的乱码。Windows Terminal 仍会在前面通过 WT_SESSION 被匹配到。

  • rc:3640199152 — tmux 断言过弱(已实现)。 tmux DCS 透传测试现在断言精确的双 ESC 前缀 \x1bPtmux;\x1b\x1b]8;;,因此一旦 ESC 加倍逻辑(replaceAll('\x1b', '\x1b\x1b'))被移除,测试就会失败——此前的 toContain('\x1bPtmux;') 即便去掉加倍也仍会通过。

有三个既有的测试设置了 TERM_PROGRAM=iTerm.app 但未设置版本,现在补充了 TERM_PROGRAM_VERSION=3.5.0;在新的(与参考实现一致的)版本门控下,没有版本号的 iTerm 会被正确拒绝,因此这些测试需要一个真实的支持版本号,才能继续验证 OSC 8 路径。

冲突说明

--conflict false:未执行 origin/main 的合并;本分支可以干净地应用。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx eslint packages/core/src/qwen/qwenOAuth2.ts packages/core/src/qwen/qwenOAuth2.test.ts — 通过(无错误)
  • npx vitest run src/qwen/qwenOAuth2.test.ts -t "showFallbackMessage"(在 packages/core 中)— 29 个通过
  • npx vitest run src/qwen/qwenOAuth2.test.ts(在 packages/core 中)— 114 个通过,1 个失败:getQwenCachedCredentialPath > should return correct path to cached credentials。该失败是既有的、与本次改动无关——它在干净的代码树上同样会复现(已通过 git stash 验证),是本沙箱中 os.homedir() 路径不一致导致的环境相关问题;它断言的是凭据文件路径,与 OSC 8 工作毫无关联。

没有修改任何配置源(settings source),因此无需运行 npm run generate:settings-schema。改动的行为是 packages/core 中一个可单元测试的函数,已被上面的聚焦 Vitest 运行完全覆盖,因此无需打包后的 CLI 集成测试。

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-preview

@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. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Not reviewed: Agent 0: Issue fidelity & root-cause ownership, Agent 1a: Line-by-line correctness, Agent 2: Security, Agent 3: Code quality, Agent 4: Performance & efficiency, Agent 5: Test coverage, Agent 6a: Undirected audit — attacker mindset, Agent 6b: Undirected audit — 3 AM oncall mindset, Agent 6c: Undirected audit — six-months-later maintainer, Agent 1b: Removed-behavior audit, Agent 1c: Cross-file tracer, Agent 7: Build & test verification — its prompt was built, but no agent on record was launched with it. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.

— qwen3.7-max via Qwen Code /review

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

No action required

The latest review round on PR #6433 contains no actionable feedback:

  • The automated reviewer (@qwen-code-ci-bot) posted a COMMENTED review with 1 Suggestion-level finding that could not be anchored to a changed line and was dropped. The review explicitly states "nothing further to act on here."
  • No inline comments were left.
  • No issue-level comments were left.
  • No CI checks are failing or still-red.

No code changes are needed for this round.

中文说明

无需操作

PR #6433 的最新审查轮次中没有需要处理的反馈:

  • 自动审查器(@qwen-code-ci-bot)发布了一条 COMMENTED 审查,其中包含 1 条建议级别的发现,但因无法锚定到已更改的代码行而被丢弃。审查明确指出"此处无需进一步操作"。
  • 没有行内评论。
  • 没有 Issue 级别的评论。
  • 没有失败或持续失败的 CI 检查。

本轮无需进行任何代码更改。

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


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

Resolve conflict in favor of main's #7255, which already shipped the same
"emit OAuth login URL as a single OSC 8 hyperlink" feature using the shared
packages/core/src/utils/osc8.ts utilities (sanitizeForOsc, osc8Hyperlink,
supportsHyperlinks, wrapForMultiplexer). This PR's locally duplicated helpers
are a byte-for-byte subset of that shared module and even collided at the
identifier level (osc8Hyperlink both imported and redefined), so the
duplication is dropped and showFallbackMessage reverts to main's injectable-out
implementation. qwenOAuth2.ts and qwenOAuth2.test.ts now match origin/main.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Review feedback

No review feedback required action this round — feedback.md contained no
reviews, inline comments, issue-level comments, failed checks, or still-red
checks newer than the last evaluation. The only task was conflict resolution
(--conflict true).

Conflict resolution

Merged origin/main into fix/auth-url-osc8-hyperlink. The merge conflicted in
packages/core/src/qwen/qwenOAuth2.ts and packages/core/src/qwen/qwenOAuth2.test.ts.

Root cause of the conflict: while this PR (#6433) was open, main merged #7255
("emit OAuth login URL as a single OSC 8 hyperlink"), which independently
implemented the exact same feature this PR targets — and did so through the shared
packages/core/src/utils/osc8.ts utilities (sanitizeForOsc, osc8Hyperlink,
supportsHyperlinks, wrapForMultiplexer).

Understanding both sides:

  • main (feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255): showFallbackMessage(url, out = process.stderr) imports
    osc8Hyperlink / supportsHyperlinks from ../utils/osc8.js; the OSC 8 path is
    an early-return, non-box output; the ASCII box is only the fallback.
  • this PR: defined every OSC 8 helper locally inside qwenOAuth2.ts (duplicating
    the shared module — its own comments state it "mirrors" the CLI util) and used a
    box-with-OSC-8-inside variant writing directly to process.stderr.

The shared packages/core/src/utils/osc8.ts is a byte-for-byte superset of this
PR's local helpers (identical bidi sanitization, VTE packed-version parsing,
multiplexer DCS wrapping, and mintty/Konsole/Alacritty gating). Keeping both
produced a duplicate-identifier compile conflict (osc8Hyperlink was both imported
and redefined).

Resolution: adopted main's implementation wholesale for both files
(git checkout --theirs). The redundant local helpers are dropped, showFallbackMessage
reverts to main's injectable-out version, and the test file reverts to main's
HYPERLINK_ENV_KEYS-based block. Both files are now byte-identical to origin/main
(verified: git diff origin/main -- <files> is empty). No unique behavior was lost —
main's inline http / https scheme check is the correct guard for an OAuth
device-flow URL.

Net effect: git diff origin/main...HEAD is now empty — this PR is fully
superseded by main's #7255 and contributes no further changes. It can be closed as
superseded.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npx eslint packages/core/src/qwen/qwenOAuth2.ts packages/core/src/qwen/qwenOAuth2.test.ts — passed (exit 0)
  • npx vitest run src/qwen/qwenOAuth2.test.ts (in packages/core, QWEN_HOME unset) — 89/89 passed
  • npx vitest run src/qwen/qwenOAuth2.test.ts (in packages/core, sandbox QWEN_HOME set) — 88 passed, 1 pre-existing environment-specific failure (see note)

Note on the one failing test: clearQwenCredentials > should return correct path to cached credentials fails only because this sandbox sets
QWEN_HOME=/home/runner/work/_temp/qwen-autofix-review-home. The test computes its
expectation with os.homedir() (/home/runner/.qwen/...) while the implementation
honors QWEN_HOME. Both files are byte-identical to origin/main, so this failure
is pre-existing on the base branch and unrelated to the merge resolution; it passes
with QWEN_HOME unset (verified).

中文说明

评审反馈

本轮没有需要处理的评审反馈 —— feedback.md 中没有任何新于上次评估的评审、行内评论、
issue 级评论、失败检查或持续失败的检查。本轮唯一的任务是解决冲突(--conflict true)。

冲突解决

已将 origin/main 合并进 fix/auth-url-osc8-hyperlink。合并在
packages/core/src/qwen/qwenOAuth2.tspackages/core/src/qwen/qwenOAuth2.test.ts
两个文件中产生冲突。

冲突根因: 在本 PR(#6433)开放期间,main 合入了 #7255("emit OAuth login URL as a
single OSC 8 hyperlink"),它独立实现了本 PR 所要做的完全相同的功能 —— 并且是通过共享的
packages/core/src/utils/osc8.ts 工具函数(sanitizeForOscosc8Hyperlink
supportsHyperlinkswrapForMultiplexer)实现的。

对双方的理解:

  • main(feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255):showFallbackMessage(url, out = process.stderr)../utils/osc8.js
    导入 osc8Hyperlink / supportsHyperlinks;OSC 8 路径是一段提前返回的非边框输出;
    ASCII 边框仅作为回退方案。
  • 本 PR:在 qwenOAuth2.ts 内部本地定义了所有 OSC 8 辅助函数(重复实现了共享模块 ——
    其自身的注释也写明它 "mirrors"(镜像)CLI 工具函数),并使用了把 OSC 8 链接放在边框
    内部、直接写入 process.stderr 的变体。

共享的 packages/core/src/utils/osc8.ts 是本 PR 本地辅助函数的逐字节超集(bidi 净化、
VTE 打包版本解析、multiplexer DCS 包裹、以及 mintty/Konsole/Alacritty 门控完全一致)。
同时保留两者会产生重复标识符的编译冲突(osc8Hyperlink 既被导入又被重新定义)。

解决方案: 两个文件都整体采用 main 的实现(git checkout --theirs)。冗余的本地辅助
函数被移除,showFallbackMessage 回退到 main 的可注入 out 版本,测试文件回退到 main
基于 HYPERLINK_ENV_KEYS 的测试块。两个文件现在与 origin/main 逐字节一致(已验证:
git diff origin/main -- <files> 为空)。没有丢失任何独有行为 —— main 内联的
http / https 协议检查对于 OAuth device-flow URL 来说正是正确的防护。

最终效果: git diff origin/main...HEAD 现在为空 —— 本 PR 已被 main 的 #7255 完全
取代,不再贡献任何变更。可以将其作为"已被取代"关闭。

验证

  • npm run build —— 通过
  • npm run typecheck —— 通过
  • npx eslint packages/core/src/qwen/qwenOAuth2.ts packages/core/src/qwen/qwenOAuth2.test.ts —— 通过(退出码 0)
  • npx vitest run src/qwen/qwenOAuth2.test.ts(在 packages/core 中,未设置 QWEN_HOME)—— 89/89 通过
  • npx vitest run src/qwen/qwenOAuth2.test.ts(在 packages/core 中,设置了沙箱 QWEN_HOME)—— 88 通过,1 个预先存在的环境相关失败(见说明)

关于那一个失败测试的说明: clearQwenCredentials > should return correct path to cached credentials 失败仅仅是因为本沙箱设置了
QWEN_HOME=/home/runner/work/_temp/qwen-autofix-review-home。该测试用 os.homedir()
/home/runner/.qwen/...)计算期望路径,而实现遵循的是 QWEN_HOME。两个文件都与
origin/main 逐字节一致,因此这个失败在基础分支上就已存在,与本次合并解决无关;在未设置
QWEN_HOME 时它会通过(已验证)。

Base-conflict check · 基分支冲突检查: conflicted with main — resolved in this push. · 与 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-preview

@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. Not reviewed: coverage — the plan could not be used (coverage: /home/github-runner/actions-runner-test-1/_work/qwen-code/qwen-code/.qwen/tmp/qwen-review-pr-6433-fetch.json has no chunks[]), so this run cannot show that any of the diff was read. Not reviewed: verification — could not check that Step 4 and Step 5 ran (coverage: /home/github-runner/actions-runner-test-1/_work/qwen-code/qwen-code/.qwen/tmp/qwen-review-pr-6433-fetch.json has no chunks[]).

— qwen3.7-max via Qwen Code /review

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

No changes were made in response to this review round.

The only feedback is a COMMENTED review from the automated reviewer noting it could not complete its coverage or verification analysis due to an infrastructure issue (the review plan fetch returned no chunks). It raised no code findings, and the review status is not CHANGES_REQUESTED.

There are no inline comments, no issue-level comments, no failed checks, and no still-red checks to address.

Additionally, the branch's three-dot diff against main is empty: the latest merge commit (f84f65ab9) resolved all conflicts in favor of main's #7255, which already shipped the same OSC 8 hyperlink feature using shared packages/core/src/utils/osc8.ts utilities. This PR's locally duplicated helpers were a byte-for-byte subset of that shared module, so the merge dropped them entirely. There is no remaining unique code on this branch to review or fix.

中文说明

本轮审查未做任何修改。

唯一的反馈是自动审查机器人的一条 COMMENTED 评论,指出由于基础设施问题(审查计划获取未返回任何代码块),它无法完成覆盖率或验证分析。该评论未提出任何代码问题,审查状态也不是 CHANGES_REQUESTED

没有行内评论、没有 issue 级别的评论、没有失败的检查项、也没有持续失败的检查项需要处理。

此外,该分支相对于 main 的三点 diff 为空:最新的合并提交(f84f65ab9)已将所有冲突以 main 的 #7255 为准解决,而 #7255 已经使用共享的 packages/core/src/utils/osc8.ts 工具模块发布了相同的 OSC 8 超链接功能。本 PR 本地重复实现的辅助函数是该共享模块的逐字节子集,因此合并时已将其全部移除。该分支上已无剩余的独特代码可供审查或修复。

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


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

@wenshao

wenshao commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Local verification report — merge reference

Maintainer request: build real tests locally and verify this PR. Everything below was run on macOS 24.6.0 / Node v22.23.1, against this PR's head f84f65a and origin/main ebf8f75. Assets: pr-assets/6433-verify.

Verdict: do not merge — this branch is now empty. Close it, and land the salvage test file below instead.

This is not a criticism of the work. The feature this PR set out to build shipped and works. It just shipped through #7255, and this branch's own commits were then discarded by its last merge.


1. The branch has a zero-byte diff

$ gh api repos/QwenLM/qwen-code/pulls/6433 --jq '{additions,deletions,changed_files}'
{"additions":0,"deletions":0,"changed_files":0}

$ git rev-parse f84f65a^{tree}      # PR head
c221d2e1bfb7b11687e40b13b17dad92751655e3
$ git rev-parse 45c8d8f^{tree}      # merge base
c221d2e1bfb7b11687e40b13b17dad92751655e3   # ← identical

$ git diff 45c8d8f f84f65a | wc -c
0

The cause is the last commit on the branch, f84f65a, whose own message states it:

Resolve conflict in favor of main's #7255qwenOAuth2.ts and qwenOAuth2.test.ts now match origin/main.

That merge reverted the branch's 12 commits of work to main's content. Merging this PR today would add a merge commit and change no files.

2. The feature works on main — verified on a real pty

Not a mock: showFallbackMessage was driven under script -q /dev/null, so stderr is a kernel pty and the isTTY probe inside supportsHyperlinks() is answered by the OS. The bytes below are the exact bytes written, replayed through xterm.js.

profile OSC 8 emitted bytes
TERM=xterm-kitty yes 453
TERM_PROGRAM=iTerm.app 3.4.7 yes 453
TERM_PROGRAM=vscode 1.85.0 yes 453
TERM=xterm-256color no (ASCII box) 800
TERM_PROGRAM=Apple_Terminal no (ASCII box) 800
CI=1 / NO_COLOR=1 / QWEN_DISABLE_HYPERLINKS=1 / TMUX no 800
TMUX + FORCE_HYPERLINK=1 yes, DCS-wrapped 464
redirected to a file (no pty) no escapes in the file

Before — terminal without OSC 8 support. The URL is hard-wrapped across lines. This is the #6428 complaint, and it remains the correct fallback here.

plain terminal

After — terminal with OSC 8 support. One hyperlink. It still visually wraps at the 80-column edge, but it is a single clickable/copyable unit.

osc8 terminal

Refusal paths. No escape bytes emitted.

refusals

3. Was anything of value lost in the merge? Three separate answers

3a. Implementation — nothing lost. The merge commit's claim checks out.

f84f65a justified itself by calling this PR's helpers "a byte-for-byte subset" of main's shared module. I tested that rather than taking it on faith: both implementations were sliced verbatim out of their commits and run side by side in one process.

=== A: curated terminal profiles (x2 for isTTY) ===       80 states
=== B: randomized env fuzz over all 21 detector keys ===   50000 states
=== C: emitter + sanitizer over URL corpus ===             84 comparisons
TOTAL comparisons: 50164
DIVERGENCES: 0

Positive controls confirm the harness is live, not vacuously green — mutating main's copy produces divergences immediately:

control mutation divergences
mintty gate 3.34.0 1 (mintty 3.4)
VTE packed-integer unpack disabled 2 (VTE 5000, VTE 4900)
bidi range dropped from sanitizeForOsc 6
(restored) 0

So the detector, emitter and sanitizer really were equivalent. The merge lost no detection behaviour.

3b. Tests — this is the real loss. 26 tests, over logic that ships untested.

The reverted qwenOAuth2.test.ts had 29 showFallbackMessage cases. Main has 3, plus 13 primitive tests in osc8.test.ts.

The implementation on main covers mintty version gates, VTE packed-integer parsing, iTerm2 ≥ 3.1, VS Code ≥ 1.72, Konsole, Alacritty, JetBrains, Ghostty, DomTerm, TeamCity, the FORCE_HYPERLINK contract and the scheme allowlist. Nothing on main asserts any of it. 28 mutants against main's suites:

=== SUMMARY: 7 killed, 21 SURVIVED (of 28) ===

Every survivor is live shipped logic that no test would notice breaking — including M03 VTE packed-integer unpack disabled and M04 VTE 0.50.0 segfault guard removed, i.e. exactly the "fix VTE parsing" work this branch's last commit was named after. (VTE 0.50.0 advertises OSC 8 and then segfaults; nothing on main stops us from emitting to it.)

I wrote the replacement. osc8.matrix.test.ts — 66 tests, a 52-row terminal matrix, Prettier- and ESLint-clean, green on unmodified main. Re-running the same 28 mutants with it added:

=== SUMMARY: 27 killed, 1 SURVIVED (of 28) ===
  SURVIVED: M02 mintty missing-version refusal removed

That single survivor is a provably equivalent mutant: if (!env['TERM_PROGRAM_VERSION']) return false; never changes the verdict, because parseVersion(undefined) yields 0.0.0 and the >= 3.3 comparison already refuses it. Verified across undefined, '', '0', '2.7', '3.0', '3.3', '4.0', 'abc', … — no input where the guard matters. So 27/27 non-equivalent mutants die.

3c. Behaviour — one genuine gap survived into main.

This branch sanitized the URL once, up front, so both render paths were covered:

const url = sanitizeForOsc(verificationUriComplete);   // this PR
const url = verificationUriComplete;                   // main, qwenOAuth2.ts:723

On main only osc8Hyperlink() sanitizes. The ASCII-box path — the one every non-OSC-8 terminal takes — writes verification_uri_complete raw. Confirmed against the real unmodified module, with the value travelling the genuine wire path (HTTP response → requestDeviceAuthorization() → deviceAuth → showFallbackMessage, qwenOAuth2.ts:893):

### LEVEL 1 — real showFallbackMessage(), poisoned URLs
clean  title-setting OSC  | OSC 8 terminal (kitty) | leaked=[none]
LEAK   title-setting OSC  | plain terminal         | leaked=[C0/DEL U+001b, C0/DEL U+0007]
clean  RLO label spoof    | OSC 8 terminal (kitty) | leaked=[none]
LEAK   RLO label spoof    | plain terminal         | leaked=[BIDI/SEP U+202e, BIDI/SEP U+202c]
LEAK   C1 8-bit OSC       | plain terminal         | leaked=[C1 U+009d, C1 U+009c]
LEAK   CR overwrite       | plain terminal         | leaked=[C0/DEL U+000d]

### LEVEL 2 — value travels the real wire path
server-supplied verification_uri_complete round-tripped intact: true
escape reaches the terminal on the ASCII-box path: true

An ESC ]0; … BEL in the URL is executed — note the hijacked title bar:

title hijack

A bare CR rewinds the cursor, so the box displays a host that is not the real URL. The user copies what they see:

cr overwrite

Severity: low, and I want to be straight about why. The input is verification_uri_complete from Qwen's own OAuth endpoint over TLS, so reaching this needs a compromised or MITM'd auth server — at which point you have larger problems. It is defence-in-depth, not a live exploit. It is worth fixing anyway because main's own sanitizeForOsc docstring already states the intent ("stripping bidi controls guards the visible label from … click-deception"); the box path simply never calls it. The fix is one line at the call site plus the import:

-  const url = verificationUriComplete;
+  const url = sanitizeForOsc(verificationUriComplete);

I applied it and re-ran: all 8 leaking states go clean (LEVEL 1 leaking states: 0/8), and all 168 tests still pass.

Two other deltas I checked and judged not worth carrying back — main is fine or better:

  • Scheme allowlist. This PR allowed ftp/ftps/sftp/ssh/mailto to become clickable; main allows only http/https. Main is stricter. Keep main's.
  • Box layout. This PR kept the URL inside a widened box. Measured on a realistic 147-character auth URL, that box's borders come out 151 columns wide, so the frame itself wraps on an 80-column terminal — worse than the problem being fixed. Main drops the box in OSC 8 mode (widest line 147, and it is one hyperlink, so wrapping is harmless). Keep main's.

4. Test suites

$ cd packages/core && npx vitest run src/utils/osc8.test.ts src/qwen/qwenOAuth2.test.ts
  Test Files  2 passed (2)
       Tests  102 passed (102)

$ npx vitest run src/utils/osc8.matrix.test.ts      # proposed addition
  Test Files  1 passed (1)
       Tests  66 passed (66)

5. Recommendation

  1. Close fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433 as superseded by feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255. Merging it changes nothing, and leaving it open keeps the autofix loop spending rounds on an empty branch (it has run 5 and is at round 5/100).
  2. Land osc8.matrix.test.ts as packages/core/src/utils/osc8.matrix.test.ts. This is the salvageable value in this PR, and it takes main's OSC 8 mutation score from 7/28 to 27/27.
  3. Optionally apply the one-line sanitizeForOsc fix in 3c (verified above: closes all 8 leaks, 168/168 still green).
  4. Credit @DennisYu07 on the follow-up. For the record: fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433 opened 2026-07-07 and feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255 opened 2026-07-19; feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255's description references Emit auth login URLs as single OSC 8 hyperlinks instead of hard-wrapping across multiple lines #6428 but not fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433. Whether that was independent work or not, this branch raised and first implemented the fix, and the test matrix in 3b is its work.

6. Reproducing

git fetch origin pull/6433/head:pr6433-head
git diff $(git merge-base pr6433-head origin/main) pr6433-head | wc -c    # 0

git worktree add --detach /tmp/wt6433 pr6433-head
cd /tmp/wt6433/packages/core
npx vitest run src/utils/osc8.test.ts src/qwen/qwenOAuth2.test.ts         # 102 pass

# real-pty capture (macOS/Linux)
env -u CI -u NO_COLOR TERM=xterm-kitty script -q /dev/null \
  npx tsx -e "import {showFallbackMessage} from './src/qwen/qwenOAuth2.js'; \
              showFallbackMessage('https://chat.qwen.ai/device?code=A')" | xxd | grep '1b5d 383b'
中文说明

本地验证报告 — 合并参考

维护者要求本地构建真实测试验证此 PR。以下全部在 macOS 24.6.0 / Node v22.23.1 上运行,针对本 PR head f84f65aorigin/main ebf8f75。资源分支:pr-assets/6433-verify

结论:不建议合并 —— 此分支现在是空的。 建议关闭,改为合入下面的补救测试文件。

这不是对作者工作的否定。此 PR 想做的功能已经上线并且工作正常,只是通过 #7255 上线的,而本分支自己的提交随后被它最后一次 merge 丢弃了。

1. 分支 diff 为零字节

gh api 报告 additions/deletions/changed_files 全为 0;PR head f84f65a 与 merge base 45c8d8f 的 tree 哈希完全相同(c221d2e…),git diff 输出 0 字节。

原因是分支最后一个提交 f84f65a,其提交信息自述:「Resolve conflict in favor of main's #7255 …… qwenOAuth2.tsqwenOAuth2.test.ts 现与 origin/main 一致」。该 merge 把分支 12 个提交的工作回退成了 main 的内容。今天合并此 PR 只会增加一个 merge commit,不改变任何文件。

2. 功能在 main 上正常 —— 已用真实 pty 验证

不是 mock:showFallbackMessagescript -q /dev/null 下运行,stderr 是真实的内核 pty,supportsHyperlinks() 里的 isTTY 探测由操作系统回答。截图中的字节就是实际写出的字节,经 xterm.js 回放。

支持 OSC 8 的终端(kitty / iTerm2 3.4.7 / VS Code 1.85)输出超链接(453 字节);xterm-256color、Apple Terminal 走 ASCII 框(800 字节);CI / NO_COLOR / QWEN_DISABLE_HYPERLINKS / TMUX 一律拒绝;TMUX + FORCE_HYPERLINK=1 输出并带 DCS 包裹(464 字节);重定向到文件时文件中没有任何转义字节

3. merge 是否丢失了有价值的东西?三个独立答案

3a. 实现 —— 没有丢失,merge commit 的说法属实。

f84f65a 自称本 PR 的辅助函数是 main 共享模块的「逐字节子集」。我没有直接采信,而是把两份实现从各自 commit 中原样切片,在同一进程里并排运行:50164 次比较,0 处分歧。阳性对照证明该测试并非空转——改动 main 的副本会立刻产生分歧(mintty 门槛 3.34.0 产生 1 处;禁用 VTE 打包整数解析产生 2 处;去掉 bidi 范围产生 6 处;还原后回到 0)。所以检测器、发射器、消毒函数确实等价,merge 没有丢失任何检测行为。

3b. 测试 —— 这才是真正的损失:26 个测试,覆盖的是已上线但无人测试的逻辑。

被回退的 qwenOAuth2.test.ts29showFallbackMessage 用例;main 只有 3 个,加上 osc8.test.ts 的 13 个基础用例。

main 的实现覆盖了 mintty 版本门槛、VTE 打包整数解析、iTerm2 ≥ 3.1、VS Code ≥ 1.72、Konsole、Alacritty、JetBrains、Ghostty、DomTerm、TeamCity、FORCE_HYPERLINK 契约和 scheme 白名单,但 main 上没有任何测试断言这些。针对 main 测试套件的 28 个变异体:7 个被杀,21 个存活。每个存活者都是坏掉也没有测试会发现的线上逻辑——其中就包括 M03 禁用 VTE 打包整数解析M04 移除 VTE 0.50.0 段错误防护,正是本分支最后一个提交名字里的「fix VTE parsing」。(VTE 0.50.0 声称支持 OSC 8 然后会段错误,而 main 上没有任何测试阻止我们向它发送转义。)

我已经写好了替代品osc8.matrix.test.ts —— 66 个测试,52 行终端矩阵,Prettier 与 ESLint 均通过,在未修改的 main 上全绿。加上它后重跑同样 28 个变异体:27 个被杀,1 个存活

那个唯一的存活者是可证明的等价变异体if (!env['TERM_PROGRAM_VERSION']) return false; 永远不改变结论,因为 parseVersion(undefined) 得到 0.0.0,而 >= 3.3 的比较本身就已经拒绝它。已在 undefined, '', '0', '2.7', '3.0', '3.3', '4.0', 'abc' … 上验证,不存在该防护起作用的输入。所以27/27 个非等价变异体全部被杀

3c. 行为 —— 有一个真实缺口留在了 main 上。

本分支在前面统一消毒一次,因此两条渲染路径都被覆盖:const url = sanitizeForOsc(verificationUriComplete);;而 main 是 const url = verificationUriComplete;qwenOAuth2.ts:723)。

main 上只有 osc8Hyperlink() 做消毒。ASCII 框路径——所有不支持 OSC 8 的终端走的那条——原样写出 verification_uri_complete。已针对真实未修改模块确认,且该值走的是真实链路(HTTP 响应 → requestDeviceAuthorization() → deviceAuth → showFallbackMessageqwenOAuth2.ts:893):URL 中的 ESC ]0; … BEL 会被执行(截图中标题栏被劫持);裸 CR 会回退光标,使框内显示的主机名与真实 URL 不同,而用户复制的正是他所看到的内容。C1(U+009D/U+009C)与 bidi(U+202E)同样泄漏。

严重性:低,我想说清楚原因。 输入来自 Qwen 自己的 OAuth 端点,经 TLS 传输,因此触发它需要认证服务器被攻陷或被中间人劫持——真到那一步,问题已经比这大得多。这属于纵深防御,而非可用漏洞。但仍值得修,因为 main 自己 sanitizeForOsc 的文档注释已经写明了意图(「剥离 bidi 控制符可保护可见标签免受点击欺骗」),只是框路径从未调用它。改动为调用处一行加一个 import:const url = sanitizeForOsc(verificationUriComplete);

我已实际应用该修复并重跑:8 个泄漏状态全部变为 clean(LEVEL 1 leaking states: 0/8),且 168 个测试仍全部通过。

另外两处差异我检查后判断不值得带回,main 更好或持平:

  • scheme 白名单:本 PR 允许 ftp/ftps/sftp/ssh/mailto 变成可点击链接,main 只允许 http/https。main 更严格,保留 main 的。
  • 框体布局:本 PR 把 URL 留在加宽的框内。以一个真实的 147 字符认证 URL 实测,框的边框宽达 151 列,于是边框本身在 80 列终端上换行——比它要修的问题更糟。main 在 OSC 8 模式下直接去掉框(最宽行 147,且是单个超链接,换行无害)。保留 main 的。

4. 测试套件

packages/core 现有套件:102 passed。建议新增的矩阵文件:66 passed

5. 建议

  1. 关闭 fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433,标记为被 feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255 取代。合并它不改变任何东西,而继续开着会让 autofix 循环持续在一个空分支上消耗轮次(已跑 5 轮,当前 5/100)。
  2. 合入 osc8.matrix.test.tspackages/core/src/utils/osc8.matrix.test.ts。这是本 PR 中真正可挽救的价值,能把 main 的 OSC 8 变异得分从 7/28 提到 27/27。
  3. 可选:应用 3c 中的一行 sanitizeForOsc 修复(上文已验证:8 处泄漏全部消除,168/168 仍全绿)。
  4. 后续 PR 中请给 @DennisYu07 署名。事实记录:fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433 开于 2026-07-07feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255 开于 2026-07-19feat(core): emit OAuth login URL as a single OSC 8 hyperlink #7255 的描述引用了 Emit auth login URLs as single OSC 8 hyperlinks instead of hard-wrapping across multiple lines #6428,但没有引用 fix(core): emit auth URL as OSC 8 hyperlink instead of hard-wrapping #6433。无论是否为独立工作,本分支率先提出并实现了该修复,3b 中的测试矩阵也是它的成果。

Verified locally at head f84f65a against origin/main ebf8f75 · harnesses: 50,164-state implementation differential, 28-mutant matrix ×2, real-pty capture ×14, xterm.js render · assets on pr-assets/6433-verify

@qwen-code-dev-bot

qwen-code-dev-bot commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

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

中文说明

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

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

Autofix review response — no code change this round

I verified the maintainer's report against the checkout and made no code change. The branch is empty, and the requested disposition (close this PR) is a maintainer action outside this bot's scope.

Verified findings

The central claim checks out — this branch has a zero-byte diff against origin/main:

$ git diff origin/main...HEAD | wc -c
0
$ git rev-parse HEAD^{tree}
c221d2e1bfb7b11687e40b13b17dad92751655e3
$ git rev-parse $(git merge-base origin/main HEAD)^{tree}
c221d2e1bfb7b11687e40b13b17dad92751655e3   # identical tree

Merging this PR would add a merge commit and change no files. I also confirmed the supporting facts: qwenOAuth2.ts:723 is const url = verificationUriComplete; (the raw ASCII-box path from finding 3c), sanitizeForOsc is exported from osc8.ts, and osc8.matrix.test.ts does not exist on this branch or main.

Classification of each recommendation

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


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

@github-actions github-actions Bot added the review/self-reported The linked issue was opened by the PR author (self-reported) label Jul 26, 2026
@wenshao wenshao closed this Jul 26, 2026
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+) category/authentication Authentication and authorization priority/P3 Low - Minor, cosmetic, nice-to-fix issues review/self-reported The linked issue was opened by the PR author (self-reported) scope/oauth OAuth authentication flows type/feature-request New feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emit auth login URLs as single OSC 8 hyperlinks instead of hard-wrapping across multiple lines

4 participants