Skip to content

fix(desktop): strip Windows verbatim prefix from runtime spawn paths - #8936

Merged
yiliang114 merged 1 commit into
mainfrom
fix/desktop-runtime-verbatim-paths
Aug 11, 2026
Merged

fix(desktop): strip Windows verbatim prefix from runtime spawn paths#8936
yiliang114 merged 1 commit into
mainfrom
fix/desktop-runtime-verbatim-paths

Conversation

@yiliang114

Copy link
Copy Markdown
Collaborator

What this PR does

When the desktop shell spawns the bundled Node runtime on Windows, it now strips the \\?\ extended-length ("verbatim") prefix from the Node executable path and the CLI entry-script path before handing them to the spawn. The workspace path was already covered by #8619; this closes the same class of bug for the remaining two spawn arguments. A Windows-gated regression test asserts neither runtime spawn path keeps the prefix.

Why it's needed

Fixes #8929. On Windows, Tauri's resource-directory resolution returns verbatim \\?\ paths, and the launcher passed them through to the spawn unchanged. Node's entry-script resolution (resolveMainPathrealpathSync) cannot handle that prefix and dies with EISDIR: lstat 'C:' before the daemon prints its listening URL — the app cannot start at all, regardless of which workspace is chosen. The reporter captured the actual spawn command via WMI and showed the prefix on the program path, the entry-script path, and the workspace value; the first two are what trigger the crash, so the workspace fix from #8619 alone is not sufficient. The reporter's workaround — pointing the runtime-directory environment variable at a plain path — confirms the runtime paths as the cause.

Reviewer Test Plan

How to verify

  • cargo test --manifest-path src-tauri/Cargo.toml in packages/desktop-shell passes (37 tests locally on macOS); the new Windows-gated test runs on the windows-2022 leg of the desktop_shell CI job.
  • On a packaged Windows build: start the app and confirm the runtime comes up; the spawned command line no longer contains \\?\ for the Node executable or the entry script.

Evidence (Before & After)

N/A — startup-crash fix in the Tauri launcher; no UI change. Before: "Bundled runtime closed stdout before reporting its listening URL" with an EISDIR stack on every start attempt (see #8929). After: runtime starts as it does with the reporter's plain-path workaround.

Tested on

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

Environment (optional)

cargo test / cargo clippy --tests on the desktop crate; no bundled runtime needed.

Risk & Scope

  • Main risk or tradeoff: dunce::simplified keeps the verbatim form when a simplified path would be unsafe (e.g. over 260 characters), so in that edge case behavior is unchanged from today rather than broken.
  • Not validated / out of scope: end-to-end startup on a packaged Windows build — the Windows CI test covers the path logic; a release build should be smoke-tested before the next Desktop release.
  • Breaking changes / migration notes: none.

Linked Issues

Fixes #8929. Related: #8615 / #8619 (workspace-path half of the same verbatim-path bug class).

中文说明

这个 PR 做了什么

桌面端外壳在 Windows 上拉起内置 Node 运行时之前,现在会先剥离 Node 可执行文件路径和 CLI 入口脚本路径上的 \\?\ 扩展长度("verbatim")前缀。workspace 路径此前已由 #8619 覆盖;本 PR 补齐了剩余两个 spawn 参数上的同类问题。并新增了一个仅在 Windows 上运行的回归测试,断言两个运行时 spawn 路径都不再保留该前缀。

为什么需要

修复 #8929。在 Windows 上,Tauri 的资源目录解析返回 verbatim \\?\ 路径,而启动器原样将其传给了 spawn。Node 的入口脚本解析(resolveMainPathrealpathSync)无法处理该前缀,会在守护进程打印监听 URL 之前以 EISDIR: lstat 'C:' 崩溃 —— 无论选择哪个 workspace,应用都完全无法启动。报告者通过 WMI 抓到了真实的 spawn 命令,显示程序路径、入口脚本路径和 workspace 值上都带有该前缀;其中前两个才是触发崩溃的原因,因此仅有 #8619 的 workspace 修复并不够。报告者的临时方案 —— 将运行时目录环境变量指向普通路径 —— 也印证了运行时路径正是问题根源。

评审者测试计划

如何验证

  • packages/desktop-shell 下运行 cargo test --manifest-path src-tauri/Cargo.toml 通过(本地 macOS 37 个测试全过);新增的 Windows 门控测试会在 desktop_shell CI 任务的 windows-2022 分支上运行。
  • 在打包后的 Windows 构建上:启动应用并确认运行时正常拉起;spawn 出的命令行中 Node 可执行文件和入口脚本不再包含 \\?\

证据(前后对比)

N/A —— Tauri 启动器中的启动崩溃修复,无 UI 变化。修复前:每次启动都报 "Bundled runtime closed stdout before reporting its listening URL" 并附 EISDIR 堆栈(见 #8929)。修复后:运行时如报告者用普通路径 workaround 时一样正常启动。

测试平台

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

环境(可选)

对桌面 crate 运行 cargo test / cargo clippy --tests;不需要内置运行时。

风险与范围

  • 主要风险或权衡:当简化后的路径不安全时(例如超过 260 字符),dunce::simplified 会保留 verbatim 形式,因此该边缘情况下行为与现状一致,而不会被改坏。
  • 未验证 / 超出范围:打包后 Windows 构建的端到端启动 —— Windows CI 测试覆盖了路径逻辑;下一个 Desktop 版本发布前应对 release 构建做一次冒烟测试。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

修复 #8929。相关:#8615 / #8619(同一 verbatim 路径问题中 workspace 路径的那一半)。

Tauri's resource_dir() returns \\?\ verbatim paths on Windows, so the
bundled Node executable and the cli-entry.js argument were spawned with
that prefix. Node's entry-script resolution cannot handle it and dies
with EISDIR before the daemon reports its listening URL, making the app
unstartable regardless of workspace. Simplify both paths with dunce
before spawning, complementing the workspace-path fix from #8615.

Fixes #8929
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

⚠️ Deferred approval withheld — 1 PR CI workflow run(s) on cc74ccf did not finish green; see the updated table in the Stage 2 comment. Re-run @qwen-code /triage after fixes. finalize run

⚠️ 延迟审批已搁置 —— cc74ccf 有 1 个 PR CI workflow 未以绿色完成,详见 Stage 2 评论中已更新的表格。修复后可重新运行 @qwen-code /triage查看 finalize 运行

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed, not theoretical. #8929 is a P1 startup crash — Windows Desktop 0.1.0 cannot start at all, dying with EISDIR: lstat 'C:' before the daemon prints its listening URL. The reporter captured the actual spawn command line via WMI (verbatim \\?\ prefix on the program path and the entry-script path), reproduced the failure standalone with fs.realpathSync on the bundled Node, and showed the app starts when plain paths are supplied via QWEN_DESKTOP_RUNTIME_DIR. That workaround pins the cause to exactly the two paths this PR strips.

Direction: aligned — a desktop app that doesn't launch on Windows is about as core as it gets. No related claude-code CHANGELOG entry, but this is a launcher bug specific to our Tauri desktop shell.

Size: not applicable — packages/desktop-shell/src-tauri/** is not a core-module path; one file, 34 additions / 6 deletions.

Approach: minimal, and the fix the issue itself suggests. Path construction for node/entry is extracted into layout_from_root, both results run through dunce::simplified, and a Windows-gated regression test is added. All three root sources (env override, debug build, packaged resource_dir) flow through it, and with the workspace path already covered by #8619 this closes the remaining spawn arguments. Reuses the existing dunce dependency rather than hand-rolling prefix stripping. Nothing extra in the diff.

Risk: no elevated risk signals (no revert-correlated path matches). One edge the PR itself calls out: when stripping would be unsafe (>260 chars, trailing dot/space) dunce::simplified keeps the verbatim form — behavior in that case is unchanged from today, not worse.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的真实 bug,而非理论问题。#8929 是 P1 启动崩溃——Windows 桌面端 0.1.0 完全无法启动,在守护进程打印监听 URL 之前就以 EISDIR: lstat 'C:' 崩溃。报告者通过 WMI 抓到了真实的 spawn 命令行(程序路径和入口脚本路径均带 \\?\ verbatim 前缀),用内置 Node 单独复现了 fs.realpathSync 的失败,并验证了通过 QWEN_DESKTOP_RUNTIME_DIR 提供普通路径后应用即可启动。该 workaround 恰好把根因锁定在本 PR 剥离前缀的两个路径上。

方向:对齐——桌面端在 Windows 上无法启动是最核心的问题。claude-code CHANGELOG 无相关条目,但这是我们 Tauri 桌面外壳特有的启动器 bug。

规模:不适用——packages/desktop-shell/src-tauri/** 不属于核心模块路径;单文件,+34/−6。

方案:最小改动,正是 issue 建议的修法。node/entry 路径构造提取为 layout_from_root,两者均经过 dunce::simplified,并新增仅 Windows 运行的回归测试。三个 root 来源(环境变量覆盖、调试构建、打包后的 resource_dir)都会经过它;workspace 路径已由 #8619 覆盖,本 PR 补齐其余 spawn 参数。复用已有 dunce 依赖而非手写前缀剥离。diff 无多余改动。

风险:无升级风险信号(未命中 revert 相关路径)。PR 已自述一个边缘情况:当剥离不安全时(超 260 字符、结尾点/空格),dunce::simplified 保留 verbatim 形式——此时行为与现状一致,不会更糟。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

Independent take before reading the diff: for "Tauri hands us \\?\ paths and Node's entry resolution chokes", I'd normalize the two spawn args with dunce::simplified (syntactic, no filesystem access, keeps the verbatim form where stripping would be unsafe) and add a Windows-gated test. That is exactly what this PR does, so the approach matches my baseline.

Reading the diff against the base code, nothing blocking:

  • Coverage is complete: DesktopRuntime::start is the only consumer of RuntimeLayout, and all three root sources (QWEN_DESKTOP_RUNTIME_DIR override, debug build, packaged resource_dir) now flow through layout_from_root, so both spawn args are simplified on every path. The env path always arrived plain — that's why the reporter's workaround worked — and dunce::simplified is a no-op there.
  • simplified over canonicalize is the right call here: the layout is existence-checked right after via require_file, so no extra filesystem round-trip and no new failure mode; it also mirrors the dunce usage fix(desktop): strip Windows verbatim prefix from workspace paths #8619 introduced for the workspace path.
  • The regression test feeds a realistic \\?\C:\… root through the helper and asserts both outputs drop the prefix — the fix's actual mechanism, exercised on a real Windows runner by the desktop CI leg.
  • The residual edge — an install path where stripping would be unsafe (>260 chars, trailing dot/space) keeps the verbatim form and fails as it does today — is the right tradeoff (hard-stripping would be wrong there) and is documented in Risk & Scope.

No correctness, security, or convention issues found.

Testing

Unattended CI run — no PR code was built or executed here; the evidence below is the PR's own CI on the reviewed commit. The load-bearing job is green: Desktop Shell (windows-2022) compiles the Windows branch and runs the new runtime_layout_strips_windows_verbatim_prefix test on a real Windows runner, and Desktop Shell (ubuntu-22.04) covers the unchanged non-Windows path. The macOS/Windows Node suites show skipped by path filtering (this PR touches only the Rust desktop crate); the still-running Test (ubuntu-latest, Node 22.x) does not exercise this crate but counts for the green-CI gate. No failing checks.

Final CI results for cc74ccf (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Test (ubuntu-latest, Node 22.x) ❌ failure
Classify PR ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

What CI cannot settle: end-to-end startup of a packaged Windows build — the author flags this too. Neither sandbox lane applies here: @qwen-code /verify runs on Linux, where dunce::simplified is a no-op, so an A/B harness cannot observe the Windows behavior; @qwen-code /tmux drives the CLI's TUI, not the Tauri launcher. The actionable follow-up is the one the PR itself names: smoke-test a release build on Windows before the next Desktop release. Note the reporter's workaround (plain paths → app starts) is strong observed evidence that the causal chain holds — this PR mechanizes that workaround.

中文说明

代码审查

读 diff 前先给出独立方案:针对 "Tauri 给出 \\?\ 路径、Node 入口解析无法处理",我会用 dunce::simplified(纯语法处理、不访问文件系统、剥离不安全时保留 verbatim 形式)规范化两个 spawn 参数,并新增 Windows 门控测试。PR 的做法与此完全一致。

对照基础代码审查 diff,无阻塞问题:

  • 覆盖完整:DesktopRuntime::startRuntimeLayout 的唯一消费者,三个 root 来源(QWEN_DESKTOP_RUNTIME_DIR 覆盖、调试构建、打包后的 resource_dir)现在都经过 layout_from_root,每条路径上两个 spawn 参数都会被简化。env 路径本来就是普通路径(这正是报告者 workaround 生效的原因),dunce::simplified 对它是无操作。
  • 这里选 simplified 而非 canonicalize 是对的:layout 随后由 require_file 做存在性检查,不额外访问文件系统、不引入新的失败模式;也与 fix(desktop): strip Windows verbatim prefix from workspace paths #8619 为 workspace 路径引入的 dunce 用法保持一致。
  • 回归测试用真实的 \\?\C:\… root 走一遍该 helper,断言两个输出都不再带前缀——修复机制本身在桌面 CI 的真实 Windows runner 上得到验证。
  • 残留边缘情况——剥离不安全的安装路径(超 260 字符、结尾点/空格)会保留 verbatim 形式、维持现状的失败——是正确取舍(硬剥离在那里才是错的),且已在 Risk & Scope 中说明。

未发现正确性、安全性或规范问题。

测试

无人值守 CI 运行——此处未构建或执行任何 PR 代码;以下证据来自 PR 自身在受审 commit 上的 CI。关键任务已绿:Desktop Shell (windows-2022) 编译 Windows 分支并在真实 Windows runner 上运行新增的 runtime_layout_strips_windows_verbatim_prefix 测试;Desktop Shell (ubuntu-22.04) 覆盖未改动的非 Windows 路径。macOS/Windows 的 Node 套件因路径过滤显示 skipped(本 PR 只改 Rust 桌面 crate);仍在运行的 Test (ubuntu-latest, Node 22.x) 不涉及本 crate,但计入 CI 全绿门槛。无失败检查。

(上方 CI 表格在 CI 结束后由 finalize 流程原地更新。)

CI 无法定论的一点:打包后 Windows 构建的端到端启动——作者也已注明。两个沙箱通道在此均不适用:@qwen-code /verify 在 Linux 上运行,dunce::simplified 在非 Windows 平台是无操作,A/B 无法观测 Windows 行为;@qwen-code /tmux 驱动的是 CLI 的 TUI,而非 Tauri 启动器。可执行的后续动作正是 PR 自己写明的:下一个 Desktop 版本发布前,对 Windows release 构建做冒烟测试。报告者的 workaround(普通路径 → 应用正常启动)为该因果链提供了有力的观测证据——本 PR 正是把这个 workaround 机制化。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — a fully-evidenced P1 startup-crash fix, and the change is exactly the minimal mechanism the evidence points to.

Stepping back: the problem is as well-evidenced as a gate could ask — a captured spawn command line, a standalone reproduction of the Node failure, and a workaround that proves the causal chain. The PR mechanizes that workaround for the two remaining spawn arguments; the approach matches the one I proposed independently before reading the diff; and nothing in the diff goes beyond what the goal needs. The test pins the fix's actual mechanism and passed on a real Windows runner. The one unverified piece — packaged Windows build startup — is inherently a release-time smoke test (no bot lane can execute it), and the PR says so itself. Six months from now, maintaining this: a small, commented helper with a spelled-out edge-case tradeoff — thank them, not curse them.

CI is not fully settled yet (Qwen Code CI still running, though the load-bearing part — both Desktop Shell legs — is green), so approval is deferred until CI lands green on cc74ccfcc80e5467e2919e310c8dc911ae8bb56e; the finalize step posts it pinned to that commit.

中文说明

置信度:5/5 —— 证据完备的 P1 启动崩溃修复,改动恰好是证据指向的最小机制。

退一步看:这个问题的证据是审查门槛所能要求的最完备级别——抓到的 spawn 命令行、Node 失败的独立复现、以及证明因果链的 workaround。PR 把这个 workaround 机制化到剩余的两个 spawn 参数上;方案与我在读 diff 之前独立提出的方案一致;diff 中没有任何超出目标所需的改动。测试直接钉住修复机制本身,且已在真实 Windows runner 上通过。唯一未验证的部分——打包后 Windows 构建的启动——本质上只能靠发布前冒烟测试(任何机器人通道都无法执行),PR 也已自述。半年后维护这段代码:一个小巧、注释到位、边缘情况取舍明确的 helper——值得感谢而非吐槽。

CI 尚未全部结束(Qwen Code CI 仍在运行,但关键的两个 Desktop Shell 分支已绿),因此批准推迟到 CI 在该 commit 上全绿后,由 finalize 流程钉在同一 commit 上执行。

Qwen Code · qwen3.8-max

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

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed exact head cc74ccfcc80e5467e2919e310c8dc911ae8bb56e. The runtime-path change looks correct: every RuntimeLayout root flows through dunce::simplified, clippy is clean, and both Desktop Shell CI jobs pass. I did not find a blocking code issue.

Non-blocking linkage follow-up: #8929 also records the separate visible Windows runtime console bug (CREATE_NO_WINDOW), but no separate issue currently tracks it. Since this PR uses Fixes #8929, split that follow-up into its own issue before merge so it is not silently closed.

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI N/A% N/A% N/A% N/A%
Core 87.86% 87.86% 89.4% 86.37%
CLI Package - Full Text Report
CLI full-text-summary.txt not found at: coverage_artifact/cli/coverage/full-text-summary.txt
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.86 |    86.37 |    89.4 |   87.86 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.38 |    84.54 |   94.85 |   90.38 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.59 |    77.55 |   83.33 |   85.59 | ...1793-1797,1800 
  ...ound-tasks.ts |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |    91.1 |    86.68 |   89.23 |    91.1 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |    92.4 |       90 |   83.78 |    92.4 | ...1862,1911-1914 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1705,1711-1712 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   82.04 |    84.17 |   88.97 |   82.04 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.98 |    87.13 |   75.37 |   84.98 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.29 |    86.85 |   73.79 |   84.29 | ...8350,8354-8355 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.37 |    88.08 |   93.29 |   92.37 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   92.05 |     87.4 |   91.66 |   92.05 | ...3987,4085-4086 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6215,6243-6259 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 68-72             
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.67 |    93.07 |     100 |   98.67 | ...79,707-708,755 
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.33 |    88.12 |   96.15 |   96.33 |                   
  ...tGenerator.ts |   97.24 |    86.72 |   94.87 |   97.24 | ...1429,1458,1469 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1329,1550-1552 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |    95.6 |    88.74 |    92.3 |    95.6 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.52 |    87.88 |   91.89 |   95.52 | ...1195-1196,1224 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.63 |    90.43 |   95.61 |   91.63 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.45 |    91.18 |     100 |   95.45 | ...1301,1309,1408 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.19 |    90.44 |   98.36 |   97.19 |                   
  dashscope.ts     |   98.36 |    92.99 |   95.65 |   98.36 | ...93-494,636-637 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   87.27 |    84.01 |   92.52 |   87.27 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.85 |    86.38 |   97.87 |   90.85 | ...1218-1224,1268 
  ...ionManager.ts |   82.24 |    80.14 |   81.52 |   82.24 | ...2730,2752-2753 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.36 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.42 |    82.66 |     100 |   90.42 | ...0,990-991,1001 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |    79.9 |    78.92 |    90.9 |    79.9 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   71.76 |    64.76 |   71.42 |   71.76 | ...53-654,661-662 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |    93.3 |    89.05 |    94.6 |    93.3 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.79 |     88.5 |   96.42 |   88.79 | ...04-805,828-831 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...83,186,190-192 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |   95.74 |    93.33 |     100 |   95.74 | 154-155           
  goal-reducer.ts  |    93.4 |    90.65 |   96.96 |    93.4 | ...27,501,519-520 
  goal-runtime.ts  |   97.62 |     89.9 |     100 |   97.62 | ...1049,1169-1170 
  goal-tools.ts    |   98.22 |    93.02 |      95 |   98.22 | ...46-147,248-249 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.36 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.12 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.83 |    83.86 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    74.19 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.97 |   91.13 |   92.55 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.16 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.63 |    89.01 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |     92.7 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.07 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.77 |    84.63 |   96.92 |   89.77 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |    98.5 |     87.5 |     100 |    98.5 | 81-82,105,476-477 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   91.41 |    85.15 |   95.65 |   91.41 | ...2116,2143-2144 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    93.93 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |    90.85 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.79 |    83.72 |   97.18 |   88.79 | ...2477,2553-2573 
  sessionTitle.ts  |   94.26 |    73.21 |     100 |   94.26 | ...45-248,279-280 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...ite-origin.ts |     100 |    93.33 |     100 |     100 | 32                
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.73 |    83.97 |   84.83 |   81.73 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |    99.1 |    95.72 |      95 |    99.1 | 145,369-370       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.03 |    76.51 |   66.07 |   60.03 | ...1484,1501-1521 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,482-483,499 
  sdk.ts           |   82.12 |    90.47 |   66.66 |   82.12 | ...90-194,232-254 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |    91.1 |    88.68 |   96.77 |    91.1 | ...1737,1768-1771 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |      83 |    94.32 |   86.36 |      83 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.02 |    98.41 |   82.92 |   96.02 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.24 |    84.99 |   88.72 |   86.24 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.77 |   81.25 |   82.76 | ...45-746,865-915 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   79.87 |    85.58 |   89.47 |   79.87 | ...2259,2263-2266 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.71 |    77.08 |   81.25 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5036,5099-5100 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   93.11 |    92.53 |   91.66 |   93.11 | ...69-570,586-592 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   86.72 |    84.92 |   88.88 |   86.72 | ...25-828,865-900 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.22 |    87.68 |   88.69 |   87.22 |                   
  agent.ts         |   85.84 |    86.59 |   86.31 |   85.84 | ...4315,4337-4347 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   86.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.89 |    89.62 |   96.88 |   92.89 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   83.01 |    95.03 |    61.9 |   83.01 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.95 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |     93.1 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |    83.96 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.07 |    88.33 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       64 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |    87.5 |    86.13 |     100 |    87.5 | ...76-480,510-525 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   96.74 |    91.04 |     100 |   96.74 | ...69,196,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

Not explored to full depth (tool budget reached): This PR (QwenLM/qwen-code #8936) fixes issue #8929: on Wi...: none — all checks above completed within budget.; This PR (QwenLM/qwen-code #8936) fixes issue #8929: on Wi...: none — all planned checks completed within budget..

中文说明

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

未探索到全部深度(达到工具调用预算):This PR (QwenLM/qwen-code #8936) fixes issue #8929: on Wi...:none — all checks above completed within budget.;This PR (QwenLM/qwen-code #8936) fixes issue #8929: on Wi...:none — all planned checks completed within budget.

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

Comment on lines +179 to +180
// Tauri's resource_dir() returns `\\?\` verbatim paths on Windows, and
// Node's entry-script resolution cannot handle that prefix (#8929).

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] Fixes #8929 auto-closes the issue's second, still-unfixed bug — the visible runtime console window on Windows — which this very fix un-masks for every Windows user. The issue body's "Follow-up: visible runtime console window" section reports that the bundled runtime (qwen serve) appears in its own console window and closing that console kills the whole app; the issue's triage confirmed this is unfixed on main (CREATE_NO_WINDOW is set nowhere in this crate) and suggested tracking it separately or folding it into the same fix. This PR does neither, and no separate issue exists. — Failure scenario: after merge, GitHub closes #8929 — the only record of the console-window bug — while the fixed startup path makes the window newly visible on every Windows startup (previously masked by the instant crash). Users see a blank console window beside the app, and closing it terminates the runtime and the whole app, with no issue left tracking the behavior.

Suggested fix: either add the CREATE_NO_WINDOW creation flag to the runtime spawn (cfg-gated std::os::windows::process::CommandExt::creation_flags on the Command before group_spawn()), or file a follow-up issue for the console window and reference it in the PR description before merging, so closing #8929 does not silently drop that half of the report.

中文说明

Fixes #8929 会自动关闭该 issue 中第二个尚未修复的 bug —— Windows 上可见的运行时控制台窗口 —— 而本修复恰好会让这个窗口对每个 Windows 用户显现出来。issue 正文的 "Follow-up: visible runtime console window" 部分指出:内置运行时(qwen serve)会出现在独立的控制台窗口中,关闭该窗口会导致整个应用退出;issue 的 triage 已确认该问题在 main 上仍未修复(整个 crate 中没有设置任何 CREATE_NO_WINDOW),并建议单独跟踪或并入同一修复。本 PR 两者都没有做,且目前也没有单独的 issue 跟踪此问题。— 失败场景:合并后 GitHub 关闭 #8929(控制台窗口 bug 的唯一记录),而修复后的启动路径使该窗口在每次 Windows 启动时新出现(此前因运行时立即崩溃而被掩盖)。用户会在应用旁看到一个空白控制台窗口,关闭它会导致运行时和整个应用退出,且不再有 issue 跟踪该行为。

建议修复:为运行时 spawn 添加 CREATE_NO_WINDOW 创建标志(cfg 门控的 std::os::windows::process::CommandExt::creation_flags,在 group_spawn() 之前设置),或在合并前为控制台窗口问题创建一个后续 issue 并在 PR 描述中引用,避免关闭 #8929 时悄悄丢掉报告的另一半。

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

Comment on lines +610 to +613
assert!(
!path.starts_with("\\\\?\\"),
"runtime path keeps the verbatim prefix: {path}"
);

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 test asserts only the absence of the \\?\ prefix, never the resulting path values, so it cannot distinguish node from entry and passes for any prefix-free output — including value-corrupting mutations of the changed lines (swapping &node/&entry between the tuple slots, simplifying &root instead, returning an empty or mis-joined PathBuf). This is the only test covering layout_from_root, and the desktop_shell CI job runs without the bundled runtime, so such a regression would surface only at packaged-app runtime. — Failure scenario: a future refactor of layout_from_root that swaps the node/entry slots or mis-joins a segment stays green here (an empty string doesn't start with \\?\), and the wrong layout ships — spawning cli-entry.js as the executable fails desktop runtime startup on packaged Windows builds while this test passes.

Suggested fix: pin the full expected values instead of the loop (the assert_eq!s must run before node/entry are moved into the array):

assert_eq!(
    node,
    PathBuf::from(r"C:\Users\user\AppData\Local\Qwen Code Desktop\runtime\qwen-code\node\node.exe")
);
assert_eq!(
    entry,
    PathBuf::from(r"C:\Users\user\AppData\Local\Qwen Code Desktop\runtime\qwen-code\lib\cli-entry.js")
);
中文说明

该测试只断言 \\?\ 前缀不存在,从不验证结果路径的具体值,因此无法区分 nodeentry,任何不带前缀的输出都能通过 —— 包括对改动行的取值破坏型变异(在元组两个槽位间交换 &node/&entry、改为对 &root 做简化、返回空或拼接错误的 PathBuf)。这是覆盖 layout_from_root 的唯一测试,且 desktop_shell CI 任务不带内置运行时运行,因此此类回归只会在打包后的应用中暴露。— 失败场景:未来对 layout_from_root 的重构若交换了 node/entry 槽位或拼错路径段,此测试仍为绿色(空字符串同样不以 \\?\ 开头),错误布局会被放行 —— 把 cli-entry.js 当作可执行文件 spawn 会导致打包后的 Windows 构建无法启动桌面运行时,而此测试却显示通过。

建议修复:用完整期望值替代循环断言(assert_eq! 必须在 node/entry 被移入数组之前执行):见上方英文部分的代码块。

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

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

Code Review Overview (AI Generated)

PR: #8936 fix(desktop): strip Windows verbatim prefix from runtime spawn paths
Type: Bug Fix (platform / Windows launcher) — scope/windows, priority/P1
Change size: +34/-6 across 1 file (packages/desktop-shell/src-tauri/src/runtime.rs)
Reviewed at HEAD: cc74ccfcc80e5467e2919e310c8dc911ae8bb56e (1 commit)

Findings Summary

  • Critical: 0
  • Major: 1
  • Minor: 2
  • Nit: 3

Key Observations

The mechanism is right and the PR is strictly better than the status quo: dunce::simplified is the correct tool (syntactic, no I/O, and require_file does the existence check immediately after), the extraction into layout_from_root puts all three root sources — QWEN_DESKTOP_RUNTIME_DIR, the debug_assertions path, and the packaged resource_dir() — behind one helper, and dunce was already a dependency so no lockfile churn.

The one substantive gap is a parallelism gap with #8619, the workspace half of this exact bug class, in this exact file. #8619 shipped a three-part pattern:

  1. strip with dunce (dunce::canonicalize, runtime.rs:209),
  2. reject any path where dunce refused to strip, with an actionable message (ensure_supported_workspace_path, runtime.rs:194-205),
  3. test both the strip and the rejection (3 tests, incl. \\?\UNC\ / \\?\GLOBALROOT\ / >260-char).

This PR ports (1) and half of (3), and drops (2) entirely. dunce::simplified returns the input unchanged and silently for any prefix that is not Prefix::VerbatimDisk — notably \\?\UNC\…, which is what fs::canonicalize yields for a mapped network drive or UNC install. In that case require_file still succeeds (Win32 accepts verbatim paths, so is_file() returns true) and the spawn then dies with exactly the EISDIR: lstat 'C:' / "Bundled runtime closed stdout before reporting its listening URL" that this PR exists to eliminate — with zero diagnostic pointing at the path. See M1.

Industry Context

dunce is the canonical Rust answer to the \\?\ problem and is already used by cargo/rustup/tauri for it, so the dependency and the simplified-over-canonicalize choice need no defence. The relevant industry pattern the PR misses is not the normalizer but the "normalize, then assert the invariant you actually need" discipline: a best-effort normalizer whose failure mode is "return the input unchanged" must be paired with a validation step, otherwise the caller silently inherits the un-normalized value. #8619 got this right in the same file; this PR relies on dunce alone.

Cross-Validation

Finding Other Reviewer My Assessment
Fixes #8929 auto-closes the issue's still-open CREATE_NO_WINDOW console-window follow-up qwen-code-ci-bot (inline @180), yiliang114 (review body) Confirmed — independently found in Round 0 linked-issue verification. Verified creation_flags/CREATE_NO_WINDOW appear nowhere in src-tauri/src/**, and Command at runtime.rs:54-66 sets no creation flags. Agree it is non-blocking, but the follow-up must be split into its own issue before merge. Worth adding to Risk & Scope, which currently omits it.
New test asserts only the absence of \\?\, never the resulting path values qwen-code-ci-bot (inline @613) Confirmed — same conclusion, reached independently. I add the missing other half below (no negative-case test at all — see m2).
Residual verbatim edge is "the right tradeoff"; "No correctness, security, or convention issues found" (confidence 5/5) qwen-code-ci-bot (triage stage 2 & 3) Disagree. The tradeoff is right for the stripping decision — hard-stripping a >260-char or UNC path would indeed be wrong. But #8619 paired that same tradeoff with ensure_supported_workspace_path so the residual becomes a diagnosable error rather than a cryptic crash. That half is missing here, which is a real correctness/diagnosability gap, not a documented tradeoff. See M1.
"all three root sources … so both spawn args are simplified on every path" qwen-code-ci-bot (triage stage 2) Partially inaccurate. Simplification is conditional and re-evaluated per path; node and entry have different suffix lengths and can therefore diverge. See m1.
M1 (Major): residual-verbatim guard from #8619 not ported to the runtime paths New finding — runtime.rs:172-185
m1 (Minor): node/entry simplified independently → mixed plain/verbatim state reachable New finding — runtime.rs:181-184
m2 (Minor): documented residual behavior has no negative-case test (#8619 shipped two) New finding — runtime.rs:601-615
Nits: positional (PathBuf, PathBuf) return; root: PathBuf taken by value; assertion loop hides which path failed — (bot's @613 partially overlaps the third) New / partial overlap

Additional Audit Coverage

Independently checked, no issue found — recorded so the clean areas are explicit:

  • Caller/consumer blast radius: RuntimeLayout has exactly one consumer (DesktopRuntime::start, runtime.rs:51-56); layout_from_root is private with only resolve and the new test as callers. No downstream breakage, no public API surface added.
  • Convention compliance (AGENTS.md): packages/desktop-shell/src-tauri/** is not one of the listed core-module paths, so the maintainer-only two-tier gate does not apply; the diff is minimal and adds no speculative abstraction, consistent with "Simplicity First".
  • Supply chain: dunce = "1.0.5" already present in src-tauri/Cargo.toml (added by #8619); no Cargo.toml/Cargo.lock change needed or made. Correct.
  • CI reachability of the new test: desktop_shell matrix is ['ubuntu-22.04', 'windows-2022'] (ci.yml:1133) and runs cargo test --manifest-path src-tauri/Cargo.toml (ci.yml:1209), so the #[cfg(windows)] test does execute on a real Windows runner. fmt/clippy are deliberately not gated for this crate (ci.yml:1124-1125), so the new #[cfg(windows)] use super::layout_from_root; import placement carries no CI risk.
  • Security (adversarial pass): traced dunce::is_safe_to_strip_unc — it rejects any non-VerbatimDisk prefix and any .., reserved (CON, COM4, …), or trailing-dot/space component. Stripping therefore cannot change the resolved target; no traversal or path-semantics change is introduced.
  • #[cfg(windows)] gate on the new test is required, not merely conservative: off Windows the literal \\?\C:\… parses as a single Normal component and simplified is a compile-time no-op, so the assertion would fail. Correctly gated — and correspondingly, this test contributes zero coverage on the Linux leg and on the author's macOS run.
  • Non-Windows cost: two extra to_path_buf() allocations once per app start. Non-issue.
  • Error-message side effect: require_file now reports the simplified path, which is a small unadvertised improvement to the "runtime is missing at …" message. Benign.

Final Verdict

Needs Changes (non-blocking on the P1 itself). The fix is correct for the reported case and I would not hold the P1 behind polish — but M1 is ~8 lines that reuse a guard already living 10 lines below in this same file, and without it the exact failure mode this PR exists to eliminate remains silently reachable on UNC/mapped-drive and long-path installs. Recommend landing M1 + m2 with this PR, and splitting the CREATE_NO_WINDOW follow-up out of #8929 before merge as both other reviewers requested. m1 and the Nits are optional.

中文说明

结论:建议修改(不阻塞该 P1 修复本身)。

修复机制本身正确:dunce::simplified 是这里的正确工具(纯语法、无 I/O,且紧随其后的 require_file 负责存在性检查),把路径构造抽成 layout_from_root 让三个 root 来源(环境变量、debug、打包 resource_dir)统一走同一条路径,dunce 也已是现有依赖。

核心问题是与 #8619(同一文件、同一类 bug 的 workspace 那一半)不对等#8619 落地的是三件套:① 用 dunce 剥离;② 对 dunce 拒绝剥离的残留路径给出可行动的报错ensure_supported_workspace_path,runtime.rs:194-205);③ 同时测试剥离成功与残留拒绝(3 个测试,含 \\?\UNC\\\?\GLOBALROOT\、>260 字符)。本 PR 只落地了 ① 和 ③ 的一半,完全没有 ②。

dunce::simplified 对任何非 Prefix::VerbatimDisk 的前缀会静默原样返回 —— 典型就是映射网络驱动器 / UNC 安装时 fs::canonicalize 产出的 \\?\UNC\…。此时 require_file 依然通过(Win32 接受 verbatim 路径,is_file() 返回 true),随后 spawn 仍以 EISDIR: lstat 'C:' 崩溃 —— 正是本 PR 要消灭的症状,且没有任何指向路径的诊断信息。详见 M1

交叉验证:已确认另两位评审的两条发现(Fixes #8929 会关掉未修的控制台窗口问题;新测试只断言前缀缺失)。不同意 triage 的「残留边界是正确取舍、无正确性问题、置信度 5/5」——取舍对的是「是否强行剥离」,缺的是 #8619 配套的残留校验。另外 triage 所述「两个 spawn 参数在所有路径上都被简化」并不精确:简化是按路径逐个条件判定的,nodeentry 可能出现一个普通、一个 verbatim 的混合状态(m1)。

建议随本 PR 一并处理 M1m2,并在合并前把 CREATE_NO_WINDOW 后续问题拆成独立 issue。


This review was generated by QoderWork AI

dunce::simplified(&node).to_path_buf(),
dunce::simplified(&entry).to_path_buf(),
)
}

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.

[Major] The residual-verbatim guard from #8619 is not ported to the runtime paths

dunce::simplified is best-effort: it strips only when is_safe_to_strip_unc passes, which requires the prefix to be Prefix::VerbatimDisk, every component to be a valid non-reserved Normal/RootDir, and the path to be within 260 chars. Anything else is returned unchanged and silently — and path.to_str() returning None (non-UTF-8 path) also falls back to the original.

That residual case has a precedent in this very file. #8619 — the workspace half of this same bug class — did not rely on dunce alone: it paired dunce::canonicalize with ensure_supported_workspace_path (runtime.rs:194-205) precisely so that a path dunce refuses to normalize surfaces as an actionable error instead of a crash. This PR ports the stripping but not the guard.

Concrete failure, not hypothetical — install or launch from a mapped network drive / UNC share:

  1. resource_dir() canonicalizes, so root becomes \\?\UNC\server\share\….
  2. simplified correctly declines (not VerbatimDisk) and returns it verbatim.
  3. require_file succeeds — the Win32 API accepts verbatim paths, so is_file() returns true and neither check fires.
  4. The spawn then dies in resolveMainPathrealpathSync with exactly the EISDIR: lstat 'C:' / "Bundled runtime closed stdout before reporting its listening URL" of Windows: Qwen Code Desktop 0.1.0 fails to start - launcher passes \\?\ verbatim paths to bundled Node (EISDIR) #8929, with nothing in the message pointing at the path.

The same holds for a >260-char install path and for a non-UTF-8 path. Risk & Scope frames this as "behavior is unchanged from today rather than broken", which is true of the stripping decision — but the workspace half of this bug class converts that unchanged-and-broken state into a diagnosable one, and the runtime half now does not.

Suggested fix — generalize the helper that already exists 10 lines below and call it on both paths:

fn ensure_supported_path(path: &Path, description: &str) -> Result<(), String> {
    if matches!(
        path.components().next(),
        Some(Component::Prefix(prefix)) if prefix.kind().is_verbatim()
    ) {
        return Err(format!(
            "{description} path uses an unsupported Windows extended-length form: {}. \
             Choose a local drive path; network (UNC) shares, paths over 260 characters, \
             and names ending in a dot or space are not supported.",
            path.display()
        ));
    }
    Ok(())
}

// in RuntimeLayout::resolve, before the require_file calls:
ensure_supported_path(&node, "Node.js runtime")?;
ensure_supported_path(&entry, "Qwen Code runtime entry")?;

Prefix::is_verbatim() already covers VerbatimDisk, VerbatimUNC and Verbatim, so this catches every residual form in one predicate. It also makes the per-path divergence flagged separately below unreachable.

中文说明

dunce::simplified 是 best-effort:只有当前缀为 Prefix::VerbatimDisk、所有组件合法且非保留名、路径不超过 260 字符时才剥离;其它情况(尤其 \\?\UNC\…静默原样返回,非 UTF-8 路径也会回退到原值。

同一文件里已有先例:#8619 处理 workspace 时并没有只依赖 dunce,而是把 dunce::canonicalizeensure_supported_workspace_path(runtime.rs:194-205)配对,让 dunce 拒绝规范化的路径以可行动的报错暴露出来,而不是崩溃。本 PR 只搬了剥离,没有搬校验。

真实失败场景(映射网络驱动器 / UNC 安装):resource_dir() 规范化后 root 变成 \\?\UNC\server\share\…simplified 正确地拒绝剥离 → require_file 依然通过(Win32 接受 verbatim 路径,is_file() 为 true)→ spawn 仍在 resolveMainPathrealpathSync 处以 EISDIR: lstat 'C:' 崩溃,报错信息里毫无路径线索。>260 字符与非 UTF-8 路径同理。

Risk & Scope 里「行为与现状一致,不会更糟」对「是否强行剥离」这个决定是成立的;但同类 bug 的 workspace 那一半把「一致地坏」变成了「可诊断」,runtime 这一半没有。

建议把下方已有的 helper 泛化后对两个路径都调用(见上方代码)。Prefix::is_verbatim() 已覆盖 VerbatimDisk/VerbatimUNC/Verbatim,一个判定即可兜住所有残留形式,同时也让下面单独提到的两路径分歧不可能发生。


This review was generated by QoderWork AI

// Node's entry-script resolution cannot handle that prefix (#8929).
(
dunce::simplified(&node).to_path_buf(),
dunce::simplified(&entry).to_path_buf(),

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.

[Minor] node and entry are simplified independently, so a mixed plain/verbatim state is reachable

dunce::simplified re-evaluates is_safe_to_strip_unc for each argument, and one of its conditions is a length check (path_os_str.len() > 260 && windows_char_len(path_os_str) > 260). The two paths carry different suffixes — \node\node.exe (14 chars) vs \lib\cli-entry.js (17) — so there is a 3-character window of root lengths in which node is simplified to a plain path while entry keeps its \\?\ prefix.

That combination is the worst of both worlds: a plain program path spawned with a verbatim entry-script argument, i.e. the #8929 crash again, but from a layout that looks half-fixed in the logs. It also makes the triage note "both spawn args are simplified on every path" not quite exact — simplification is conditional and evaluated per path, not once per root.

Simplifying root once before the joins would keep the two consistent, at the cost of possibly emitting a plain >260-char path. Adding the residual guard suggested above is the cleaner fix, since it makes the mixed state impossible to reach silently rather than merely unlikely.

中文说明

dunce::simplified 会对每个入参各自重新判定 is_safe_to_strip_unc,其中包含长度检查(len() > 260 && windows_char_len() > 260)。两个路径后缀长度不同 —— \node\node.exe(14 字符)与 \lib\cli-entry.js(17 字符)—— 因此存在约 3 个字符的 root 长度窗口,使 node 被简化为普通路径、而 entry 仍保留 \\?\ 前缀。

这种组合是最糟的情况:用普通程序路径去 spawn 一个 verbatim 的入口脚本参数,即再次触发 #8929 崩溃,但日志上看起来像「已修一半」。这也说明 triage 所述「两个 spawn 参数在所有路径上都被简化」并不精确 —— 简化是按路径条件判定的,不是按 root 一次判定。

在 join 之前对 root 简化一次可以保证两者一致,代价是可能产出超过 260 字符的普通路径;更干净的做法是加上上面建议的残留校验,让混合状态无法被静默触达。


This review was generated by QoderWork AI

"runtime path keeps the verbatim prefix: {path}"
);
}
}

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.

[Minor] The documented residual behavior has no test — #8619 shipped two for the workspace half

#8619 added three Windows-gated tests for this bug class: one positive (resolve_workspace_strips_windows_verbatim_prefix) and two negative (rejects_residual_windows_verbatim_workspace_paths pinning \\?\UNC\ and \\?\GLOBALROOT\, plus resolve_workspace_rejects_residual_verbatim_paths pinning the >260-char case). This PR adds only the positive one, so the exact edge case called out in Risk & Scope is unverified and free to change silently under a dunce version bump.

Secondly, because layout_from_root returns a positional (PathBuf, PathBuf) of two identically-typed values, for path in [node, entry] cannot distinguish them and the failure message names neither. Pinning the exact expected values — as the other reviewer also suggests — plus a case where the prefix is expected to survive would close both gaps:

assert_eq!(
    node,
    PathBuf::from(r"C:\Users\user\AppData\Local\Qwen Code Desktop\runtime\qwen-code\node\node.exe")
);
assert_eq!(
    entry,
    PathBuf::from(r"C:\Users\user\AppData\Local\Qwen Code Desktop\runtime\qwen-code\lib\cli-entry.js")
);

Nits while here: layout_from_root could be RuntimeLayout::from_root(&Path) -> Self, which is type-safe against slot swaps and lets the test read layout.node/layout.entry by name; and root: PathBuf is taken by value although only &Path is needed (join does not consume).

中文说明

#8619 为同类 bug 加了三个 Windows 门控测试:一个正向(resolve_workspace_strips_windows_verbatim_prefix)和两个负向(rejects_residual_windows_verbatim_workspace_paths 钉住 \\?\UNC\\\?\GLOBALROOT\resolve_workspace_rejects_residual_verbatim_paths 钉住 >260 字符)。本 PR 只加了正向那个,因此 Risk & Scope 里明确写出的边界情况没有任何测试保护,dunce 升级时行为可以静默变化。

其次,由于 layout_from_root 返回的是两个同类型值的位置元组 (PathBuf, PathBuf)for path in [node, entry] 无法区分两者,断言失败信息也不会指明是哪一个。按另一位评审的建议钉住完整期望值,再补一个「前缀预期保留」的用例,即可同时补齐两处(见上方代码)。

顺带的 Nit:layout_from_root 可以写成 RuntimeLayout::from_root(&Path) -> Self,既能在类型上防止两个槽位被交换,也便于测试按 layout.node / layout.entry 具名读取;另外 root: PathBuf 是按值传入的,而实际只需要 &Pathjoin 不消耗所有权)。


This review was generated by QoderWork AI

@qwen-code-review-bot qwen-code-review-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. The change is minimal, correctly scoped, and well-tested.

What this PR does: Extracts the Node runtime and entry-script path construction into a layout_from_root helper, then applies dunce::simplified to both paths before returning them. This strips the \\?\ verbatim prefix that Tauri's resource_dir() returns on Windows, matching the same fix already applied to the workspace path in #8619.

Correctness: dunce::simplified is the right call — syntactic only, no filesystem access, keeps the verbatim form where stripping would be unsafe (>260 chars, trailing dot/space). The require_file check immediately after verifies the paths are valid regardless. Every RuntimeLayout root source flows through layout_from_root, so both spawn args are covered on all paths.

Testing: The Windows-gated regression test feeds a realistic \\?\C:\... root through the helper and asserts both outputs drop the prefix. Both Desktop Shell CI legs (Windows + Ubuntu) pass.

One non-blocking note: This PR uses Fixes #8929, but #8929 also tracks the separate CREATE_NO_WINDOW console bug. Consider splitting that follow-up into its own issue before merge so it is not silently closed.

@qwen-code-review-bot

Copy link
Copy Markdown
Collaborator

Approved via gh pr review --approve. The change is minimal, correctly scoped, and well-tested — dunce::simplified on both spawn args mirrors the same fix from #8619, and the Windows-gated regression test passed on a real runner. One non-blocking note: #8929 also tracks the CREATE_NO_WINDOW console bug; consider splitting that into its own issue before merge so it is not silently closed.

@ytahdn ytahdn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. Clean, focused fix that correctly reuses dunce::simplified() consistent with the workspace-path fix in #8619. The Windows-gated test properly asserts both node and entry paths strip the \\?\ prefix.

Minor suggestions (non-blocking):

  • Consider asserting the paths end with node.exe and cli-entry.js in the test, not just the prefix absence.
  • For the >260 char edge case where dunce::simplified preserves the verbatim form, a warning log would help future debugging.

@yiliang114
yiliang114 added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit 8cf36b8 Aug 11, 2026
153 of 156 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.10.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: Qwen Code Desktop 0.1.0 fails to start - launcher passes \\?\ verbatim paths to bundled Node (EISDIR)

5 participants