Skip to content

feat(extensions): support Agent Plugins v1 - #8834

Merged
wenshao merged 3 commits into
mainfrom
codex/agent-plugins-v1
Aug 11, 2026
Merged

feat(extensions): support Agent Plugins v1#8834
wenshao merged 3 commits into
mainfrom
codex/agent-plugins-v1

Conversation

@callmeYe

@callmeYe callmeYe commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds native Agent Plugins v1 loading to the existing extension lifecycle without converting or rewriting the package. A standard plugin.json package can be installed, linked, updated, enabled, disabled, and displayed through the existing extension entry points while preserving its original files.

The runtime support intentionally matches Codex's current portable capability boundary: direct-child Agent Skills plus stdio and Streamable HTTP MCP servers are enabled; bundled commands, agents, hooks, apps, channels, context, settings, client namespaces, and legacy SSE MCP are ignored. The implementation also isolates malformed components, persists PLUGIN_DATA across updates and reinstalls, contains filesystem access within the plugin root, and applies credential-safe HTTP validation and redirect behavior.

Why it's needed

Qwen Code currently requires third-party extension packages to be converted into qwen-extension.json, so valid Agent Plugins packages fail installation and linking even when they only use portable Skills and MCP capabilities. Native loading lets authors distribute the same standards-based package unchanged while keeping Qwen-specific extension behavior and existing formats unaffected.

Reviewer Test Plan

How to verify

Install and link a valid Agent Plugins v1 fixture that contains a direct-child Skill and stdio MCP server. Confirm the extension is identified as AgentPlugins, the Skill and MCP server are available, the MCP server connects with expanded PLUGIN_ROOT and stable PLUGIN_DATA, and the installed package contains the original plugin.json, mcp.json, SKILL.md, and server files byte-for-byte with no generated qwen-extension.json.

Install a capability fixture without a version and confirm it defaults to 1.0.0. Confirm only valid direct-child Skills and supported stdio or Streamable HTTP MCP entries load, while nested or malformed Skills, legacy SSE MCP, commands, agents, and hooks remain unavailable. Confirm one invalid Skill or MCP entry does not disable valid siblings.

Update and reinstall the same plugin identity, reconnect its MCP server, and confirm the same PLUGIN_DATA directory and prior state are retained. For HTTP MCP, confirm HTTPS and loopback HTTP are accepted, unsafe URLs and client-owned headers are rejected, and configured credentials are not forwarded across redirects.

Evidence (Before & After)

Before: the released Qwen Code CLI exits with Configuration file not found .../qwen-extension.json for both local install and link of an unchanged Agent Plugins v1 package.

After: the bundled CLI installs and links the unchanged package, lists Origin: AgentPlugins, discovers the expected Skill, connects both supported MCP transports, preserves source file hashes, and does not create qwen-extension.json.

Tested on

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

Environment (optional)

macOS with Node.js 22, the bundled CLI, isolated QWEN_HOME directories, local stdio MCP probes, and a local Streamable HTTP MCP server.

Risk & Scope

  • Main risk or tradeoff: This adds a second native extension format and security-sensitive MCP/path handling; format detection is schema-gated, runtime policies are scoped to Agent Plugins, and existing Qwen/Claude/Gemini/Qoder paths retain their prior behavior.
  • Not validated / out of scope: Bundled commands, agents, hooks, apps, channels, context, settings, client-specific namespaces, legacy SSE MCP, and Agent Plugins marketplaces are intentionally unsupported. Windows and Linux rely on unit tests and CI rather than local E2E runs.
  • Breaking changes / migration notes: None. Existing extension formats, install entry points, and normal MCP transport behavior are unchanged.

Linked Issues

N/A

中文说明

本 PR 做了什么

为现有 Extension 生命周期新增 Agent Plugins v1 原生加载能力,不转换也不改写插件包。标准 plugin.json 插件现在可以通过现有入口安装、链接、更新、启停和展示,同时保留原始文件。

运行时能力边界有意与 Codex 当前的 portable core 对齐:启用直接子目录中的 Agent Skills,以及 stdio 和 Streamable HTTP MCP;忽略 bundled commands、agents、hooks、apps、channels、context、settings、client namespace 和 legacy SSE MCP。实现同时提供组件级错误隔离、跨更新和重装持久化的 PLUGIN_DATA、插件根目录内的文件系统边界,以及避免凭据泄露的 HTTP 校验和重定向策略。

为什么需要

Qwen Code 当前要求第三方 Extension 转换为 qwen-extension.json,因此即使标准 Agent Plugins 包只使用可移植的 Skills 和 MCP 能力,安装和链接仍会失败。原生加载允许作者不修改标准包即可分发给 Qwen Code,同时不影响 Qwen 专属 Extension 行为和现有格式。

Reviewer Test Plan

如何验证

安装并链接一个包含直接子 Skill 和 stdio MCP server 的有效 Agent Plugins v1 fixture。确认 Extension 来源显示为 AgentPlugins,Skill 和 MCP server 可用,MCP 使用展开后的 PLUGIN_ROOT 和稳定的 PLUGIN_DATA 成功连接;同时确认安装后的 plugin.jsonmcp.jsonSKILL.md 和 server 文件与源文件逐字节一致,且没有生成 qwen-extension.json

安装一个缺失 version 的 capability fixture,确认版本默认显示为 1.0.0。确认仅加载有效的直接子 Skills 和受支持的 stdio 或 Streamable HTTP MCP entry;嵌套或错误 Skill、legacy SSE MCP、commands、agents 和 hooks 均不可见。确认单个错误 Skill 或 MCP entry 不会禁用有效的同级组件。

更新并重新安装同一插件标识,重新连接 MCP server,确认复用相同的 PLUGIN_DATA 目录并保留已有状态。对于 HTTP MCP,确认只接受 HTTPS 或 loopback HTTP,拒绝不安全 URL 和 client-owned headers,配置凭据不会经重定向转发。

前后证据

之前:已发布的 Qwen Code CLI 对未改动的 Agent Plugins v1 包执行本地安装和链接时,都会以 Configuration file not found .../qwen-extension.json 退出。

之后:bundle 后的 CLI 可以安装和链接原始插件包,显示 Origin: AgentPlugins,发现预期 Skill,连接两种受支持的 MCP transport,保持源文件 hash 不变,且不会创建 qwen-extension.json

测试平台

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

环境(可选)

macOS、Node.js 22、bundle 后的 CLI、隔离的 QWEN_HOME、本地 stdio MCP probe 和本地 Streamable HTTP MCP server。

风险与范围

  • 主要风险或取舍:本 PR 新增第二种原生 Extension 格式及安全敏感的 MCP/路径处理;格式检测受 schema 限制,运行时策略仅作用于 Agent Plugins,现有 Qwen/Claude/Gemini/Qoder 路径保持原行为。
  • 未验证或不在范围内:bundled commands、agents、hooks、apps、channels、context、settings、client namespace、legacy SSE MCP 和 Agent Plugins marketplace 均明确不支持。Windows 和 Linux 由单元测试与 CI 覆盖,未做本地 E2E。
  • 破坏性变更或迁移说明:无。现有 Extension 格式、安装入口和普通 MCP transport 行为不变。

关联 Issue

N/A

@callmeYe

Copy link
Copy Markdown
Collaborator Author

E2E Test Report

Tested the bundled CLI on macOS with fresh isolated QWEN_HOME directories and fixtures stored outside the repository.

  • Baseline: Qwen Code 0.18.5-preview.0 rejected both install and link with Configuration file not found .../qwen-extension.json.
  • Native install/link: both succeeded; extensions list showed Origin: AgentPlugins, version 1.0.0, the expected Skill, and the expected MCP server; mcp list reported the stdio server as connected.
  • File preservation: installed plugin.json, mcp.json, SKILL.md, and server files matched the source byte-for-byte; qwen-extension.json was absent; only the existing install sidecar was added.
  • Capability boundary: a no-version fixture defaulted to 1.0.0; only the valid direct-child Skill and supported stdio MCP loaded; malformed and nested Skills, SSE MCP, commands, agents, and hooks stayed unavailable; the hook marker was never created.
  • Runtime variables and persistence: PLUGIN_ROOT, PLUGIN_DATA, and cwd were observed with the expected values. MCP state increased from 1 to 2 after an update and to 3 after uninstall/reinstall, using the same plugin-data path.
  • Streamable HTTP: a real local MCP server completed initialization, tools/list, and tools/call through the Qwen MCP client. A configured-header cross-origin redirect was blocked before the target received any request.
  • Regression checks: 423 focused Core tests and 34 focused CLI tests passed, followed by npm run typecheck, npm run lint, npm run build, and npm run bundle.

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Gate re-run at @wenshao's request — the head is unchanged from the previous pass (0f8a8ffa), so the gate findings stand; what changed since is the evidence, and the stage comments are being updated with the completed outcome.

Template: complete ✓

Problem: an observed gap, not a theoretical one: an unmodified Agent Plugins v1 package fails both install and link today with Configuration file not found .../qwen-extension.json, and the PR body shows the before/after. The maintainer's local E2E since reproduced the same before/after independently against the base and head builds.

Direction: aligned. Native loading (no conversion, no file rewriting) is the right call for a standards-based format, and the capability boundary (direct-child Skills + stdio/Streamable HTTP MCP, nothing else) matches Codex's portable core. No auth/sandbox/public-contract escalation triggers.

Size: core paths are touched (packages/core/src/extension/**, config/config.ts, tools/mcp-client.ts, plus CLI/acp-bridge/sdk wiring). Breakdown: ~1,166 production lines / ~1,241 test lines / ~132 docs lines (+2,475/−64 across 33 files). The maintainer-awareness escalation for a 500+ production-line core feat was the reason the previous pass deferred — it is now answered: @wenshao exercised the feature end-to-end on macOS and formally approved this exact head. With that sign-off given, the escalation no longer withholds a verdict.

Approach: scope remains disciplined. Everything outside the two fix commits was assessed as load-bearing in the first pass, and the fix delta maps 1:1 to the Critical findings from the /review rounds — no drive-by changes.

Risk: ⚠️ packages/core/src/tools/mcp-client.ts stays on the repo's high-risk path list (correlated with post-merge reverts), and it got the matching attention: the redirect stop was re-verified statically this pass, and the maintainer mutation-tested it live — with the guard patched out, the plugin token leaked across the redirect; with it in place, the redirect target receives nothing. CI evidence is quoted in the Stage 2 comment.

Moving on to code review. 🔍

中文说明

@wenshao 请求再次执行 Gate —— head 与上一轮相同(0f8a8ffa),门禁结论不变;变化的是证据,各阶段评论将更新为最终结果。

**模板:**完整 ✓

**问题:**已观测到的缺口而非理论问题:未改动的 Agent Plugins v1 包目前在 installlink 时都会以 Configuration file not found .../qwen-extension.json 失败,PR 正文给出了前后对比。维护者随后的本地 E2E 已在 base/head 两侧独立复现了同一前后对比。

**方向:**对齐。对标准化格式而言原生加载(不转换、不改写文件)是正确选择;能力边界(直接子目录 Skills + stdio/Streamable HTTP MCP,其余不支持)与 Codex 的 portable core 一致。未触及 auth/sandbox/公共契约等升级项。

规模:触及核心路径(packages/core/src/extension/**config/config.tstools/mcp-client.ts,外加 CLI/acp-bridge/sdk 接线)。拆分:约 1,166 行生产代码 / 约 1,241 行测试 / 约 132 行文档(33 个文件,+2,475/−64)。500+ 生产行核心 feat 的维护者关注升级项是上一轮 defer 的原因——现已得到回应@wenshao 在 macOS 上完成端到端验证并对当前 head 正式批准。签核既已给出,该升级项不再阻止裁决。

**方案:**范围依旧克制。两个 fix commit 之外的部分在首轮已评估为必要组成,fix delta 与两轮 /review 的 Critical 发现一一对应,无顺手改动。

**风险:**⚠️ packages/core/src/tools/mcp-client.ts 仍属仓库高风险路径(与合并后 revert 相关),也得到了相应关注:重定向拦截本轮经静态复核,维护者还做了在线变异测试——去掉该判断后插件 token 会随重定向泄露,保留后重定向目标收不到任何请求。CI 证据见 Stage 2 评论。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review (final pass at 0f8a8ffa)

This pass re-read the security-critical hunks independently rather than trusting earlier passes: the MCP loader's URL and header policy, the containment helpers, the scoped redirect stop in mcp-client.ts, the format-detection precedence in the converter, and the link-metadata validation in the manager. Nothing new surfaced — the posture is consistently fail-closed:

  • HTTP MCP: absolute HTTP(S) only; non-loopback plaintext HTTP, URL user-info, and fragments refused; client-owned headers (authorization, host, user-agent, …) dropped from plugin config, and duplicate header names rejected case-insensitively.
  • stdio MCP: command restricted to a bare name or a contained ./ path; cwd restricted to ./, ${PLUGIN_ROOT}/…, ${PLUGIN_DATA}/… with a post-expansion containment check; reserved PLUGIN_ROOT/PLUGIN_DATA env names refused. Variable expansion is single-pass, so expanded values are never re-expanded.
  • Containment: all boundary checks realpath before comparing (paths.ts), symlinks are dropped at install (lstat filter), and createTransport re-validates stdio roots at launch — containment holds at load and start.
  • Existing paths untouched: redirect: 'manual' engages only for agentPluginV1 servers that carry configured headers or a request-level Authorization; every other MCP config goes through the unchanged code path.
  • Detection & lifecycle: schema-gated ($schema must match exactly; other agent-plugins.org versions fail explicitly instead of guessing); an explicit marketplace selection bypasses root detection and strips any carried plugin.json; link metadata is honored only when source is a non-empty string, at both call sites; PLUGIN_DATA ids are validated as 64-hex before path construction.

The two fix commits' claims were verified in the code at this head (each check re-done this pass):

Finding Fix verified at this head
R1-2 + R2-1 — bundled commands/ becoming live, unconsented slash commands FileCommandLoader excludes extensions keyed on both format === 'agent-plugins-v1' and originSource === 'AgentPlugins'; regression test pins zero commands loaded
R1-3 — symlinked source root silently copying nothing copyExtension realpaths the source when skipSymlinks is set; symlinks inside the package are dropped via lstat filter
R1-4 — startup hang on a non-regular root plugin.json getAgentPluginSchemaStatus requires statSync(...).isFile() before reading
R1-5 — cwd: "${PLUGIN_DATA}/<subdir>" accepted but never startable loader mkdirs contained stdio cwd targets at load time; launch-time validateAgentPluginStdioRuntimePaths re-checks containment
R1-6 + R2-3 — root plugin.json pre-empting an explicit marketplace selection with a pluginName selection, root detection is bypassed and any carried plugin.json is removed from the converted directory
R2-2 — unvalidated link-metadata source consumed by fingerprint/load paths both call sites require a non-empty string source before honoring type: 'link'

Follow-ups the author committed to (from the maintainer E2E, explicitly non-blocking): document or warn when a package carries both plugin.json and qwen-extension.json (Agent Plugins precedence is silent today), and guard the empty MCP servers: section in extensions list output.

Flow — the install path, for orientation (unchanged):

sequenceDiagram
    participant P1 as User
    participant P2 as Install flow
    participant P3 as Format detection
    participant P4 as Plugin loaders
    participant P5 as Consent prompt
    participant P6 as Extension store
    P1->>P2: install or link a package
    P2->>P3: probe root manifest schema
    P3-->>P2: AgentPlugins detected
    P2->>P4: load plugin.json, skills, mcp.json
    P4-->>P2: contained config and MCP entries
    P2->>P5: show servers and skills
    P5-->>P1: approve or abort
    P1->>P2: approve
    P2->>P6: copy without symlinks, persist PLUGIN_DATA by id
Loading
Files changed (30 of 33 shown)
File What changed
docs/design/agent-plugins-v1-native-support.md Design doc - native format rationale, capability boundary, security policies
docs/users/extension/_meta.ts Adds the agent-plugins page to docs navigation
docs/users/extension/agent-plugins.md User docs - install and link commands, support matrix, PLUGIN_ROOT and PLUGIN_DATA
docs/users/extension/extension-releasing.md Releasing docs now accept plugin.json as a root manifest
docs/users/extension/introduction.md Ecosystem intro and storage layout mention Agent Plugins
packages/acp-bridge/src/status.ts Serve origin union gains AgentPlugins
packages/cli/src/commands/extensions/consent.ts Agent Plugins skip the third-party compatibility warning but keep the safety text
packages/cli/src/commands/extensions/utils.ts Adds the Origin row label to extension details
packages/cli/src/services/FileCommandLoader.ts Excludes Agent Plugins from bundled slash-command loading, keyed on format and originSource
packages/cli/src/ui/components/extensions/views/PluginDetailView.tsx Renders the Origin row when the sidecar records an originSource
packages/core/src/config/config.ts ExtensionOriginSource union gains AgentPlugins
packages/core/src/extension/agent-plugins-v1/index.ts Module barrel for the new format
packages/core/src/extension/agent-plugins-v1/manifest.ts plugin.json schema gating plus manifest validation, with a regular-file guard
packages/core/src/extension/agent-plugins-v1/mcp.ts mcp.json loader - stdio and Streamable HTTP only, single-pass variable expansion, URL and header safety, PLUGIN_DATA cwd creation
packages/core/src/extension/agent-plugins-v1/paths.ts Path containment helpers - realpath resolution and lexical within checks
packages/core/src/extension/agent-plugins-v1/skills.ts Direct-child SKILL.md loader - parsed and validated, grants nothing
packages/core/src/extension/extension-converter.ts Detection hook - marketplace selection wins over root plugin.json; carried manifests dropped from converted dirs
packages/core/src/extension/extension-store.ts Stable per-plugin PLUGIN_DATA directory keyed by a validated sha256 id
packages/core/src/extension/extensionManager.ts Install, link, update, reinstall wiring - format on Extension, link-metadata validation, realpath copy for symlinked sources
packages/core/src/extension/github.ts Records originSource through git-based installs
packages/core/src/tools/mcp-client.ts Credential-safe redirect stop for agentPluginV1 HTTP servers and launch-time stdio containment validation
packages/sdk-typescript/src/daemon/types.ts SDK origin union gains AgentPlugins
packages/cli/src/commands/extensions/utils.test.ts Tests the Origin row
packages/cli/src/services/FileCommandLoader.test.ts Pins that Agent Plugin bundled commands load nothing
packages/core/src/extension/agent-plugins-v1/manifest.test.ts Schema status gating and the non-regular manifest guard
packages/core/src/extension/agent-plugins-v1/mcp.test.ts Server loading, expansion, isolation, URL and header safety, cwd creation
packages/core/src/extension/agent-plugins-v1/skills.test.ts Skill parsing, containment, BOM and CRLF normalization
packages/core/src/extension/extension-converter.test.ts Marketplace selection precedence over root plugin.json, including future schemas
packages/core/src/extension/extensionManager.test.ts Install, link, update, reinstall flows plus symlinked source and broken-metadata isolation
packages/core/src/tools/mcp-client.test.ts Redirect stop and launch-time validation paths
…and 3 more files consent.test.ts, extension-store.test.ts, github.test.ts

Test evidence

Unattended CI run — I do not build or execute PR code; the evidence below is the PR's own CI on the reviewed commit (fetched via API), plus the two isolated lanes that ran afterwards. All pull_request-event workflow runs on this head completed green (Qwen Code CI, Qwen Live Host CI, SDK Java). The macOS/Windows Node suites and the CLI integration suite remain gated-skipped for this commit, so CI itself settles the Linux unit surface only.

Check Conclusion
Test (ubuntu-latest, Node 22.x) ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
Live Host (macos-latest) ✅ success
Real daemon E2E / Java 11 ✅ success
SDK Java (ubuntu 11/17/21, macos 21, windows 21) ✅ success
Classify PR ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success

Skipped (gated) on this commit: Test (macos-latest / windows-latest, Node 22.x), Integration Tests (CLI, No Sandbox), build-cli. / 本 commit 上被门控跳过:macOS/Windows Node 测试套件、CLI 集成测试、build-cli。

What closes the behavioural gap CI cannot:

  • Sandboxed verification (@qwen-code /verify) — ✅ passed, merge-ready verdict on this head (report earlier in this thread): the load-bearing A/B held — the base build rejects an unchanged plugin.json package, this head installs and links it with Origin: AgentPlugins.
  • Maintainer-run local E2E (@wenshao, macOS) — not an author claim: the maintainer built base and head from source and reproduced the whole Reviewer Test Plan against real stdio and Streamable HTTP servers and a live daemon, with server-side header logging. Notably: configured Authorization/Host never reached the server, cross-origin redirects stopped dead, symlink escapes were dropped at install, PLUGIN_DATA stayed stable across update/uninstall/reinstall, and a mutation A/B proved the mcp-client.ts redirect guard is load-bearing. Verdict: LGTM, followed by a formal approving review of this exact head.
  • /tmux real-user run — timed out before completing. The TUI surfaces it would have exercised (consent prompt wording, extensions-list Origin row) were instead driven in the maintainer E2E above, so this is noted, not left open.

Not verified anywhere: Windows/Linux end-to-end runtime behavior (unit tests only on those platforms), and git/npm/release install sources for Agent Plugins (local path, link, and archive were exercised). Both are acknowledged in the PR's Risk & Scope.

中文说明

代码审查(在 0f8a8ffa 上的最终一轮)

本轮独立重读了安全关键代码段,而非沿用早前轮次的结论:MCP loader 的 URL/header 策略、包容性辅助函数、mcp-client.ts 中限定作用域的重定向拦截、converter 的格式检测优先级、manager 的 link 元数据校验。没有新发现——姿态始终是 fail-closed:HTTP MCP 仅允许绝对 HTTP(S)(非 loopback 明文 HTTP、user-info、fragment 被拒绝),client-owned header 被丢弃;stdio 的 command/cwd 被限制在插件根或 PLUGIN_DATA 内且展开后复查包容性,变量展开为单趟不递归;所有边界检查先 realpath 再比较,安装时丢弃符号链接,启动时二次校验;redirect: 'manual' 仅作用于带凭据的 agentPluginV1 server,其余 MCP 配置走原路径;schema 严格门禁、marketplace 显式选择优先并清理携带的 plugin.json、link 元数据仅在 source 为非空字符串时生效(两处调用点)、PLUGIN_DATA id 校验为 64 位十六进制。两个 fix commit 的六项修复本轮逐条在当前 head 代码中重新核实(见上表)。作者承诺的后续跟进项(双 manifest 静默优先级、extensions list 空小节)均不阻塞。

测试证据

无人值守 CI 运行——不构建或执行 PR 代码。该 head 上所有 pull_request 事件工作流全绿(Qwen Code CI、Qwen Live Host CI、SDK Java);macOS/Windows Node 套件与 CLI 集成套件仍被门控跳过,CI 本身仅覆盖 Linux 单元面。CI 表格见上方标记区域。

补足 CI 无法覆盖的行为证据:沙箱验证 /verify ✅ 通过、结论 merge-ready(关键 A/B 成立:base 拒绝、head 接受未改动的 plugin.json 包);维护者 @wenshao 的本地 E2E(维护者亲自执行,非作者声明):base/head 均从源码构建,对真实 stdio 与 Streamable HTTP server、真实 daemon 复现了全部 Reviewer Test Plan,服务端 header 记录证实凭据不外泄、跨源重定向被拦截、符号链接安装时被丢弃、PLUGIN_DATA 全生命周期稳定,并对重定向防护做了变异 A/B 证明其真实有效,结论 LGTM 并对当前 head 正式批准;/tmux 运行超时,但其目标界面(consent 文案、Origin 行)已由维护者 E2E 实际演练。仍未被任何证据覆盖:Windows/Linux 端到端运行时行为(仅单元测试)、git/npm/release 安装来源——两者均已在 PR 的 Risk & Scope 中声明。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean review at this head, and both independent lanes landed green (sandboxed /verify merge-ready; maintainer E2E with LGTM). The remaining points are follow-ups, not blockers.

The previous pass deferred with four asks for @wenshao. All four are now answered, so this pass acts instead of deferring again:

  1. Core-size policy sign-off (~1,166 production lines on core paths) — answered the strongest way possible: a maintainer-run end-to-end verification followed by a formal approving review of this exact head. The escalation exists to make sure a human owns a core change of this size; a human owns it.
  2. PLUGIN_DATA after final uninstall — exercised across update/uninstall/reinstall in the maintainer E2E and accepted as designed behavior (state is meant to survive reinstall). Still worth a docs line, not a merge blocker.
  3. The mcp-client.ts redirect change (high-risk path) — statically re-verified here, and mutation-tested live: with the guard removed the plugin token crossed the redirect, with it in place the redirect target received nothing. Load-bearing, scoped to credentialed plugin servers, existing MCP configs untouched.
  4. The /verify report — passed with a merge-ready verdict on this head.

Stepping back: this is what review iteration should look like. Two adversarial /review rounds produced nine Critical findings; two fix commits resolved all nine with regression tests in +248/−11 and zero drive-by changes; and the behavioral claim was then proven by an A/B sandboxed run and a maintainer who built both sides from source. The design matches my independent proposal (self-contained format module + detection hooks, no lifecycle rewrite) and exceeds it where it matters — error isolation, containment at load and launch, fail-closed redirects, credential-safe headers. The scope stayed disciplined throughout.

Follow-ups for @callmeYe (keep them out of this PR, as agreed): file issues for the silent dual-manifest precedence (doc line or debugLogger.warn) and the empty MCP servers: section in extensions list, plus the docs line for PLUGIN_DATA persistence.

Approving, pinned to the reviewed commit. Note for the thread: this approval is the bot's latest review, so it supersedes the two stale CHANGES_REQUESTED reviews anchored to the earlier commits — GitHub's decision flips without anyone needing to dismiss them by hand.

中文说明

置信度:4/5 —— 当前 head 审查干净,两条独立证据通道均已落地且为绿(沙箱 /verify 结论 merge-ready;维护者 E2E 给出 LGTM)。剩余各点均为后续跟进项,不构成阻塞。

上一轮带着四个问题转交 @wenshao,现已全部得到回应,因此本轮直接裁决而不再 defer:1)核心规模策略签核(核心路径约 1,166 生产行)——以最强方式回应:维护者亲自端到端验证后对当前 head 正式批准;该升级项的意义在于确保有人类对这一规模的核心改动负责,现在已经有了。2)最终卸载后的 PLUGIN_DATA —— 维护者 E2E 已跨 update/uninstall/reinstall 演练并接受为设计行为(状态本就要在重装后保留),值得补一句文档,不阻塞合并。3)mcp-client.ts 重定向改动(高风险路径)——本轮静态复核,且经在线变异测试:去掉防护 token 会跨重定向泄露,保留后重定向目标收不到任何请求;防护真实有效、作用域限定于带凭据的插件 server、不影响现有 MCP 配置。4)/verify 报告 —— 在该 head 上通过,结论 merge-ready。

整体评价:这是评审迭代应有的样子。两轮对抗性 /review 产生九个 Critical 发现,两个 fix commit 以 +248/−11、零顺手改动全部解决并附回归测试;行为声明随后由 A/B 沙箱运行和一位从源码构建两侧的维护者证实。方案与我独立设想一致(自包含格式模块 + 检测钩子,不重写生命周期),且在关键处做得更好——组件级隔离、加载与启动双重包容性校验、fail-closed 重定向、凭据安全的 header 处理。范围始终克制。

@callmeYe 的后续跟进项(按约定不要塞进本 PR):为双 manifest 静默优先级(补文档或 debugLogger.warn)、extensions list 的空 MCP servers: 小节、以及 PLUGIN_DATA 持久化的文档说明分别建 issue。

批准,锚定在被审查的 commit 上。线程说明:本批准是机器人最新的评审,因此取代此前锚定在较早 commit 上的两个过期 CHANGES_REQUESTED —— GitHub 的裁决会随之翻转,无需人工 dismiss。

Qwen Code · qwen3.8-max

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

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.81% 83.81% 89.74% 83.03%
Core 87.86% 87.86% 89.44% 86.33%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.81 |    83.03 |   89.74 |   83.81 |                   
 src               |   84.97 |    81.29 |   88.49 |   84.97 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |    72.8 |    77.39 |   80.76 |    72.8 | ...1299-1303,1424 
  ...ractiveCli.ts |   86.74 |    81.15 |   88.13 |   86.74 | ...2955,2961,3026 
  ...liCommands.ts |   89.33 |     85.6 |      90 |   89.33 | ...01,518,552,674 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   71.19 |    73.65 |   90.84 |   71.19 |                   
  acpAgent.ts      |   70.59 |    73.45 |   90.37 |   70.59 | ...29,12234-12236 
  ...k-reporter.ts |     100 |    80.95 |     100 |     100 | 77,80,115,135     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.04 |    95.71 |   93.33 |   97.04 |                   
  filesystem.ts    |   97.04 |    95.71 |   93.33 |   97.04 | ...21-122,242-243 
 ...ration/session |   91.49 |    86.98 |   96.71 |   91.49 |                   
  Session.ts       |   90.51 |    85.18 |   95.94 |   90.51 | ...90,10717-10721 
  ...entTracker.ts |    96.8 |    89.36 |      90 |    96.8 | 137-143,221       
  ...projection.ts |   98.57 |    93.29 |     100 |   98.57 | ...76,333,344,356 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   93.44 |    91.74 |     100 |   93.44 | 74,85-88,115-125  
  ...y-replayer.ts |   98.54 |    95.65 |     100 |   98.54 | 241-243           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...lure-guard.ts |   98.32 |    97.75 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   96.01 |    94.15 |   96.66 |   96.01 |                   
  ...ageEmitter.ts |   95.95 |       96 |     100 |   95.95 | 52-59             
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   99.18 |    96.47 |     100 |   99.18 | 355-356           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/agent-view    |   89.03 |    81.37 |   89.09 |   89.03 |                   
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  ...sor-client.ts |   80.38 |    72.54 |   76.66 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    89.47 |   84.61 |   96.61 | 129-130,150-151   
  ...sor-runner.ts |    84.9 |     75.6 |      85 |    84.9 | ...44,468,471-481 
  ...sor-server.ts |   85.71 |    83.06 |   95.45 |   85.71 | ...67-468,471-488 
  ...isor-store.ts |   97.73 |    81.16 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |     91.3 |   83.33 |   93.98 | 228-238           
 src/commands      |   90.81 |    79.71 |   66.66 |   90.81 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.66 |      100 |      50 |   98.66 | 86                
  serve.ts         |   89.84 |    77.45 |     100 |   89.84 | ...50,853-856,868 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   88.91 |    88.49 |   90.54 |   88.91 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   95.21 |    96.73 |   88.88 |   95.21 | ...18-221,266-269 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.87 |    96.35 |     100 |   95.87 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.96 |    85.39 |   94.23 |   93.96 | ...1229,1236-1237 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.49 |    96.51 |     100 |   98.49 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    85.8 |    82.17 |      88 |    85.8 | ...85,591-594,606 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.85 |    87.73 |   87.09 |   88.85 |                   
  consent.ts       |   72.53 |    90.32 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |   75.63 |    55.55 |     100 |   75.63 | ...30-134,136-140 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.31 |    84.61 |   83.33 |   90.31 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   93.15 |    84.84 |      80 |   93.15 | ...78-180,198-199 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |    87.5 |     87.9 |   88.33 |    87.5 |                   
  agent-prompt.ts  |   93.49 |    91.68 |   97.22 |   93.49 | ...2421,2537-2617 
  base-tree.ts     |   76.16 |    80.76 |   77.77 |   76.16 | ...50-371,373-386 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   89.12 |    82.22 |   83.33 |   89.12 | ...99-504,506-507 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   96.33 |    91.85 |      96 |   96.33 | ...1916,1944-1966 
  cost-ledger.ts   |   94.67 |    95.86 |   78.57 |   94.67 | ...04-505,545-555 
  drive.ts         |   76.07 |    85.71 |   81.81 |   76.07 | ...90-492,497-499 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-pr.ts      |    76.7 |    68.75 |   63.63 |    76.7 | ...95,417,450-455 
  findings.ts      |   89.35 |    89.13 |   95.45 |   89.35 | ...15-918,927-928 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.54 |     92.3 |   66.66 |   85.54 | 67-72,131-136     
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.66 |    96.55 |     100 |   99.66 | 404               
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   81.77 |    80.86 |   92.85 |   81.77 | ...1043,1072-1074 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ish-assets.ts |   77.18 |    82.14 |   71.42 |   77.18 | ...85-531,533-544 
  repo-context.ts  |   94.92 |    90.82 |     100 |   94.92 | ...67-368,376-377 
  ...ve-anchors.ts |   77.77 |    88.88 |      75 |   77.77 | ...77-182,194-211 
  run.ts           |   82.16 |    87.12 |   91.66 |   82.16 | ...52,468-516,529 
  save-artifact.ts |    89.9 |    81.81 |   94.11 |    89.9 | ...08-311,404-407 
  script-lint.ts   |   83.67 |    78.41 |   88.88 |   83.67 | ...59-773,775-797 
  submit.ts        |    84.1 |     84.7 |    90.9 |    84.1 | ...66,555,582-618 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  test-efficacy.ts |   88.04 |    84.12 |   95.45 |   88.04 | ...2602,2610-2630 
  test-plan.ts     |   91.44 |    91.39 |   89.47 |   91.44 | ...38-839,903-920 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |   96.98 |    94.81 |   97.71 |   96.98 |                   
  agent-briefs.ts  |   98.96 |      100 |      50 |   98.96 | 719-720           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  authorization.ts |    92.4 |    92.59 |     100 |    92.4 | 127-133           
  budget.ts        |     100 |    96.29 |     100 |     100 | 370,401           
  coverage.ts      |   94.48 |    94.57 |      96 |   94.48 | ...72-489,526-537 
  deadline.ts      |   98.13 |    92.75 |     100 |   98.13 | 169-170,219,479   
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  effort.ts        |     100 |      100 |     100 |     100 |                   
  gh.ts            |   86.42 |    91.83 |      75 |   86.42 | ...52,289-290,317 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  ...ry-context.ts |   96.19 |    94.93 |     100 |   96.19 | ...90-491,496-499 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |     87.5 |     100 |     100 | 92                
  prompt-record.ts |   97.88 |    93.87 |     100 |   97.88 | 260-261,267       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   97.26 |    91.42 |     100 |   97.26 | 49-50             
  report.ts        |   94.68 |    93.75 |     100 |   94.68 | 189-193           
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 184               
  retirement.ts    |     100 |     92.3 |     100 |     100 | ...37,317-318,457 
  review-footer.ts |     100 |      100 |     100 |     100 |                   
  roster.ts        |     100 |    95.71 |     100 |     100 | 145,163,208       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.11 |    94.04 |     100 |   98.11 | 416,457,497-498   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.59 |    94.56 |     100 |   96.59 | ...08,297-298,323 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 172               
  workspaces.ts    |     100 |     95.9 |     100 |     100 | ...27,452,499,512 
  worktree.ts      |     100 |      100 |     100 |     100 |                   
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.84 |    89.73 |   96.22 |   94.84 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   88.93 |    88.59 |   83.33 |   88.93 | ...2451,2453-2461 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   96.42 |    93.22 |      95 |   96.42 | ...69-570,624-625 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |   97.43 |       50 |     100 |   97.43 | 236-239           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.87 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.27 |    92.64 |      90 |   91.27 | ...1030,1032-1033 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.47 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   80.98 |    77.27 |   84.12 |   80.98 |                   
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...31-632,635-636 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |    44.9 |    66.19 |   55.26 |    44.9 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   55.01 |    67.14 |   58.33 |   55.01 | ...15-624,639-644 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |    98.1 |    94.13 |   95.23 |    98.1 |                   
  ...putAdapter.ts |   97.98 |     93.2 |   98.07 |   97.98 | ...1415,1431-1432 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.49 |      100 |   90.47 |   98.49 | 85-86,126-127     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/runtime       |   99.61 |    95.04 |     100 |   99.61 |                   
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   87.51 |    83.77 |   90.46 |   87.51 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.43 |    93.05 |     100 |   93.43 | ...20-321,324-326 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 672               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.89 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   88.59 |    93.68 |   96.29 |   88.59 | ...95-207,451-454 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.27 |     85.2 |     100 |   87.27 | ...10,816-820,838 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.42 |    84.44 |    97.1 |   92.42 | ...1466,1520-1524 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.1 |    77.83 |   94.73 |    90.1 | ...1014,1021-1026 
  daemon-logger.ts |    82.2 |    77.42 |   91.76 |    82.2 | ...1720,1747-1753 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.57 |     90.8 |     100 |   98.57 | ...1411,1413-1414 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    86.95 |     100 |   92.06 | ...72,287-293,316 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.89 |    90.25 |     100 |   94.89 | ...24,702,718,728 
  fast-path.ts     |   90.99 |    81.38 |   95.45 |   90.99 | ...33-542,608-609 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-144             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...30-131,142-143 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   83.96 |    80.01 |   75.26 |   83.96 | ...7435,7441-7442 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.22 |    88.99 |     100 |   94.22 | ...27,531-532,572 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   90.58 |    91.18 |   71.81 |   90.58 | ...2718,2732-2736 
  ...-admission.ts |   98.24 |    94.73 |     100 |   98.24 | 79-80,303-304     
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |    93.3 |    76.83 |     100 |    93.3 | ...20,823,836-838 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   92.18 |    88.37 |     100 |   92.18 | ...21-224,267-270 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   93.89 |     87.5 |     100 |   93.89 | ...18-519,525-526 
  ...e-remember.ts |   98.23 |    92.51 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   83.98 |    90.29 |     100 |   83.98 | ...48-156,216-237 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.09 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   77.89 |    79.56 |   93.03 |   77.89 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |    98.2 |    88.55 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   73.19 |    76.77 |      94 |   73.19 | ...5165,5213-5219 
  index.ts         |   82.23 |    80.11 |   91.07 |   82.23 | ...2341,2425-2426 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 src/serve/fs      |   86.39 |    80.74 |     100 |   86.39 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |     73.8 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.42 |    89.18 |     100 |   90.42 | 161-169           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   86.16 |    79.55 |     100 |   86.16 | ...2510,2520-2521 
 src/serve/live    |   77.28 |    69.21 |   89.91 |   77.28 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  ...-workspace.ts |   88.63 |    82.53 |     100 |   88.63 | ...40-241,253-254 
  discovery.ts     |   85.77 |    76.92 |      90 |   85.77 | ...49-250,255-256 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.75 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |   45.17 |    81.96 |   68.18 |   45.17 | ...80-381,395-407 
  ...oordinator.ts |   76.17 |     64.4 |   85.36 |   76.17 | ...1858,1949-1950 
  ...controller.ts |   67.82 |    79.31 |   72.72 |   67.82 | ...66-278,287-295 
  ...ak-to-user.ts |   96.66 |      100 |   83.33 |   96.66 | 37-38             
  ...sk-service.ts |   86.22 |    59.64 |   93.33 |   86.22 | ...1152,1175-1182 
  ...task-tools.ts |      99 |      100 |   85.71 |      99 | 205-206           
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.83 |    77.58 |     100 |   94.83 | ...18,327-330,350 
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/serve/routes  |   85.52 |    79.98 |   94.72 |   85.52 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   86.45 |       88 |     100 |   86.45 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   95.65 |    88.88 |     100 |   95.65 | 63-67,186         
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |    82.4 |    71.42 |     100 |    82.4 | ...-94,96-101,121 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.29 |    82.94 |   92.59 |   87.29 | ...1275,1318-1319 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.41 |    81.79 |   91.04 |   85.41 | ...4730,4732-4733 
  sse-events.ts    |   86.82 |    85.71 |   94.11 |   86.82 | ...16-927,930,937 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.92 |    79.69 |     100 |   90.92 | ...81-482,501-502 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.15 |    74.95 |   92.98 |   88.15 | ...2027,2072-2073 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   84.44 |    64.51 |     100 |   84.44 | ...73-275,355-357 
  ...t-branches.ts |   75.43 |    66.66 |     100 |   75.43 | ...13-618,627-634 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    93.18 |     100 |     100 | 52,77,188         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...management.ts |   87.41 |    84.13 |     100 |   87.41 | ...1660,1680-1685 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.04 |    72.99 |     100 |   75.04 | ...79-690,696-697 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.9 |    87.15 |     100 |    76.9 | ...29-354,360-394 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.92 |    66.21 |      80 |   78.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |    90.8 |     88.4 |   96.57 |    90.8 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |    86.5 |    72.34 |     100 |    86.5 | ...47,764,827-836 
  fs-factory.ts    |     100 |    92.59 |     100 |     100 | 34,42,103,159     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.13 |    95.09 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |      95 |     87.5 |     100 |      95 | 182-188           
  ...on-archive.ts |   89.55 |    87.83 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   99.02 |    97.44 |     100 |   99.02 | ...25,639,781-783 
 src/serve/voice   |    92.7 |    91.48 |   97.67 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   90.65 |    87.73 |   91.11 |   90.65 |                   
  index.ts         |   90.13 |    87.04 |   89.74 |   90.13 | ...1464-1468,1471 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.49 |    89.26 |      98 |   92.49 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 105-118           
  ...killLoader.ts |   97.19 |    85.29 |     100 |   97.19 | 142,153-154       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   87.09 |    83.07 |     100 |   87.09 | ...35-340,345-350 
  ...omptLoader.ts |   79.55 |    88.29 |   83.33 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.77 |    92.15 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.23 |    86.48 |     100 |   88.23 | ...94-199,232-233 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.89 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |     86.8 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.77 |   94.73 |   88.28 | ...1362,1366-1373 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.09 |    79.16 |   77.77 |   94.09 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   73.08 |    75.43 |   67.41 |   73.08 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   74.29 |    72.05 |   68.57 |   74.29 | ...4112,4228-4234 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   70.08 |    71.73 |   66.66 |   70.08 | ...01,324,377-382 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   58.53 |    66.18 |   51.06 |   58.53 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.21 |    70.73 |   57.69 |   60.21 | ...90,794,803,806 
  useAuth.ts       |    94.6 |    73.52 |     100 |    94.6 | ...21-222,241-247 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   82.67 |    83.11 |   89.15 |   82.67 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...24-125,133-142 
  ...essCommand.ts |   68.06 |    54.05 |      75 |   68.06 | ...96-197,211-214 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   69.07 |     72.6 |   84.61 |   69.07 | ...78-611,622-623 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   82.97 |    78.57 |     100 |   82.97 | 47-52,67-70,91-96 
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   72.81 |    86.84 |   66.66 |   72.81 | ...63-168,277-280 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   94.44 |    90.14 |     100 |   94.44 | ...13-214,241-251 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   84.78 |    82.47 |     100 |   84.78 | ...1071,1105-1110 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   89.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |   90.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   92.92 |       85 |   66.66 |   92.92 | ...72-177,276-281 
 src/ui/components |   71.52 |    79.07 |   79.85 |   71.52 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   88.65 |    90.41 |     100 |   88.65 | ...84-286,300-302 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-72,84,139,153 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-598             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   76.99 |    66.66 |      50 |   76.99 | ...96,233,255-260 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.28 |    66.99 |     100 |   79.28 | ...08,511,514-520 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   83.26 |    82.23 |      80 |   83.26 | ...2231,2257,2331 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   96.28 |     94.8 |      50 |   96.28 | ...01,459-463,466 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   81.95 |    71.27 |     100 |   81.95 | ...1045,1050-1066 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   95.67 |    87.09 |     100 |   95.67 | ...24-125,275-277 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |   85.34 |    84.91 |   92.98 |   85.34 |                   
  ...sksDialog.tsx |   81.87 |    82.77 |   85.71 |   81.87 | ...1853,1965-1971 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |    50.7 |    52.38 |   20.83 |    50.7 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.24 |      100 |       0 |    9.24 | 40-67,70-163      
 ...mponents/hooks |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.26 |    86.89 |   85.57 |   90.26 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.11 |    95.91 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.63 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.06 |    86.32 |   93.75 |   93.06 | ...1037,1082-1084 
 ...ponents/shared |   86.29 |    82.41 |   94.17 |   86.29 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.95 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.16 |    81.83 |   85.13 |   84.16 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 235-236           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   85.42 |    82.97 |   87.71 |   85.42 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...87-288,293-294 
  ...dProcessor.ts |   85.75 |     68.4 |   81.81 |   85.75 | ...1464,1485-1489 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...ng-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      42 |       75 |     100 |      42 | 42-44,53-59,62-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.45 |    83.01 |     100 |   95.45 | ...60-161,285-288 
  ...ompletion.tsx |   97.09 |    87.09 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |   57.89 |    71.42 |      50 |   57.89 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   86.08 |    81.23 |   76.92 |   86.08 | ...5198-5200,5202 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.38 |    98.85 |     100 |   98.38 | 141-144           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.4 |     100 |     100 | 175,262           
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.48 |    88.88 |     100 |   89.48 | ...54-456,489-499 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.26 |    77.14 |     100 |   95.26 | 120-121,223-228   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.26 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    91.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   87.13 |    85.34 |   95.62 |   87.13 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   79.84 |     75.6 |     100 |   79.84 | ...66,270,328-329 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.38 |    81.91 |   95.23 |   92.38 | ...43-746,799-804 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |    52.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.38 |    92.38 |     100 |   98.38 | 108,136-137,343   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.18 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.42 |       95 |     100 |   91.42 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |   96.03 |     97.1 |     100 |   96.03 | 103-106           
  ...mage-parts.ts |   97.75 |    94.87 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   82.73 |    79.48 |     100 |   82.73 | ...84-606,737-738 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.94 |    95.45 |   94.11 |   97.94 | ...82-283,443-444 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   90.42 |    92.85 |     100 |   90.42 | ...06-207,240-241 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |     60.3 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    66.38 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.27 |    79.92 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |    81.4 |    87.03 |   92.57 |    81.4 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       95 |     100 |     100 | 72                
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |    89.65 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...64,381-382,427 
  jsonc-editor.ts  |   93.18 |    92.66 |     100 |   93.18 | ...80-381,384-385 
  languageUtils.ts |   98.88 |    97.05 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   86.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.87 |    56.93 |   76.92 |   45.87 | ...1040,1052-1075 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       90 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   91.63 |    91.02 |      95 |   91.63 |                   
  cleanup.ts       |   95.77 |    95.83 |     100 |   95.77 | 70-72             
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   91.91 |    90.47 |    87.5 |   91.91 | 58-62,73,131-135  
  throttledOnce.ts |   86.66 |     86.2 |     100 |   86.66 | ...99,105,137-138 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.86 |    86.33 |   89.44 |   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.3 |    86.85 |   73.79 |    84.3 | ...8356,8360-8361 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.34 |    88.04 |   93.26 |   92.34 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   91.95 |    87.18 |   91.56 |   91.95 | ...3928,4026-4027 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6215,6243-6259 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.3 |     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.71 |    84.62 |   92.57 |   87.71 |                   
  ...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.94 |    86.26 |   97.91 |   90.94 | ...1230-1236,1280 
  ...ionManager.ts |   83.89 |    82.86 |   81.72 |   83.89 | ...2832,2861-2862 
  ...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.71 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.48 |    82.71 |     100 |   90.48 | ...4,994-995,1005 
  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 
 ...ent-plugins-v1 |   84.94 |    79.51 |     100 |   84.94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  manifest.ts      |   81.87 |    84.48 |     100 |   81.87 | ...55-156,161-174 
  mcp.ts           |   84.98 |    79.56 |     100 |   84.98 | ...88-389,419-420 
  paths.ts         |     100 |    94.44 |     100 |     100 | 59                
  skills.ts        |   82.31 |    63.88 |     100 |   82.31 | ...38-141,150-151 
 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.24 |   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 |    87.91 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.12 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.83 |    83.81 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |     79.1 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.62 |   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 |       44 |   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.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.67 |    84.57 |   96.91 |   89.67 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   98.49 |    87.28 |     100 |   98.49 | 75-76,99,470-471  
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   91.41 |    85.15 |   95.65 |   91.41 | ...2116,2143-2144 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    93.93 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...41,467-474,519 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |    90.85 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   82.45 |    74.11 |   97.61 |   82.45 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.79 |    83.72 |   97.18 |   88.79 | ...2477,2553-2573 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.73 |    83.57 |   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 |     87.5 |   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.53 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.35 |   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 |    85.07 |   88.72 |   86.24 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   80.03 |    86.58 |   89.47 |   80.03 | ...2272,2276-2279 
  ...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 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.69 |    77.08 |   81.25 |   85.69 | ...95-911,957-958 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5035,5098-5099 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   93.11 |    92.53 |   91.66 |   93.11 | ...69-570,586-592 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |    86.7 |    84.92 |   88.88 |    86.7 | ...24-827,864-899 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.22 |    87.68 |   88.69 |   87.22 |                   
  agent.ts         |   85.84 |    86.59 |   86.31 |   85.84 | ...4315,4337-4347 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   86.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.89 |    89.62 |   96.87 |   92.89 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   83.01 |    95.03 |    61.9 |   83.01 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.95 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |     93.1 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.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.34 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       64 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |    87.5 |    86.02 |     100 |    87.5 | ...76-480,510-525 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   96.74 |    91.04 |     100 |   96.74 | ...69,196,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

@callmeYe

Copy link
Copy Markdown
Collaborator Author

@qwen-code /verify

@callmeYe

Copy link
Copy Markdown
Collaborator Author

@qwen-code /tmux

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 569 passed · 0 failed · 569 total

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

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

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

Verification report

PR 8834 Deep Verification — feat(extensions): support Agent Plugins v1

Verdict: merge-ready — 569/569 scripted assertions passed, 0 failed.
Verified head: 7900328422b11a314e94ba679757e4e3bccdc28e (single commit, reachable locally and matching the metadata snapshot), merged onto base 57e6c31030ae432781df145f488a147f5d408810.

中文摘要
  • 结论:merge-ready。569 个脚本化断言全部通过(A/B 25、安全矩阵 68、HTTP/stdio 实物 wire 测试 12、受影响测试套件 457、变异测试 7)。
  • A/B 结论(核心主张成立):对同一个未改动的 Agent Plugins v1 包(plugin.json + skill + stdio/HTTP MCP),HEAD 构建可安装/链接,Origin: AgentPlugins,发现 skill,仅加载 stdio 与 Streamable HTTP 两个 server(SSE 被跳过),安装产物与源文件逐字节一致且不生成 qwen-extension.jsonPLUGIN_DATA 在更新与重装后保持不变;BASE 构建对同一包在安装和链接时都精确复现 PR 描述中的失败 Configuration file not found .../qwen-extension.json,而同一 BASE 构建安装普通 qwen-extension.json 扩展成功(双臂阳性对照,证明失败专属于新格式)。
  • 安全面验证:URL 网关(含 http://2130706433/、全角点、尾点、IPv4-mapped、同形域名等 17 种形态)、client-owned header 丢弃、重定向凭据不外泄(真实 loopback 双服务器对)、插件根路径收敛(符号链接逃逸、.. 命令/cwd 逃逸、保留环境变量覆盖)、单个非法组件不禁用合法兄弟组件——全部按设计 fail-closed。真实 MCP stdio 连接确认子进程收到展开后的 PLUGIN_ROOT/PLUGIN_DATA/自定义 env 与 cwd。
  • 测试钉住行为:对 7 个关键守卫做单点变异,全部被 PR 新增测试杀死(含一次粗变异存活后升级为细变异 M5b 杀死);唯一存活变异说明 copyExtension 中的显式符号链接早退子句相对 lstat+类型过滤是冗余防线(见 Finding 2,nit)。
  • Findings:1 个 Suggestion(重定向凭据守卫仅作用于 Agent Plugin server,普通扩展的既有转发行为依旧存在,属既有行为而非本 PR 引入)+ 2 个 nit。无阻塞项。
  • 未覆盖:见报告 Not covered(Windows 行为、真实 GitHub/归档安装链路、仓库级 lint/typecheck、真实 CLI 二进制端到端)。

Central claim + A/B

Central claim: an unchanged Agent Plugins v1 package (plugin.json with the
canonical $schema) installs and links through the existing extension lifecycle
without conversion — identified as AgentPlugins, with portable skills and
stdio/Streamable HTTP MCP servers loaded, stable PLUGIN_DATA, and no
generated qwen-extension.json — where base fails with
Configuration file not found .../qwen-extension.json.

Both arms run the identical harness (ab-install.mjs) against compiled dist
output; the only difference between cells is the build. Evidence:
01-ab-head-install-link.png, 02-ab-base-install-link.png.

cell oracle base (57e6c310) head (79003284)
control: qwen-extension installs (both arms) install succeeds, name ctrl-ext ✅ PASS ✅ PASS
install-local agent plugin install result Configuration file not found .../qwen-extension.json (expected red = assertion PASS) ✅ installed
link agent plugin link result ❌ same error (expected red = PASS) ✅ linked, path === source
origin / version / skills metadata + discovery AgentPlugins, 1.0.0 default, [greet]
non-portable capabilities inactive commands/agents/context/hooks/settings/channels ✅ all empty/undefined
MCP gating loaded server keys [local, remote] (sse skipped)
PLUGIN_ROOT/PLUGIN_DATA/args expansion env values vs realpath ✅ expanded, data dir outside package
byte-identical package, no qwen-extension.json, escaping symlink dropped file comparison ✅ 4/4 files identical
consent payload originSource, skill list AgentPlugins
update + reinstall keep PLUGIN_DATA same path, state.txt survives ✅ both
link manifest fingerprint refreshCacheIfSourcesChanged + reload ✅ edit → detected → version 9.9.9 reloaded

Counts: head 21/21, base 4/4 (the two base reds are expected-failure
assertions and count as passes). 25/25 A/B assertions.

Secondary claims verified:

  • Security surface (security-matrix.mjs, 68/68 — 03-security-matrix.png):
    URL gate across 17 accept/reject shapes including http://2130706433/,
    http://127.1/, trailing-dot, ideographic-dot , Arabic-Indic digits,
    localhost.evil.com, [::ffff:127.0.0.1], userinfo/fragment/file/ftp;
    client-owned header drop, duplicate/control-char/invalid-name headers;
    stdio containment (./bin/../../evil, absolute commands, ${PLUGIN_*} and
    absolute cwd escapes, reserved-env overrides); skills (nested not
    discovered, symlinked dir skipped, name/description/frontmatter rules,
    allowed-tools validated but not granted); manifest/schema gating
    (unsupported version explicit, unrelated schema falls through, escaping
    plugin.json symlink rejects rather than falls back). Every invalid entry
    was isolated — valid siblings always loaded.
  • Redirect credential guard (http-wire.mjs, 4/4 against real loopback
    redirector/target pair — 04-http-redirect-wire.png): with configured
    headers or request Authorization, the redirect is stopped (redirect: manual) and the target server receives zero requests; without secrets
    the redirect still follows; non-agent-plugin servers keep pre-existing
    follow-and-forward behavior (see Finding 1).
  • Real MCP connection (stdio-wire.mjs, 8/8 — 05-stdio-mcp-wire.png):
    a real @&#8203;modelcontextprotocol/sdk stdio server spawned via
    createTransport from the normalized config reports back the env it
    actually received: expanded PLUGIN_ROOT, PLUGIN_DATA, custom env, and
    cwd inside PLUGIN_DATA; a tampered config missing runtime roots is
    rejected before spawn.
  • Tests are load-bearing (mutations.mjs, 7/7 kills —
    06-mutation-matrix.png): converter AgentPlugins branch, HTTP loopback
    gate, client-owned-header drop, redirect guard, reserved-env check, consent
    origin exemption, and symlink-free copy (M5b) each turn exactly their pinned
    PR test red with a behavioral assertion (e.g. M5b:
    AssertionError: expected true to be false on the outside-link existence
    check). Unmutated suites green (positive control for every suite).

Corrections

None — no prior round or bot claims needed correction.

Findings

No blocking findings. Three reviewer-worthy observations, ordered:

  1. Suggestion — redirect credential hardening is scoped to Agent Plugins
    only (pre-existing sibling left open).
    http-wire.mjs cell
    c4-ordinary-extension-unchanged proves that for a non-agent-plugin
    streamable-http config, a redirect from the configured host is still
    followed with the request headers forwarded to the target
    (x-api-key observed at the redirect target). This is pre-existing
    behavior — the base build has the same fetch path and the PR explicitly
    gates the guard on agentPluginV1 === true — so it is not a regression
    and not attributable to this PR. Naming it because it is the same defect
    class this PR chose to close; generalizing the guard later would be a
    behavior change for ordinary extensions and deserves its own discussion.
    Repro: node http-wire.mjs packages/core/dist (cell c4 row).
  2. Nit — one redundant clause in copyExtension's symlink handling (dead
    guard, defense-in-depth).
    Mutation M5 (disabling only
    if (options.skipSymlinks && stats.isSymbolicLink()) return false;)
    survived: with skipSymlinks, the filter already lstats and admits
    only isFile() || isDirectory(), which a symlink is not, so the early
    return changes nothing. The behavior itself IS pinned — the finer mutation
    M5b (reverting to dereference: true + stat) is killed by the install
    test's outside-link assertion. Classifying per the mutation protocol:
    the clause is redundant dead code, not a coverage gap; removing it or
    keeping it as a named invariant are both fine.
  3. Nit — URL-gate over/under-reach documentation. Two shapes resolve
    differently than a string-reading suggests, both safely:
    http://[::ffff:127.0.0.1]/ (IPv4-mapped loopback) is rejected
    (fail-closed over-rejection), while http://2130706433/ and http://127.1/
    are accepted because WHATWG URL — the same implementation used by
    both the validator and fetch/undici — normalizes them to 127.0.0.1
    before either validation or connection, so there is no
    parser-differential bypass. No change requested; worth a line in the
    design doc so the next reviewer does not flag the decimal form.

Not covered

  • Windows behavior (PR self-reports ⚠️): reservedEnvironmentName
    case-folding, path.win32 bare-command root check, and backslash rejections
    were verified by code reading and unit tests only; this run is Linux, which
    also partially fills the PR's Linux E2E gap (real install/link/connect ran
    here).
  • Real GitHub / archive / npm install transports: exercised only through
    the PR's mocked unit tests (100 github tests green); no network fetch in
    this sandbox. The local-source path — the one the A/B targets — ran for real.
  • Full CLI binary E2E (qwen extensions install <dir>): the lifecycle was
    driven at the ExtensionManager API level (the exact code the CLI calls);
    CLI-side surfaces are covered by the consent/utils/PluginDetailView unit
    tests in the gate.
  • Repo-wide lint/typecheck/test: not re-run (PR CI covers them); gates
    here were the affected test files only (457 tests).
  • Per-commit attribution: trivially satisfied — the snapshot lists one
    commit and exactly that commit (79003284) is locally reachable between
    HEAD^1..HEAD^2 in the depth-2 checkout.
  • previous-report.md: absent — first verification round.

Methodology

Environment: the CI verify container (node:22-bookworm), working tree at
refs/pull/8834/merge (depth 2), npm ci + npm run build pre-run at HEAD.
A/B: git worktree add tmp/base-tree HEAD^1, rebuilt only
packages/core inside it (tsc --build emitted despite pre-existing
standalone type errors in files untouched by the PR — runtime JS complete;
packages/core has no internal workspace deps, and its non-hoisted external
deps were linked in from the root install, valid because the PR changes
neither package.json nor the lockfile). The harness imports each arm's
dist by explicit file URL and asserts the loaded module's realpath is inside
the arm's tree (control-loaded-from-dist-root, both arms). Wire harnesses
use real loopback HTTP servers and a real @modelcontextprotocol/sdk stdio
server — no stubs of code under test. Mutations were applied one at a time
in-tree, each followed by its pinned vitest file and git restore (final
git status clean). Harnesses, per-mutation logs, and the base build log
live alongside this report (*.mjs, logs/); six evidence captures in
evidence/. Assertion accounting: A/B 25 + security matrix 68 + HTTP wire 4 +
stdio wire 8 + vitest gates 457 + mutation kills 7 = 569 executed, 0 failed.

Evidence images

01-ab-head-install-link

02-ab-base-install-link

03-security-matrix

04-http-redirect-wire

05-stdio-mcp-wire

06-mutation-matrix

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

tmux real-user testing: timeout - workflow run

The tmux test did not complete before the time limit. This is not a pass/fail result for the affected flow; see the workflow run and artifacts for details.

Full tmux transcript


===== 00 initial ready screen =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>   Type your message or @path/to/file
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ➜ workspace · git:(6c1e3c8) · fake-model
  Auto mode (shift + tab to cycle)
































===== 01 extensions manage view (empty state) =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
  │  Installed    Discover    Sources   (Tab / ←→ to switch)                                         │
  │                                                                                                  │
  │ No plugins or MCP servers installed.                                                             │
  │ Use the Discover tab to find and install plugins.                                                │
  │                                                                                                  │
  │ ↑↓ navigate · Space enable/disable · f favorite · Enter details · Esc close                      │
  └──────────────────────────────────────────────────────────────────────────────────────────────────┘







































===== 01b extensions dialog rendered - empty Installed tab =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
  │  Installed    Discover    Sources   (Tab / ←→ to switch)                                         │
  │                                                                                                  │
  │ No plugins or MCP servers installed.                                                             │
  │ Use the Discover tab to find and install plugins.                                                │
  │                                                                                                  │
  │ ↑↓ navigate · Space enable/disable · f favorite · Enter details · Esc close                      │
  └──────────────────────────────────────────────────────────────────────────────────────────────────┘







































===== 02 install result =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions

  > /extensions install /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin
  ●︎ Installing extension from "/__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin"...
  ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
  │                                                                                                  │
  │  Installing extension "demo-agent-plugin".                                                       │
  │  Agent Plugins v1 fixture for tmux verification of PR 8834.                                      │
  │  Extensions may introduce unexpected behavior. Ensure you have investigated the extension        │
  │  source and trust the author.                                                                    │
  │  This extension will run the following MCP servers:                                              │
  │     * probe (local): node /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-06245  │
  │       9/fixture/demo-agent-plugin/server/mcp-probe.js                                            │
  │  This extension will install the following skills:                                               │
  │     * hello-world: Greets the user for the demo agent plugin fixture. Used to verify Agent       │
  │       Plugins v1 direct-child skill loading in tmux tests.                                       │
  │                                                                                                  │
  │  Do you want to continue?                                                                        │
  │                                                                                                  │
  │  › 1. Yes                                                                                        │
  │    2. No                                                                                         │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯


===== 03 consent dialog before approving =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions

  > /extensions install /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin
  ●︎ Installing extension from "/__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin"...
  ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
  │                                                                                                  │
  │  Installing extension "demo-agent-plugin".                                                       │
  │  Agent Plugins v1 fixture for tmux verification of PR 8834.                                      │
  │  Extensions may introduce unexpected behavior. Ensure you have investigated the extension        │
  │  source and trust the author.                                                                    │
  │  This extension will run the following MCP servers:                                              │
  │     * probe (local): node /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-06245  │
  │       9/fixture/demo-agent-plugin/server/mcp-probe.js                                            │
  │  This extension will install the following skills:                                               │
  │     * hello-world: Greets the user for the demo agent plugin fixture. Used to verify Agent       │
  │       Plugins v1 direct-child skill loading in tmux tests.                                       │
  │                                                                                                  │
  │  Do you want to continue?                                                                        │
  │                                                                                                  │
  │  › 1. Yes                                                                                        │
  │    2. No                                                                                         │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  │                                                                                                  │
  ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯


===== 04 install result after consent =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions

  > /extensions install /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin
  ●︎ Installing extension from "/__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin"...
  ●︎ Extension "demo-agent-plugin" installed successfully.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>   Type your message or @path/to/file
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ➜ workspace · git:(6c1e3c8) · fake-model
  Auto mode (shift + tab to cycle)








































===== 05 extensions list text output =====

   ▄▄▄▄▄▄  ▄▄     ▄▄ ▄▄▄▄▄▄▄ ▄▄▄    ▄▄   ┌──────────────────────────────────────────────────────────┐
  ██╔═══██╗██║    ██║██╔════╝████╗  ██║  │ >_ Qwen Code (v0.21.8)                                   │
  ██║   ██║██║ █╗ ██║█████╗  ██╔██╗ ██║  │                                                          │
  ██║▄▄ ██║██║███╗██║██╔══╝  ██║╚██╗██║  │ API Key | fake-model (/model to change)                  │
  ╚██████╔╝╚███╔███╔╝███████╗██║ ╚████║  │ /__w/.../workspace                                       │
   ╚══▀▀═╝  ╚══╝╚══╝ ╚══════╝╚═╝  ╚═══╝  └──────────────────────────────────────────────────────────┘

  Tips: Type / to open the command popup; Tab autocompletes slash commands and saved prompts.
  ●︎ Auto mode enabled.
       An LLM classifier evaluates each tool call — safe actions auto-approve,
       risky ones are blocked. Exit: Shift+Tab or /approval-mode default.
  ●︎ Extensions changed on disk. Run /reload-plugins to apply updates.

  > /extensions

  > /extensions install /__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin
  ●︎ Installing extension from "/__w/qwen-code/qwen-code/tmp/pr8834-agent-plugins-tmux-20260810-062459/fixture/demo-agent-plugin"...
  ●︎ Extension "demo-agent-plugin" installed successfully.

  > /extensions list
  ●︎ Installed Extensions (1 total, 1 active)

    - [✓] demo-agent-plugin [1 MCP servers, 1 skills]
      Agent Plugins v1 fixture for tmux verification of PR 8834.


────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
>   Type your message or @path/to/file
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ➜ workspace · git:(6c1e3c8) · fake-model
  Auto mode (sh

...truncated -- full log in the run artifacts.

Qwen Code · tmux real-user testing

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

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — Test (windows-latest / macos-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only (the Windows gap is the subject of finding R1-1).

Not explored to full depth (tool budget reached): You are review agent reverse-audit — Reverse audit agen...: (none — all planned checks completed within budget).

中文说明

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — Test (windows-latest / macos-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only (the Windows gap is the subject of finding R1-1)。

未探索到全部深度(达到工具调用预算):You are review agent reverse-audit — Reverse audit agen...:(none — all planned checks completed within budget)

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

Comment thread packages/core/src/extension/agent-plugins-v1/mcp.test.ts Outdated
Comment thread packages/core/src/extension/extensionManager.ts
Comment thread packages/core/src/extension/extensionManager.ts
Comment thread packages/core/src/extension/agent-plugins-v1/manifest.ts
Comment thread packages/core/src/extension/extensionManager.ts
Comment on lines +1387 to +1390
let config = loadedManifest.config;
if (loadedManifest.format === 'qwen') {
config = resolveEnvVarsInObject(config);
}

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] Untested changed behavior (mutation-verified): the deliberate exemption of Agent Plugins configs from resolveEnvVarsInObject (gated to format 'qwen') has no test — no fixture puts $VAR/${VAR} in a portable manifest field. Mutation: removing the gate leaves all 145 tests green; probe: with the gate gone, a manifest description: "Uses ${R114_PROBE_VAR}" is rewritten from process.env at load — Concrete cost: the 'portable files are left unchanged' contract silently breaks; a future refactor drops the guard and plugin manifests get env-substituted, suite green.

Fix: in an install/load test, stub an env var and give plugin.json a description/version containing ${THAT_VAR}; assert the loaded config retains the literal placeholder.

中文说明

未测试的变更行为(已突变验证):Agent Plugins 配置有意豁免 resolveEnvVarsInObject(门控为 'qwen' 格式)这一行为没有测试——没有 fixture 在可移植清单字段中放 $VAR/${VAR}。突变:移除门控后全部 145 个测试仍绿;探针:移除门控后,清单 description: "Uses ${R114_PROBE_VAR}" 会在加载时被 process.env 重写。具体代价:'可移植文件保持不变'的契约被静默破坏;未来重构删除该防护后插件清单会被环境变量替换,套件绿灯。修复:在安装/加载测试中 stub 一个环境变量,给 plugin.json 的 description/version 加入 ${THAT_VAR},断言加载后的配置保留字面占位符。

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

Comment on lines +1195 to +1198
const effectiveRoot =
installMetadata?.type === 'link'
? installMetadata.source
: extensionRoot;

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] Untested changed behavior (trace-verified): change detection for linked extensions in this fingerprint rewrite is only tested for Agent Plugins — the only type: 'link' installs through ExtensionManager in the suite are the new agent-plugin tests; every refreshCacheIfSourcesChanged test uses qwen-format extensions written directly into the extensions dir (no linked installs). The linked branch (sidecar read, effectiveRoot from installMetadata.source, manifest selection) is all new in this PR — Concrete cost: a regression in the linked-entry branch (e.g. stamping a nonexistent manifest when metadata is absent, or an always-constant stamp) breaks refreshCacheIfSourcesChanged for linked qwen extensions — edits to the linked source are never picked up — with no failing test.

Fix: add a test: link a qwen-format extension, edit its qwen-extension.json at the source path, expect refreshCacheIfSourcesChanged() true then the new version loaded.

中文说明

未测试的变更行为(已溯源验证):这次指纹重写中链接扩展的变更检测只为 Agent Plugins 测试过——套件中唯一通过 ExtensionManager 的 type: 'link' 安装就是新的 agent-plugin 测试;所有 refreshCacheIfSourcesChanged 测试都使用直接写入扩展目录的 qwen 格式扩展(无链接安装)。链接分支(sidecar 读取、来自 installMetadata.source 的 effectiveRoot、清单选择)都是本 PR 新增。具体代价:链接条目分支的回归(如元数据缺失时戳记不存在的清单,或戳记恒为常量)会破坏链接 qwen 扩展的 refreshCacheIfSourcesChanged——对链接源的编辑永远不会被拾取——且没有失败测试。修复:新增测试:链接一个 qwen 格式扩展,在源路径编辑其 qwen-extension.json,期望 refreshCacheIfSourcesChanged() 为 true 且新版本被加载。

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

Comment on lines +1206 to +1213
try {
manifestPath = resolveContainedExistingPath(
effectiveRoot,
manifestPath,
);
} catch {
followManifestSymlink = false;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Untested changed behavior (mutation-verified): this containment fallback for a symlinked plugin.json has no test — plugin.json symlinks appear only in manifest.test.ts (helper-level), and the linked-plugin fingerprint test uses a plain-file manifest. The path is reachable: an escaping-symlink plugin.json classifies as 'supported', so the loop takes this branch. Two mutants survive the whole suite: (1) deleting the try/catch makes extensionDirFingerprint throw → every refreshCacheIfSourcesChanged status read rejects; (2) dropping the followManifestSymlink wiring makes stampPath follow the escaping symlink and stamp the out-of-root target (probe: stamp flips from the link's own metadata to the outside file's) — Concrete cost: either regression ships green — status reads breaking, or the fingerprint coupled to unrelated external file edits.

Fix: add a case where a linked plugin's plugin.json symlinks outside the source root: assert fingerprinting does not throw and refreshCacheIfSourcesChanged() stays stable.

中文说明

未测试的变更行为(已突变验证):符号链接 plugin.json 的这个包含性回退没有测试——plugin.json 符号链接只出现在 manifest.test.ts(辅助函数层级),链接插件指纹测试使用纯文件清单。该路径可达:逃逸符号链接的 plugin.json 会被分类为 'supported',循环因此进入此分支。两个突变体在整个套件中存活:(1) 删除 try/catch 会使 extensionDirFingerprint 抛错 → 每次 refreshCacheIfSourcesChanged 状态读取都 reject;(2) 去掉 followManifestSymlink 接线会使 stampPath 跟随逃逸符号链接并戳记根外目标(探针:戳记从链接自身元数据翻转为外部文件元数据)。具体代价:任一回归都会绿灯通过——状态读取损坏,或指纹与无关外部文件编辑耦合。修复:新增用例:链接插件的 plugin.json 符号链接到源根外,断言指纹计算不抛错且 refreshCacheIfSourcesChanged() 保持稳定。

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

Comment on lines +62 to +64
} else if (agentPluginStatus === 'supported') {
originSource = 'AgentPlugins';
} else if (fs.existsSync(configFilePath)) {

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] Untested changed behavior (mutation-verified): the documented precedence 'supported plugin.json beats an existing qwen-extension.json' (design doc, Compatibility) has no test pinning it — the three new converter tests cover supported plugin.json alone, unsupported + qwen-extension.json, and unrelated + qwen-extension.json; none writes a supported plugin.json alongside qwen-extension.json. Mutation: reordering the chain so the qwen manifest is checked before the 'supported' branch leaves all three tests green, and a directory with both manifests then installs as QwenCode — Concrete cost: a future refactor silently inverts the precedence (different origin, different activated components), no test fires.

Fix: add a converter test that writes both a supported plugin.json and a qwen-extension.json into the same root and asserts convertCompatibleExtension resolves with originSource 'AgentPlugins'.

中文说明

未测试的变更行为(已突变验证):文档声明的优先级"受支持的 plugin.json 优先于已存在的 qwen-extension.json"(设计文档 Compatibility 节)没有测试固定——三个新 converter 测试分别覆盖:单独的受支持 plugin.json、unsupported + qwen-extension.json、unrelated + qwen-extension.json;没有一个同时写入受支持 plugin.json 和 qwen-extension.json。突变:调整链顺序使 qwen 清单先于 'supported' 分支检查后三个测试全绿,此时含两个清单的目录会按 QwenCode 安装。具体代价:未来重构静默反转优先级(不同来源、不同激活组件),无测试报警。修复:新增 converter 测试:同一根目录写入受支持 plugin.json 和 qwen-extension.json,断言 convertCompatibleExtension 以 originSource 'AgentPlugins' 完成。

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

</InfoRow>
)}
{ext.installMetadata?.originSource && (
<InfoRow label={t('Origin:')}>

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] Untested changed behavior (trace-verified): this new Origin: InfoRow is untested — the only test touching PluginDetailView (ExtensionActionsView.test.tsx) mocks the entire view to null and asserts on the mock's props; there is no PluginDetailView.test.tsx. The CLI string twin (extensionToOutputString) did gain a test — Concrete cost: a change that drops or breaks this InfoRow (e.g. an installMetadata field rename) passes CI; users inspecting an installed Agent Plugin in the TUI silently stop seeing its origin.

Fix: render PluginDetailView directly with an extension whose installMetadata.originSource is 'AgentPlugins' and assert the Origin row renders (and is absent when originSource is undefined).

中文说明

未测试的变更行为(已溯源验证):这个新的 Origin: InfoRow 没有测试——唯一涉及 PluginDetailView 的测试(ExtensionActionsView.test.tsx)把整个视图 mock 为 null 并对 mock 的 props 断言;不存在 PluginDetailView.test.tsx。CLI 字符串孪生(extensionToOutputString)是有测试的。具体代价:删除或破坏该 InfoRow 的改动(如 installMetadata 字段重命名)会通过 CI;在 TUI 中查看已安装 Agent Plugin 的用户会静默看不到来源。修复:直接渲染 PluginDetailView,传入 installMetadata.originSource 为 'AgentPlugins' 的扩展,断言 Origin 行渲染(且 originSource 为 undefined 时不渲染)。

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

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

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — Test (windows-latest / macos-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only.

Not explored to full depth (tool budget reached): chunk 7: I did not actually run extensionManager.test.ts — because node_modules is not installed in the worktree or the parent checkout, and I opted not to perform a ful…; chunk 7: did not execute extensionManager.test.ts — node_modules is absent in this worktree and the parent checkout, and a full monorepo install exceeded the remaining….

中文说明

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — Test (windows-latest / macos-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only。

未探索到全部深度(达到工具调用预算):chunk 7:I did not actually run extensionManager.test.ts — because node_modules is not installed in the worktree or the parent checkout, and I opted not to perform a ful…;chunk 7:did not execute extensionManager.test.ts — node_modules is absent in this worktree and the parent checkout, and a full monorepo install exceeded the remaining…

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

Comment thread packages/cli/src/services/FileCommandLoader.ts
Comment thread packages/core/src/extension/extensionManager.ts
Comment thread packages/core/src/extension/extension-converter.ts
}

function isLoopbackHost(hostname: string): boolean {
const normalized = hostname.replace(/^\[|\]$/g, '').toLowerCase();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-4: isLoopbackHost coerces each label with Number(), but WHATWG URL parsing already rejected labels like 1e0/+1 as IPv4 and keeps them as opaque DNS hostnames — new URL('http://127.0.0.1e0/mcp') parses with hostname 127.0.0.1e0. Number('1e0') and Number('+1') both yield 1, so this classifies those hostnames as loopback and validateHttpUrl waives the HTTPS requirement. Probe through loadAgentPluginMcpServers: http://127.0.0.1e0/mcp and http://127.0.0.+1/mcp with configured headers survive while the http://example.com/mcp control is rejected; a per-label decimal-digit restriction flips the probe — Concrete cost: under any resolver that maps such a name off-host (hosts file, corporate/wildcard DNS), plugin-configured headers travel over plaintext HTTP despite the "non-loopback endpoints must use HTTPS" policy. (Legitimate alternate IPv4 notations are unaffected — WHATWG canonicalizes them to dotted quads before this check.)

Suggested change
const normalized = hostname.replace(/^\[|\]$/g, '').toLowerCase();
function isLoopbackHost(hostname: string): boolean {
const normalized = hostname.replace(/^\[|\]$/g, '').toLowerCase();
if (normalized === 'localhost' || normalized === '::1') return true;
const labels = normalized.split('.');
return (
labels.length === 4 &&
labels.every(
(label, index) =>
/^\d{1,3}$/.test(label) &&
Number(label) <= 255 &&
(index !== 0 || Number(label) === 127),
)
);

(suggestion shows the top of the replacement; drop the old ipv4 lines below)

中文说明

isLoopbackHostNumber() 强制转换每个标签,但 WHATWG URL 解析早已拒绝 1e0/+1 这类标签作为 IPv4,并将其保留为不透明 DNS 主机名——new URL('http://127.0.0.1e0/mcp') 解析出的主机名就是 127.0.0.1e0。由于 Number('1e0')Number('+1') 都等于 1,这些主机名会被判定为 loopback,validateHttpUrl 随之豁免 HTTPS 要求。已通过 loadAgentPluginMcpServers 探针确认:带配置 headers 的 http://127.0.0.1e0/mcphttp://127.0.0.+1/mcp 通过校验,而对照组 http://example.com/mcp 被拒绝;按标签限制为十进制数字后探针翻转。具体代价:在任何会把此类名字解析到非本机的解析器下(hosts 文件、企业/通配 DNS),插件配置的 headers 会违反"非 loopback 端点必须使用 HTTPS"的策略、以明文 HTTP 传输。(合法的 IPv4 变体写法不受影响——WHATWG 在到达本检查前已将其规范化为点分十进制。)

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

mcpServers: await loadAgentPluginMcpServers(
effectiveExtensionPath,
this.extensionStore.agentPluginDataRoot(extensionId),
{ createDataDir: true },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-5: loadExtension unconditionally passes { createDataDir: true }, and installExtensionInternal runs this load on the staging copy before the prepareOnly branch — so any agent plugin with a stdio server mkdirs <storeDir>/plugin-data/agent-plugins/<id> (plus ${PLUGIN_DATA} cwd subdirs) during the staged preview. If the prepared mutation is never applied (user declines the batched update, apply step fails), cleanupPreparedExtension removes staging + settings but has no callback for the data dir — settings in the same flow get explicit commit/discard, this side effect gets neither. Probe via prepareExtensionInstall + disposePreparedExtension: the data dir exists after both; deferring creation to the committed load flips the probe with all 129 extensionManager tests still passing — Concrete cost: every prepare-then-discard cycle orphans a persistent data directory in the extension store permanently.

Fix: pass createDataDir: false for the staged preview load (the post-commit loadExtension({ extensionDir: destinationPath }) already creates the dirs).

中文说明

loadExtension 无条件传入 { createDataDir: true },而 installExtensionInternalprepareOnly 分支之前就对 staging 副本执行该加载——因此任何带 stdio server 的 agent plugin 在预演阶段就会 mkdir <storeDir>/plugin-data/agent-plugins/<id>(以及 ${PLUGIN_DATA} cwd 子目录)。若准备好的变更从未应用(用户拒绝批量更新、apply 失败),cleanupPreparedExtension 会删除 staging 与 settings,却没有针对数据目录的回调——同一流程中的 settings 有明确的 commit/discard,这个副作用两者皆无。已通过 prepareExtensionInstall + disposePreparedExtension 探针确认:prepare 与 dispose 之后数据目录均存在;将创建推迟到提交后的加载可翻转探针,且全部 129 个 extensionManager 测试仍通过。具体代价:每次"预演后丢弃"都会在扩展商店目录中永久遗留一个数据目录。修复:预演加载传 createDataDir: false(提交后的 loadExtension({ extensionDir: destinationPath }) 已会创建目录)。

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

method: 'POST',
redirect: 'manual',
});
expect(fetchFn.mock.calls[2]?.[1]).toEqual({ method: 'POST' });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-6: This test covers credentialed agentPluginV1 servers (manual) and one header-less non-plugin server (passthrough), but never an agentPluginV1: true server with no configured headers and no Authorization — which must keep default redirect following. Probe: simplifying stopAgentPluginRedirect to mcpServerConfig?.agentPluginV1 === true passes all 113 mcp-client tests; the proposed credential-less case fails under that mutant (redirect: 'manual' appears) and passes on the PR code — Concrete cost: a future refactor dropping the credentials precondition ships silently, and credential-less plugin servers whose endpoints redirect (http→https, trailing-slash) get a raw 3xx surfaced to the SDK transport and fail to connect with an opaque error.

Fix: add a fifth case — createStreamableHttpCompatibilityFetch('plugin-no-credentials', fetchFn, { httpUrl: 'https://example.com/mcp', agentPluginV1: true }), call with { method: 'POST' }, assert strict toEqual({ method: 'POST' }) (no redirect key).

中文说明

该测试覆盖了带凭据的 agentPluginV1 server(manual)和一个无 headers 的非插件 server(透传),但从未覆盖配置 headers 且无 Authorization 的 agentPluginV1: true server——它必须保持默认的重定向跟随。探针:把 stopAgentPluginRedirect 简化为 mcpServerConfig?.agentPluginV1 === true 后全部 113 个 mcp-client 测试仍通过;补充无凭据用例后该突变体会失败(出现 redirect: 'manual'),在 PR 代码上则通过。具体代价:未来重构若丢弃凭据前置条件将静默通过测试,而无凭据、端点会重定向(http→https、结尾斜杠)的插件 server 会收到透出的原始 3xx,连接以晦涩错误失败。修复:新增第五个用例——createStreamableHttpCompatibilityFetch('plugin-no-credentials', fetchFn, { httpUrl: 'https://example.com/mcp', agentPluginV1: true }),以 { method: 'POST' } 调用,严格断言 toEqual({ method: 'POST' })(不得出现 redirect 键)。

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

}
for (const [field, fieldValue] of Object.entries(value)) {
if (!AUTHOR_FIELDS.has(field)) {
throw new Error(`Unknown Agent Plugins author field "${field}".`);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-7: This interpolates a manifest-controlled value into a thrown error without stripAnsiAndControl — the same applies to the Unsupported Agent Plugins schema throw (~line 109) and the unknown-field debugLogger.warn. claude-converter.ts documents this exact threat ("a hostile plugin … could otherwise smuggle ANSI/OSC sequences to the terminal during a failed install") and aliases stripAnsiAndControl as sanitizeForError; qoder-converter.ts does the same. loadExtensionManifest wraps the raw message and the TUI install catch renders redactUrlCredentials(getErrorMessage(error)), which strips URL userinfo but not control characters. Probe: author keys / $schema carrying ESC/OSC sequences survive into the rendered error (has_esc=true); wrapping the values flips to has_esc=false — Failure scenario: installing a plugin from a hostile repo whose plugin.json author key or $schema contains ANSI/OSC escapes clears/rewrites the terminal output during the failed install.

Suggested change
throw new Error(`Unknown Agent Plugins author field "${field}".`);
throw new Error(`Unknown Agent Plugins author field "${stripAnsiAndControl(field)}".`);

(plus stripAnsiAndControl(schema) at the schema throw; import from ../../utils/textUtils.js)

中文说明

此处把清单可控的值直接插入抛出的错误信息而未使用 stripAnsiAndControl——Unsupported Agent Plugins schema 抛出(约第 109 行)与未知字段的 debugLogger.warn 同样如此。claude-converter.ts 记录了完全相同的威胁("恶意插件……可能在安装失败时向终端走私 ANSI/OSC 序列")并将 stripAnsiAndControl 别名为 sanitizeForErrorqoder-converter.ts 亦然。loadExtensionManifest 原样包装错误信息,TUI 安装 catch 渲染 redactUrlCredentials(getErrorMessage(error))——它只剥离 URL userinfo,不处理控制字符。探针:携带 ESC/OSC 序列的 author 键/$schema 会原样进入渲染后的错误(has_esc=true);包裹这些值后翻转为 has_esc=false。失败场景:安装来自恶意仓库、plugin.json 的 author 键或 $schema 含 ANSI/OSC 转义的插件时,失败安装过程中终端输出被清空/改写。

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

)}
{ext.installMetadata?.originSource && (
<InfoRow label={t('Origin:')}>
{ext.installMetadata.originSource}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-8: This renders sidecar-derived originSource raw, while the adjacent rows in this same component sanitize extension-controlled values (stripUnsafeCharacters(ext.version ?? '') above, redactUrlCredentials(ext.installMetadata.source) below); stripUnsafeCharacters is already imported here. The identical raw interpolation also ships in packages/cli/src/commands/extensions/utils.ts:100. loadInstallMetadata is JSON.parse with zero field validation, and manually placed extension directories are loaded without an installer — a crafted .qwen-extension-install.json is a reachable input. Probe on the CLI sink: originSource carrying screen-clear/cursor-home/OSC-title escapes reaches the output verbatim; wrapping in stripAnsi flips it — Concrete cost: an attacker-placed extension directory spoofs the terminal (cleared screen, rewritten title bar, fake UI text) when the user views the extension in the manager or runs extensions list.

Suggested change
{ext.installMetadata.originSource}
{stripUnsafeCharacters(String(ext.installMetadata.originSource))}

(and stripAnsi(ext.installMetadata.originSource ?? '') at utils.ts:100)

中文说明

此处原样渲染来自 sidecar 的 originSource,而同一组件中相邻的行都会对扩展可控值做净化(上方 stripUnsafeCharacters(ext.version ?? '')、下方 redactUrlCredentials(ext.installMetadata.source));且 stripUnsafeCharacters 已在本文件导入。packages/cli/src/commands/extensions/utils.ts:100 也带着同样的原样插值。loadInstallMetadata 是零字段校验的 JSON.parse,手动放置的扩展目录无需安装器即可被加载——伪造的 .qwen-extension-install.json 是可达输入。CLI 出口探针:携带清屏/光标归位/OSC 标题转义的 originSource 原样到达输出;用 stripAnsi 包裹后翻转。具体代价:攻击者放置的扩展目录可在用户于扩展管理器查看或运行 extensions list 时欺骗终端(清屏、改写标题栏、伪造 UI 文本)。

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

Comment on lines +114 to +116
body: match[2].trim(),
level: 'extension',
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-9: parseAgentPluginSkill silently drops the Qwen-semantic frontmatter fields the sibling parser (parseSkillContent, skill-load.ts) extracts and the skill system honors — notably the invocation controls disable-model-invocation and user-invocable — with no diagnostic, unlike loadAgentPluginManifest in this same directory, which warns on every unrecognized plugin.json field. Probe: a SKILL.md with disable-model-invocation: true parses to a SkillConfig lacking the flag; SkillTool's listing filter (.filter((s) => !s.disableModelInvocation && ...)) then exposes the skill to the model. skill-load.ts:146-155 documents this exact failure as a prior regression ("the flag silently stripped") — Failure scenario: an Agent Plugin ships skills/my-tool/SKILL.md with disable-model-invocation: true; the skill parses fine and becomes model-invocable despite the author's restriction, with no log line indicating the drop. (The allowed-tools drop is deliberate and test-asserted; these restriction-side controls are different — dropping them makes skills more permissive.)

Fix: map the applicable control fields (at minimum disable-model-invocation and user-invocable, reusing skill-load.ts's lenient coercion), or emit a debugLogger.warn for unrecognized frontmatter keys mirroring loadAgentPluginManifest.

中文说明

parseAgentPluginSkill 静默丢弃了兄弟解析器(skill-load.tsparseSkillContent)会提取、且 skill 系统会生效的 Qwen 语义 frontmatter 字段——尤其是调用控制 disable-model-invocationuser-invocable——且无任何诊断;而同目录下的 loadAgentPluginManifest 对每个无法识别的 plugin.json 字段都会告警。探针:带 disable-model-invocation: true 的 SKILL.md 解析出的 SkillConfig 缺少该标志;SkillTool 的列表过滤(.filter((s) => !s.disableModelInvocation && ...))随后把该 skill 暴露给模型。skill-load.ts:146-155 把完全相同的失败记录为历史回归("该标志被静默剥离")。失败场景:Agent Plugin 携带 disable-model-invocation: trueskills/my-tool/SKILL.md 时,skill 正常解析却尽管作者限制仍变为可被模型调用,且无任何日志提示该丢弃。(allowed-tools 的丢弃是有意且已有测试断言;这些限制性控制字段不同——丢弃它们会使 skill 变得更宽松。)修复:映射相应控制字段(至少 disable-model-invocationuser-invocable,复用 skill-load.ts 的宽松强制转换),或仿照 loadAgentPluginManifest 对无法识别的 frontmatter 键输出 debugLogger.warn

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

Not reviewed: cross-file tracer — internals of readMcpServers on the ACP inventory path not audited against the new agentPluginV1 field — stopped at the agent tool budget.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — Test (macos-latest / windows-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only.

Not explored to full depth (tool budget reached): chunk 3: running mcp.test.ts under vitest (worktree has no node_modules ; skipped full monorepo install — all verification was static tracing plus the errno probe).; 本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。: none — all checks above completed within budget.; 本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。: none — all checks I started were completed within budget.; 本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。: none — all planned checks completed within budget.; 本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。: none — all checks above completed within budget., and 2 more.

中文说明

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

未审查:cross-file tracer — internals of readMcpServers on the ACP inventory path not audited against the new agentPluginV1 field — stopped at the agent tool budget。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — Test (macos-latest / windows-latest) platform test jobs were skipped in CI; the suite ran locally on Linux only。

未探索到全部深度(达到工具调用预算):chunk 3:running mcp.test.ts under vitest (worktree has no node_modules ; skipped full monorepo install — all verification was static tracing plus the errno probe).;本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。:none — all checks above completed within budget.;本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。:none — all checks I started were completed within budget.;本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。:none — all planned checks completed within budget.;本 PR(#8834)为 Qwen Code 扩展系统新增 Agent Plugins v1 原生加载支持。:none — all checks above completed within budget.,另有 2 条。

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

Comment on lines +112 to +114
for (const [name, server] of Object.entries(servers)) {
if (server.command) delete servers[name];
}

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] One stdio server's cwd-subdir mkdir failure silently disables every stdio server in the plugin. The createDataDir block wraps the pluginDataRoot mkdir and the per-server cwd mkdir loop in one try; this catch deletes every server with a command — including servers whose cwd lives under ${PLUGIN_ROOT} and never needed the data directory. Probe-confirmed at this commit: two stdio servers (A with cwd: "${PLUGIN_DATA}/work", B with default cwd) plus a regular file pre-created at <dataRoot>/workmkdir throws EEXIST (recursive mkdir tolerates existing directories, not files) → surviving servers []; a per-server try/catch fix flips it to ['b']. The only diagnostic is a debugLogger.warn gated on QWEN_DEBUG_LOG_FILE. — Failure scenario: a previous run legitimately created a regular file at <dataRoot>/work → on the next session start server B, which does not use PLUGIN_DATA, silently never starts (the same over-broad outcome follows from EACCES on any single cwd subdir).

Fix: wrap the per-server await fs.promises.mkdir(server.cwd, { recursive: true }) in its own try/catch and delete only the failed server (needs Object.entries(servers) so the name is available), keeping the outer catch for pluginDataRoot-level failures:

for (const [name, server] of Object.entries(servers)) {
  if (
    server.command &&
    server.cwd &&
    isPathWithin(resolvedPluginDataRoot, server.cwd)
  ) {
    try {
      await fs.promises.mkdir(server.cwd, { recursive: true });
    } catch {
      delete servers[name]; // only the server whose cwd could not be created
    }
  }
}

(Implementing this also requires updating the fixture of 'keeps HTTP servers when the stdio data directory cannot be created' — see the existing thread on mcp.test.ts:188.)

中文说明

单个 stdio server 的 cwd 子目录 mkdir 失败会静默禁用插件内的所有 stdio server。createDataDir 块把 pluginDataRoot 的 mkdir 与逐 server 的 cwd mkdir 循环包在同一个 try 中,而这个 catch 会删除所有带 command 的 server——包括 cwd 位于 ${PLUGIN_ROOT} 下、根本不需要数据目录的 server。已在本提交探针确认:两个 stdio server(A 的 cwd 为 ${PLUGIN_DATA}/work,B 为默认 cwd)且 <dataRoot>/work 处预先存在一个普通文件 → mkdirEEXIST(递归 mkdir 容忍已存在的目录但不容忍文件)→ 存活的 server 为 [];改为按 server 的 try/catch 后翻转为 ['b']。唯一诊断是受 QWEN_DEBUG_LOG_FILE 门控的 debugLogger.warn。失败场景:上一次运行在 <dataRoot>/work 合法创建了普通文件 → 下次会话启动时完全不使用 PLUGIN_DATA 的 server B 静默地永远不启动(任一 cwd 子目录 EACCES 同样导致过大范围删除)。修复:把逐 server 的 mkdir 包进各自的 try/catch,只删除失败的 server(需改用 Object.entries(servers) 以拿到名称),外层 catch 保留给 pluginDataRoot 级失败。(实现该修复还需更新 'keeps HTTP servers when the stdio data directory cannot be created' 的 fixture——见 mcp.test.ts:188 上的既有线程。)

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

(ext) =>
ext.isActive &&
ext.format !== 'agent-plugins-v1' &&
ext.installMetadata?.originSource !== 'AgentPlugins',

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 R2-1 fix's originSource clause is load-bearing but pinned by no test — mutation-verified at this commit: removing ext.installMetadata?.originSource !== 'AgentPlugins' leaves the whole 41-test suite green, while the new regression test exercises only the format clause (mock with format: 'agent-plugins-v1', no installMetadata). — Failure scenario: a linked Agent Plugin whose source directory later drops plugin.json and gains a qwen-extension.json reloads with format: 'qwen' while installMetadata.originSource stays 'AgentPlugins' (no re-consent on reload); without this clause — silently removable today — its commands/ directory would activate as live slash commands, violating the documented "commands are ignored for Agent Plugins" invariant that consent relied on.

Fix: add a test case where the mock extension has no format but installMetadata: { type: 'link', source: '…', originSource: 'AgentPlugins' }, and assert commands is still [].

中文说明

R2-1 修复中的 originSource 子句是承重条款但没有任何测试固定——已在本提交做突变验证:删除 ext.installMetadata?.originSource !== 'AgentPlugins' 后全部 41 个测试仍绿,而新增回归测试只覆盖了 format 子句(mock 只带 format: 'agent-plugins-v1'、无 installMetadata)。失败场景:一个链接安装的 Agent Plugin,其源目录后来删除 plugin.json 并新增 qwen-extension.json,重载后 format: 'qwen'installMetadata.originSource 仍为 'AgentPlugins'(重载不会重新征求同意);若没有这个今天可被静默删除的子句,其 commands/ 目录将激活为可用的斜杠命令,违反同意时所依赖的"Agent Plugins 忽略 commands"文档契约。修复:新增测试用例——mock 扩展不带 format 但带 installMetadata: { type: 'link', source: '…', originSource: 'AgentPlugins' },断言 commands 仍为 []

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

Comment on lines +175 to +177
(ext) =>
ext.isActive &&
ext.format !== 'agent-plugins-v1' &&

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] Agent Plugins v1's manifest files are never classified in ExtensionFileWatcher (packages/cli/src/config/extension-file-watcher.ts), so live-reload semantics break in both directions for the new format — the diff's own CLI-side special-casing (this filter) shows consumers needed per-format handling the watcher never got. Probe-confirmed against the real watcher at this commit: (1) linked plugins — an edit of mcp.json/plugin.json reaches getRuntimePathRefreshAction, matches none of EXTENSION_FILES/STALE_DIRS/AUTO_REFRESH_DIRS and returns false: no refresh is ever marked (the same edit to a linked qwen-format extension marks 'stale'); (2) installed plugins — getUserExtensionRefreshAction's !fs.existsSync(.../qwen-extension.json) catch-all returns 'stale' for ANY file change under the extension dir (Agent Plugins never have that file), including an stdio server writing runtime state into its default cwd ${PLUGIN_ROOT} (the package directory): 2 spurious stale marks observed vs 0 for a qwen-format dir. The suggested fix flips both arms. — Failure scenario: a developer links a plugin (qwen extensions link ./my-agent-plugin, advertised by this PR's new docs) and edits mcp.json mid-session → the session serves stale/absent MCP servers until restart; separately, runtime writes by an installed plugin trigger spurious "Extensions changed on disk. Run /reload-plugins" prompts (the reconcile itself is incremental, so the real cost is the misleading prompt plus a full cache-refresh cycle).

Fix: in extension-file-watcher.ts, add 'plugin.json' and 'mcp.json' to EXTENSION_FILES (fixes linked reloads), and treat a directory containing plugin.json as a classified package in getUserExtensionRefreshAction instead of the blanket 'stale' (fixes spurious markers).

中文说明

Agent Plugins v1 的清单文件从未在 ExtensionFileWatcher(packages/cli/src/config/extension-file-watcher.ts)中分类,导致新格式的热重载语义双向都坏了——本 diff 自己在 CLI 侧的特殊处理(即这个过滤器)正说明各消费方需要按格式处理,而 watcher 从未得到。已在本提交用真实 watcher 探针确认:(1) 链接插件——对 mcp.json/plugin.json 的编辑到达 getRuntimePathRefreshAction 后不匹配 EXTENSION_FILES/STALE_DIRS/AUTO_REFRESH_DIRS 中任何一组,返回 false:永远不会标记刷新(同样的编辑对链接的 qwen 格式扩展会标记 'stale');(2) 已安装插件——getUserExtensionRefreshAction!fs.existsSync(.../qwen-extension.json) 兜底会对扩展目录下任何文件变更返回 'stale'(Agent Plugins 从没有该文件),包括 stdio server 向默认 cwd ${PLUGIN_ROOT}(即包目录)写运行时状态:观察到 2 个虚假 stale 标记,而 qwen 格式目录为 0。建议的修复可使两侧翻转。失败场景:开发者链接插件(qwen extensions link ./my-agent-plugin,本 PR 新文档宣传的工作流)并在会话中编辑 mcp.json → 会话一直使用过期/缺失的 MCP server 直到重启;另外,已安装插件的运行时写入会触发虚假的 "Extensions changed on disk. Run /reload-plugins" 提示(reconcile 本身是增量的,真实代价是误导性提示加一次完整缓存刷新)。

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

Comment on lines +69 to +72
} catch (error) {
debugLogger.warn(
`Disabling Agent Plugins MCP: ${error instanceof Error ? error.message : String(error)}`,
);

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] Every load-time rejection of mcp.json goes only through this gated debugLogger.warn — probe-confirmed at this commit: with the default environment (no QWEN_DEBUG_LOG_FILE), a typo'd $schema or one stray unknown top-level field disables the entire MCP surface and writes nothing to stdout/stderr, while the extension loads active with zero servers; mirroring the warn to stderr flips the probe. No visible surface carries this state (Extension has no warnings field; the TUI hides an empty MCP section; consent lists only server names/URLs). The subsystem's own convention already documents this exact gate problem and mirrors to stderr — corruptFile.ts: "debugLogger.warn is gated behind QWEN_DEBUG_LOG_FILE (unset for almost all users) … Surface … on stderr too." The skills loader has the same pattern — see the companion comment on skills.ts. — Failure scenario: a plugin author ships mcp.json with a typo'd $schema (or one stray unknown top-level field): the whole MCP surface is disabled, the extension shows installed and enabled, no tools ever appear, and nothing anywhere explains why.

Suggested change
} catch (error) {
debugLogger.warn(
`Disabling Agent Plugins MCP: ${error instanceof Error ? error.message : String(error)}`,
);
} catch (error) {
const message = `Disabling Agent Plugins MCP: ${
error instanceof Error ? error.message : String(error)
}`;
// debugLogger.warn is gated behind QWEN_DEBUG_LOG_FILE (unset for almost
// all users); mirror the corruptFile.ts convention and surface on stderr.
process.stderr.write(`[warn] ${message}\n`);
debugLogger.warn(message);
中文说明

mcp.json 的所有加载期拒绝都只经过这个受门控的 debugLogger.warn——已在本提交探针确认:默认环境(未设 QWEN_DEBUG_LOG_FILE)下,$schema 拼写错误或多出一个未知顶层字段会禁用整个 MCP 面且 stdout/stderr 无任何输出,扩展却以零 server 的状态显示为已加载;把该 warn 镜像到 stderr 后探针翻转。没有任何可见面承载该状态(Extension 没有 warnings 字段;TUI 会隐藏空的 MCP 区块;同意界面只列出 server 名称/URL)。扩展子系统自身的惯例已明确记录了这个门控问题并镜像到 stderr——corruptFile.ts:"debugLogger.warn is gated behind QWEN_DEBUG_LOG_FILE (unset for almost all users) … Surface … on stderr too."。skills 加载器存在同样的模式——见 skills.ts 上的配套评论。失败场景:插件作者的 mcp.json 写错了 $schema(或多了一个未知顶层字段):整个 MCP 面被禁用,扩展显示已安装已启用,却永远没有任何工具出现,也没有任何地方解释原因。

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

Comment on lines +65 to +67
debugLogger.warn(
`Skipping Agent Plugins skill "${entry.name}": ${error instanceof Error ? error.message : String(error)}`,
);

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] Same invisible-diagnostic pattern as the companion comment on mcp.ts, in the skills loader: every per-skill rejection (name mismatch, invalid frontmatter, escaping symlink, unreadable SKILL.md) and every whole-root disable (lines 25/30/42) goes only through gated debugLogger.warn. Probe-confirmed at this commit: a plugin with skills/MySkill/SKILL.md containing name: myskill (case mismatch) loads with zero skills and zero stdout/stderr in the default environment; with QWEN_DEBUG_LOG_FILE=1 the warn appears in the debug log only. Mirroring the warn to stderr flips the probe. A fix anchored on mcp.ts alone would not cover these sites. — Failure scenario: a ported v1 plugin whose skill directory case-mismatches its name, or typos a frontmatter field: the skill is skipped with no trail; the extension shows active, /skills lists nothing from it.

Suggested change
debugLogger.warn(
`Skipping Agent Plugins skill "${entry.name}": ${error instanceof Error ? error.message : String(error)}`,
);
const message = `Skipping Agent Plugins skill "${entry.name}": ${
error instanceof Error ? error.message : String(error)
}`;
process.stderr.write(`[warn] ${message}\n`);
debugLogger.warn(message);
中文说明

与 mcp.ts 上的配套评论相同的"诊断不可见"模式,出现在 skills 加载器:每一次按 skill 的拒绝(名称不匹配、frontmatter 非法、符号链接逃逸、SKILL.md 不可读)以及每一次整目录禁用(第 25/30/42 行)都只经过受门控的 debugLogger.warn。已在本提交探针确认:skills/MySkill/SKILL.md 内含 name: myskill(大小写不匹配)的插件在默认环境下加载结果为零个 skill 且 stdout/stderr 无任何输出;设 QWEN_DEBUG_LOG_FILE=1 后该 warn 只出现在 debug 日志文件中。把 warn 镜像到 stderr 后探针翻转。只修 mcp.ts 无法覆盖这些位置。失败场景:移植的 v1 插件 skill 目录名与名称大小写不一致,或 frontmatter 字段拼错:skill 被跳过且无任何痕迹;扩展显示为激活,/skills 却列不出它的任何内容。

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

Comment on lines +357 to +359
function isLoopbackHost(hostname: string): boolean {
const normalized = hostname.replace(/^\[|\]$/g, '').toLowerCase();
if (normalized === 'localhost' || normalized === '::1') return true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] isLoopbackHost misclassifies three machine-local host forms as non-loopback, so validateHttpUrl rejects plain-HTTP mcp.json servers that never leave the machine — probe-confirmed through the real loader at this commit: http://[::ffff:127.0.0.1]:3000/mcp (WHATWG URL normalizes the IPv4-mapped IPv6 loopback to hostname [::ffff:7f00:1], matching neither the ::1 arm nor the dotted-quad arm), http://0.0.0.0:3000/mcp (INADDR_ANY — connects to loopback on Linux/macOS/Windows, and the form server tooling commonly prints), and http://localhost.:3000/mcp (FQDN trailing dot) are all rejected with "Non-loopback Streamable HTTP endpoints must use HTTPS" — factually wrong for loopback hosts — while the extension loads active. The direction is fail-safe (URL pre-normalizes octal/hex/shorthand IPv4 like 0177.0.0.1/127.1/2130706433 to canonical dotted quads before the classifier; no non-loopback host is admitted), hence Suggestion. — Failure scenario: a plugin ships a machine-local streamable-http server using any of the three forms; it is dropped at load with a misleading HTTPS error.

Fix: strip one trailing dot before comparison; accept 0.0.0.0; and for ::ffff:-prefixed hosts decode the mapped tail and re-run the 127-first-octet test — note the tail serializes as compressed hex (::ffff:7f00:1), so a dotted-quad-only tail test does NOT cover it (verified: it flips 0.0.0.0/localhost. but not the mapped form).

中文说明

isLoopbackHost 把三种本机 host 形态误判为非回环,导致 validateHttpUrl 拒绝根本不离开本机的纯 HTTP mcp.json server——已在本提交通过真实 loader 探针确认:http://[::ffff:127.0.0.1]:3000/mcp(WHATWG URL 把 IPv4 映射 IPv6 回环规范化为 hostname [::ffff:7f00:1],既不匹配 ::1 分支也不匹配点分四段分支)、http://0.0.0.0:3000/mcp(INADDR_ANY——在 Linux/macOS/Windows 上都连接到回环,且是服务器工具常打印的形态)、http://localhost.:3000/mcp(带尾点的 FQDN)全部被以 "Non-loopback Streamable HTTP endpoints must use HTTPS" 拒绝——对回环 host 而言该报错与事实不符——而扩展仍显示为激活。方向是失败安全的(URL 会在分类前把 0177.0.0.1/127.1/2130706433 等八进制/十六进制/简写 IPv4 预先规范化为标准点分四段;不会放行任何非回环 host),故为 Suggestion。失败场景:插件携带使用上述任一形态的本机 streamable-http server,加载时即被误导性 HTTPS 错误丢弃。修复:比较前去掉一个尾点;接受 0.0.0.0;对 ::ffff: 前缀的 host 解码映射尾部并重跑 127 首字节判断——注意尾部序列化为压缩十六进制(::ffff:7f00:1),只处理点分四段的尾部测试覆盖不到(已验证:该写法能翻转 0.0.0.0/localhost. 但翻转不了映射形态)。

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

Comment on lines +396 to +397
if (!CLIENT_OWNED_HEADERS.has(lowercaseName)) {
Object.defineProperty(normalized, name, {

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] Client-owned headers set by the plugin are dropped with zero diagnostics — the only header case that neither throws nor warns (not even a debugLogger.warn), while every other header problem (invalid name, invalid value, duplicate) throws a clear load-time error. The drop itself is deliberate hardening (design doc; test-blessed), but the portable spec's streamable-http headers allow arbitrary header names (additionalProperties: string in the live schema), so a fully compliant plugin may ship headers: { "Authorization": "Bearer …" }. Consent shows only server names/URLs — nothing at install or runtime hints at the drop. — Failure scenario: a compliant plugin declares an Authorization header; the entry is dropped silently, the server loads active and appears in consent, requests go out without the header, and the endpoint answers 401/403 with nothing pointing at the cause.

Fix: emit at least a debugLogger.warn — ideally the user-visible channel proposed in the companion mcp.ts:69 comment — when a provided header is dropped as client-owned (an else branch here).

中文说明

插件设置的 client-owned 头部被静默丢弃且零诊断——这是唯一既不抛错也不告警(连 debugLogger.warn 都没有)的头部情形,而其他所有头部问题(非法名称、非法取值、重复)都会抛出清晰的加载期错误。丢弃本身是有意加固(设计文档有述、测试已固定),但 portable 规范中 streamable-http 的 headers 允许任意头部名(线上 schema 为 additionalProperties: string),因此完全合规的插件可以携带 headers: { "Authorization": "Bearer …" }。同意界面只显示 server 名称/URL——安装时和运行时都没有任何信息提示该丢弃。失败场景:合规插件声明了 Authorization 头部;该条目被静默丢弃,server 正常加载并出现在同意列表,请求却不带该头部发出,端点返回 401/403,且没有任何线索指向原因。修复:在提供的头部因 client-owned 被丢弃时(此处加一个 else 分支)至少输出 debugLogger.warn——理想情况是走 mcp.ts:69 配套评论建议的用户可见通道。

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

Comment on lines +286 to +288
let allowedRoot: string;
if (cwd === './' || cwd.startsWith('./')) {
allowedRoot = pluginRoot;

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] normalizeCwd classifies the allowed root from the pre-expansion string, so a cwd mixing ./ with a plugin variable passes load validation but can never exist. Probe-confirmed at this commit: './${PLUGIN_DATA}/work' matches this ./ branch (allowedRoot = pluginRoot) before expandPluginVariables runs; expansion yields ./<absolute-data-path>/work, which path.resolve re-nests as <pluginRoot>/<absolute-data-path>/work — literally inside the plugin root, so containment passes and the server loads active; createDataDir never creates it (not inside the data root), and validateAgentPluginStdioRuntimePaths throws a raw ENOENT at every connect. Control '${PLUGIN_DATA}/work' creates the dir and validates OK; rejecting variable tokens in the ./ branch flips the probe. The intended load-time error never fires and no test covers the mixed form. Direction is fail-safe (no containment escape), hence Suggestion. — Failure scenario: a plugin ships cwd: "./${PLUGIN_DATA}/work" (an easy authoring mistake — both prefixes are advertised): it installs, consents, and loads active, then every connect attempt fails with a raw ENOENT pointing at a nonsense nested path.

Suggested change
let allowedRoot: string;
if (cwd === './' || cwd.startsWith('./')) {
allowedRoot = pluginRoot;
let allowedRoot: string;
if (cwd === './' || cwd.startsWith('./')) {
if (/\$\{PLUGIN_(ROOT|DATA)\}/.test(cwd)) {
throw new Error(
'Stdio cwd must not mix "./" with ${PLUGIN_ROOT} or ${PLUGIN_DATA}.',
);
}
allowedRoot = pluginRoot;
中文说明

normalizeCwd 依据展开前的字符串判定允许的根,因此混用 ./ 与插件变量的 cwd 能通过加载校验却永远不可能存在。已在本提交探针确认:'./${PLUGIN_DATA}/work'expandPluginVariables 运行前就命中这个 ./ 分支(allowedRoot = pluginRoot);展开得到 ./<绝对数据路径>/workpath.resolve 把它重新嵌套为 <pluginRoot>/<绝对数据路径>/work——字面上位于插件根内,于是包含性检查通过、server 加载为激活;createDataDir 从不创建它(它不在数据根内),validateAgentPluginStdioRuntimePaths 在每次连接时抛出原始 ENOENT。对照组 '${PLUGIN_DATA}/work' 正常创建目录并通过校验;在 ./ 分支拒绝变量 token 后探针翻转。预期的加载期错误从不触发,也没有测试覆盖混合形态。方向是失败安全的(无包含性逃逸),故为 Suggestion。失败场景:插件携带 cwd: "./${PLUGIN_DATA}/work"(很容易写错——两种前缀都是文档宣传的):安装、同意、激活都正常,随后每次连接都以指向无意义嵌套路径的原始 ENOENT 失败。

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

@callmeYe

Copy link
Copy Markdown
Collaborator Author

@wenshao @tanzhenxin @yiliang114 @LaZzyMan @doudouOUC Could one of you please review the current head 0f8a8ffa46 and approve it, or dismiss the stale bot CHANGES_REQUESTED reviews if appropriate? All 9 Critical threads from review rounds 1–2 have been fixed and resolved; round 3 reported Suggestions only; all current CI checks are green. The PR remains blocked because the two bot CHANGES_REQUESTED reviews were submitted against older commits and are not cleared by resolved threads or a later COMMENTED review.

@doudouOUC
doudouOUC enabled auto-merge August 11, 2026 11:46
@doudouOUC
doudouOUC disabled auto-merge August 11, 2026 11:46
@wenshao

wenshao commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 1100 passed · 0 failed · 1100 total

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

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

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

Verification report

PR 8834 Deep Verification — Round 2 — feat(extensions): support Agent Plugins v1

Verdict: merge-ready — 1100/1100 scripted assertions passed, 0 failed.
Verified head: 0f8a8ffa46f66408b741f1be42fa75181fa9f717 (git rev-parse HEAD^2, matches the metadata snapshot), merged onto base 962dc8eadc842274b29f4aa408c2c54ab70159b4 (HEAD^1).

中文 — 判定:✅ 通过 · 可合入(agent 判定)· 第二轮(跟进轮)

本轮为跟进验证:上一轮验证的是单 commit 头 79003284,此后 PR 新增两个 fix commit(68f678ac0f8a8ffa,共 10 个文件 +248/−11)。本轮按跟进规则对全部携带结论重新测量(非对比旧报告),并把新探针聚焦于 delta。

  • 结论:merge-ready。1100 个脚本化断言全部通过:A/B 33、delta 探针 22、HTTP wire 10、stdio 实物 wire 9、安全矩阵 55、新变异杀死 5、第一轮变异矩阵复测杀死 6、受影响测试门禁 960(core 782 + cli 178)。
  • A/B 结论(核心主张在新头上依然成立):同一未改动 Agent Plugins v1 包,HEAD 安装/链接成功、Origin: AgentPlugins、skill 被发现、仅加载 stdio 与 Streamable HTTP、安装产物逐字节一致且不生成 qwen-extension.jsonPLUGIN_DATA 跨更新/重装保持;BASE(962dc8eadc)对同一包精确复现 Configuration file not found .../qwen-extension.json,且 BASE 安装普通扩展成功(双臂阳性对照)。见 01-ab-install-link-base-vs-head.png
  • delta 五项修复全部按声明工作且 fail-closed:FileCommandLoader 不再加载 Agent Plugins 捆绑命令(普通扩展命令不受影响)、非普通文件 plugin.json 不被读取(逃逸符号链接仍走"标记 supported→装载时拒绝"的既定 fail-closed 路径)、${PLUGIN_DATA} 内 stdio cwd 目录被创建且 ${PLUGIN_DATA}/../evil 与符号链接组件逃逸均不创建、显式 marketplace 选择优先于根 Agent Plugin 清单且转换副本中的携带 plugin.json 被删除、非法 link source(undefined/42/'')不再使 refresh 崩溃。见 02-delta-fix-commit-probes.png
  • 第一轮三项发现状态:F1(重定向凭据守卫仅作用于 Agent Plugins)重新测量后依旧存在(非本 PR 回归);F2(copyExtension 冗余子句)依旧(M5 再次存活,M5b 再次被杀死);F3(URL 网关文档)依旧并扩展:UTS46 全角/句点形态经 WHATWG URL 归一为 127.0.0.1(与 fetch 同一解析器,接受是安全的),10。0.0.1 归一后仍被拒绝。
  • 新发现(nit):新增的"非常规文件 plugin.json"单测沿目录轴并未钉住 isFile() 守卫(EISDIR catch 本就返回 unrelated);守卫真正承重的是 FIFO/特殊文件不阻塞(实测 FIFO 0ms 返回 unrelated)。另有两处同类冗余防线(见 Finding 1)。均不阻塞。
  • 未覆盖:Windows 行为、真实 GitHub/归档/npm 传输、整仓 lint/typecheck、完整 CLI 二进制 E2E、第一轮 68 格矩阵中少量未重建的边角格(由门禁单测覆盖)。

Previous-finding status (round 1 → this head)

# finding (round 1) severity status at 0f8a8ffa
F1 Redirect credential guard scoped to Agent Plugins only; ordinary extensions still forward configured headers across redirects Suggestion stands — re-measured, not diffed: http-wire.mjs cell c4-ordinary-extension-unchanged at the new head shows the redirect target still receives x-api-key for a non-agent-plugin config (guard code unchanged; explicitly keyed on agentPluginV1 === true). Not a regression; same accepted-scope conclusion.
F2 Redundant clause in copyExtension symlink handling (explicit early-return dead alongside the lstat + type filter) Nit stands — re-mutated at the new head: M5 (drop the clause) survived again; M5b (lstatstat) killed again by the outside-link absence assertion. The clause remains defense-in-depth.
F3 URL-gate over/under-reach: decimal IPs accepted, [::ffff:127.0.0.1] rejected Nit stands, extended — re-measured: http://2130706433/ and http://127.1/ still accepted because WHATWG URL normalizes both to 127.0.0.1 before validation and connection (no parser differential); http://[::ffff:127.0.0.1]/ still rejected (fail-closed). New this round: ideographic/fullwidth-dot forms (127.0.0。1, 127.0.0.1) are UTS46-mapped to 127.0.0.1 and accepted for the same reason, while the security-critical sibling http://10。0.0.1/ normalizes to 10.0.0.1 and is rejected.

Central claim + A/B (re-measured at the new head)

Central claim (unchanged): an unmodified Agent Plugins v1 package installs and
links through the existing extension lifecycle without conversion — identified as
AgentPlugins, portable skills and stdio/Streamable HTTP MCP loaded, stable
PLUGIN_DATA, byte-identical package, no generated qwen-extension.json — where
base fails with Configuration file not found .../qwen-extension.json.

Base arm: git worktree add tmp/base-tree HEAD^1 (962dc8eadc — note main
advanced since round 1's 57e6c310; this A/B tests exactly what lands), rebuilt
only packages/core there. Evidence: 01-ab-install-link-base-vs-head.png.

cell oracle base (962dc8eadc) head (0f8a8ffa)
realpath control loaded module inside arm tree
control: qwen-extension installs install succeeds ctrl-ext ctrl-ext
install agent plugin result Configuration file not found .../qwen-extension.json (expected red = PASS) ✅ installed
link agent plugin result ❌ same (expected red = PASS) ✅ linked, path === source, format agent-plugins-v1
origin / version / format metadata AgentPlugins, 1.0.0, agent-plugins-v1
skills discovery [direct], allowed-tools validated but not granted
non-portable inactive commands/agents/hooks/settings/channels ✅ all empty/undefined
MCP gating loaded keys [local, remote] (sse skipped)
consent payload origin + skills AgentPlugins, skills listed, commands/subagents empty
byte fidelity 4 files + no qwen-extension.json + escaping symlink dropped ✅ 6/6
env expansion PLUGIN_ROOT/PLUGIN_DATA/args/cwd vs realpath ✅ all expanded, data dir outside package
update + reinstall same PLUGIN_DATA, state.txt survives, version bumps ✅ both

Counts: base 4/4, head 29/29 — 33/33 A/B assertions (ab-install.mjs).

Delta probes — the two fix commits (22/22)

Commit attribution (reconstructed pairwise from local objects; the shallow
graft hides commit 3's parent from rev-list, so git show on it alone is
misleading): commit 2 68f678ac = FileCommandLoader exclusion (originSource),
manifest isFile(), stdio cwd mkdir, converter pluginName gating, copyExtension
realpath; commit 3 0f8a8ffa = FileCommandLoader format check, carried
plugin.json removal, link-source guards + format field. Evidence:
02-delta-fix-commit-probes.png.

  1. FileCommandLoader exclusion — a real installed agent plugin carrying
    commands/deploy.toml loads zero commands through the real
    FileCommandLoader (dist), while an ordinary extension's hello.toml in the
    same run still loads (bystander control).
  2. Non-regular plugin.json — directory → unrelated; symlink-to-file still
    read (statSync follows); dangling symlink → unrelated; escaping symlink
    fails closed end-to-end
    : detection returns supported (deliberate, per
    round 1) and installExtension then rejects with
    Path "..." resolves outside plugin root "..." — never installs, never falls
    through to another format.
  3. stdio cwd in PLUGIN_DATA${PLUGIN_DATA}/work created and passes
    runtime validation; ${PLUGIN_DATA}/../evil rejected at normalize (not
    created, valid sibling loads); a symlinked component inside the data root
    pointing outside is rejected (realpath-based containment), no mkdir through
    it.
  4. Marketplace precedence + carried manifest removal — explicit selection →
    Claude, requested name, carried plugin.json absent from the converted
    copy; future-schema (2.0.0) carried manifest also removed; without a
    selection the root agent manifest still wins (AgentPlugins).
  5. Link-metadata isolationsource: undefined | 42 | '' in
    .qwen-extension-install.json: refreshCache() resolves, valid siblings
    load, broken entries don't.
  6. Symlinked source root — install through a dir symlink succeeds, files
    copied (exercises the copyExtension realpath change).

Wire oracles at the new head

  • HTTP redirect guard (http-wire.mjs, 10/10 —
    03-http-redirect-wire.png): real loopback redirector/target pair. Agent
    plugin with configured headers → 307 returned, target sees 0 requests;
    with request Authorization only → same; without secrets → redirect follows;
    ordinary config → follows and forwards x-api-key (F1 re-measure).
  • Real MCP stdio connection (stdio-wire.mjs, 9/9 —
    04-stdio-mcp-wire.png): a real @modelcontextprotocol/sdk server launched
    through core createTransport with the normalized config reports the env/cwd
    it actually received — expanded PLUGIN_ROOT, PLUGIN_DATA, custom env, cwd
    PLUGIN_DATA/work (delta-3's mkdir exercised through the real connection
    path); a tampered config missing runtime roots is rejected before spawn.
  • Security matrix (security-matrix.mjs, 55/55): 20 URL-gate accept/reject
    shapes + 2 normalization corroboration cells, client-owned header drop,
    duplicate/control-char/invalid-name header rejection, 10 stdio containment
    shapes with 9 valid-sibling isolation assertions, transport gating
    (sse/unknown/schema/top-level-field/mcp.json-as-directory), skills discovery
    (nested/missing-description/symlinked excluded), manifest schema gating.

Mutation matrix (all runs this round, tree restored clean after each)

New-delta mutants — evidence: 05-mutation-matrix.png:

mutant guard pinned test result
M1 FileCommandLoader agent-plugin exclusion FileCommandLoader.test.ts new test killedexpect(commands).toEqual([]) receives the deploy command
M2 converter pluginName gating extension-converter.test.ts marketplace test killedexpected 'AgentPlugins' to be 'Claude'
M3 link-source guard, loadExtension site extensionManager.test.ts isolation tests survived — isolation holds anyway: a bogus source fails manifest load and the entry is skipped (defense-in-depth, classified)
M3b link-source guard, fingerprint site same killedrefreshCache() rejects with TypeError ERR_INVALID_ARG_TYPE (path … received undefined): without this guard one corrupt metadata file crashes the whole refresh
M4 stdio cwd mkdir in PLUGIN_DATA mcp.test.ts new test killedENOENT: ... stat '.../data/work'
M5 copyExtension explicit symlink early-return install test outside-link assertion survivedlstat + isFile()/isDirectory() filter already drops symlinks (round-1 result stands)
M5b copyExtension lstatstat same killedoutside-link existence flips falsetrue
M6 manifest isFile() guard manifest.test.ts new non-regular test survived — see Finding 1

Round-1 mutants re-run at the new head (rerun-round1-mutations.mjs, 6/6
killed, logs mutant-R*.log): redirect guard
(expected { method: 'POST' } to match object { ... redirect: 'manual' }),
reserved-env check, client-owned-header drop, HTTP loopback gate, converter
AgentPlugins branch, consent origin exemption
(expected '...' not to contain 'Some features may not work perfectly'). The
7th round-1 mutant (symlink-free copy) is covered by M5/M5b above.

Positive controls: unmutated gates green before and after the mutation
round (identical 782 + 178 counts), proving the harness can both fail and pass.

Targeted gates

  • packages/core: src/extension/** + src/tools/mcp-client.test.ts27 files, 782/782 passed (includes all new delta tests).
  • packages/cli: src/services/FileCommandLoader.test.ts + src/commands/extensions/**13 files, 178/178 passed.

Corrections

None this round.

Findings

No blocking findings. One new nit, plus the three carried-over items.

  1. Nit (new) — the new "non-regular root manifest" test does not pin the
    guard it was written for along the directory axis; the guard's load-bearing
    axis is FIFO non-blocking (untested).
    Mutation M6 (deleting only
    if (!fs.statSync(resolvedManifestPath).isFile()) return 'unrelated';)
    survived: for a directory plugin.json, the surrounding catch already
    returns unrelated because readFileSync throws EISDIR. The guard's real
    value is special files: without it, readFileSync on a FIFO blocks
    indefinitely (open-for-read waits for a writer) and stalls extension refresh.
    Measured with the guard in place: a FIFO plugin.json returns unrelated in
    0 ms. The fixture that would pin this axis is a FIFO named plugin.json
    (the directory fixture pins nothing the catch didn't already). Same family:
    M3's loadExtension-site link-source guard survived for the analogous
    reason — isolation is redundantly provided by manifest-load failure, while
    the fingerprint-site guard (M3b) is the one that prevents a refresh-wide
    crash. All three are defense-in-depth that works; the observation is about
    the tests' pinned axes, not the code.
  2. (carried F1) Suggestion — redirect credential hardening remains Agent
    Plugins-only.
    Re-measured at the new head (http-wire.mjs c4): an
    ordinary streamable-http config still follows redirects with configured
    headers forwarded. Pre-existing, explicitly scoped by the PR, not a
    regression.
  3. (carried F2) Nit — copyExtension's explicit symlink early-return
    remains redundant
    with the lstat + type filter (M5 survived, M5b
    killed).
  4. (carried F3) Nit — URL-gate normalization worth a design-doc line:
    decimal (2130706433, 127.1) and UTS46 dot forms (127.0.0。1) are
    accepted because WHATWG URL — used by both the validator and fetch
    normalizes them to 127.0.0.1; [::ffff:127.0.0.1] is rejected
    (fail-closed over-rejection); mapped non-loopback (10。0.0.1
    10.0.0.1) is rejected.

Not covered

  • Windows behavior (PR self-reports ⚠️): reservedEnvironmentName
    case-folding, path.win32 bare-command root check, backslash rejections —
    code reading + unit tests only; this run is Linux (which again partially
    fills the PR's Linux E2E gap: real install/link/connect ran here).
  • Real GitHub / archive / npm transports: exercised only through mocked
    unit tests (100 github tests green in the gate); no network in this sandbox.
  • Full CLI binary E2E (qwen extensions install <dir>): lifecycle driven
    at the ExtensionManager API level; FileCommandLoader driven through its
    constructor seam with a minimal config shim (the class under test is real,
    its Config collaborator is a thin object) — not through a full Config.
  • Repo-wide lint/typecheck: not re-run (PR CI covers them). Note the base
    control build carried 16 pre-existing type errors in files untouched by the
    PR (emit proceeded; same as round 1).
  • Round-1 68-cell matrix: rebuilt this round as a focused 55-cell matrix —
    every shape family represented, but a few round-1 edge cells (e.g. astral /
    length-boundary skill frontmatter shapes) were not rebuilt; those surfaces
    are covered by the green unit-test gate.
  • Round-1 "link manifest fingerprint reload" A/B cell: not rebuilt as a
    standalone harness; refreshCacheIfSourcesChanged behavior is covered by
    extensionManager.test.ts in the gate.
  • Per-commit attribution caveat: the depth-2 graft makes commit 3
    (0f8a8ffa) appear as a root to git show/rev-list; its true diff was
    computed pairwise against the locally present commit objects
    (68f678ac..0f8a8ffa). The aggregate HEAD^1..HEAD diff is what was
    verified end to end.

Methodology

Environment: the CI verify container (node:22-bookworm), working tree at
refs/pull/8834/merge (depth 2; HEAD merge commit, HEAD^1 base tip,
HEAD^2 PR head), npm ci + npm run build pre-run at HEAD. A/B: base
worktree at HEAD^1, rebuilt only packages/core inside it with the
root's tsc (16 pre-existing unrelated type errors; emit complete); the base
tree's package-level node_modules was symlinked from the head tree —
packages/core has no internal @qwen-code/* dependencies (verified from
its package.json) and the PR changes neither package.json nor the lockfile,
so both arms share one dependency tree and differ only in packages/core
sources; each arm's harness asserts the loaded extensionManager.js realpath
is inside that arm's tree. Harnesses (ab-install.mjs, delta-probes.mjs,
http-wire.mjs, stdio-wire.mjs, security-matrix.mjs,
mutation-matrix.mjs, rerun-round1-mutations.mjs) import compiled dist
output by explicit file URL and run against real filesystem fixtures, real
loopback HTTP servers, and a real @modelcontextprotocol/sdk stdio server —
no stubs of code under test. Mutations were applied one at a time in-tree
(exact string replacement), each followed by its pinned vitest file and
git checkout -- restore; final git status clean (asserted by the matrix
scripts). Gates ran from the package directories with vitest. Raw logs
(logs/), per-mutant logs for R1–R6 (mutant-R*.log; M-series results are
quoted in the mutation matrix and its capture), the delta diff, and the base
build log live alongside this report; five evidence captures in evidence/. Assertion accounting: A/B 33 + delta
probes 22 + HTTP wire 10 + stdio wire 9 + security matrix 55 + new mutation
kills 5 + round-1 re-kills 6 + vitest gates 960 = 1100 executed, 0 failed.
Surviving mutants (M3, M5, M6) are classified in the matrix and Finding 1, and
are not counted as failures — they document defense-in-depth and coverage-gap
status, consistent with round 1's treatment.

Evidence images

01-ab-install-link-base-vs-head

02-delta-fix-commit-probes

03-http-redirect-wire

04-stdio-mcp-wire

05-mutation-matrix

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Triage re-run completed a full review pass and recorded a verdict.

✅ This pass re-reviewed the unchanged head 0f8a8ffa46f66408b741f1be42fa75181fa9f717, confirmed the previous deferral's four asks were all answered (core-size sign-off via the maintainer's E2E verification and formal approval, PLUGIN_DATA decision, mutation-tested redirect guard, green /verify report), and submitted an approving review pinned to that commit — which supersedes the two stale CHANGES_REQUESTED reviews on the earlier commits. See the stage 1/2/3 comments above for details.

中文说明

✅ 本轮 re-run 完成了完整审查并给出裁决:重新审查了未变化的 head 0f8a8ffa46f66408b741f1be42fa75181fa9f717,确认上一次 defer 的四个问题均已解决(维护者 E2E 验证加正式批准完成了核心规模签核、PLUGIN_DATA 已有结论、重定向防护经变异测试证实、/verify 报告为绿),并提交了锚定该 commit 的批准评审——它取代了较早 commit 上两个过期的 CHANGES_REQUESTED。详见上方 stage 1/2/3 评论。

@wenshao

wenshao commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Local end-to-end verification (maintainer run)

I built both sides from source and exercised this against a real stack: the bundled CLI, real stdio and Streamable HTTP MCP servers, a real qwen serve daemon, and an isolated QWEN_HOME per case. Everything in the Reviewer Test Plan reproduces. Two non-blocking observations at the end.

Environment

PR head 0f8a8ff
Base af372e5 (merge-base with main)
Build npm ci && npm run bundle in each worktree → dist/cli.js
Platform macOS 15 (darwin 25.6.0), Node v24.18.1

Sanity check on the bundles before running anything: agent-plugins.org/schemas is present in head/dist and absent from base/dist, so the A/B really is this PR's code.

The MCP servers are evidence recorders, not stubs — the stdio probe appends the argv/cwd/PLUGIN_ROOT/PLUGIN_DATA it was actually handed to a ledger inside PLUGIN_DATA, and the HTTP endpoints log every inbound header server-side. Claims below about expansion and header handling are read off the server, not off CLI output.

1. Before → after, on a package that is never modified

base refuses both entry points; head accepts both, plus a .tar.gz archive that nests the package one directory deep.

before/after

The consent screen for an Agent Plugin correctly omits the "installing an extension from {origin}" cross-ecosystem warning while still listing the MCP servers and Skills it will bring in.

2. The installed package is the original package

Four files compared by sha256, and no generated manifest anywhere under QWEN_HOME. The stdio server starts from the installed copy and connects.

fidelity

3. Capability boundary and per-component isolation

The fixture deliberately ships everything outside the portable core: bundled commands, agents, hooks, a nested Skill, a Skill with no frontmatter, a Skill whose name disagrees with its directory, plus six MCP entries of which five are invalid or unsupported. plugin.json carries no version.

The counts come from GET /workspace/extensions on a live daemon, so this is not inferred from list formatting:

capability boundary

skillCount: 1 of 4 on disk, mcpServerCount: 1 of 6, and commandCount / agentCount / hookCount / contextFileCount / channelCount all 0 with hasSettings: false. Version defaults to 1.0.0. Broken siblings do not take down the valid ones.

The five refused MCP entries cover each rejection path individually: legacy sse, an unknown transport, a cwd that escapes the plugin root, an absolute command, and an entry trying to set its own PLUGIN_DATA.

4. Streamable HTTP policy — checked on the wire

Four of seven entries are refused at load (non-loopback plaintext HTTP, URL user-info, URL fragment, file:). Loopback HTTP and real HTTPS (behind a self-signed CA via NODE_EXTRA_CA_CERTS) both connect.

http policy

The plugin configures Authorization, User-Agent, Content-Type and Host alongside two of its own headers. What the server actually received: no authorization at all, host: 127.0.0.1:39181 (not the configured attacker.example), content-type: application/json, user-agent: undici — while x-plugin-token and x-trace-id arrive intact.

For the redirect case I pointed a plugin at an endpoint that answers 307 to a different origin. The redirector logged 1 request; the redirect target logged 0, and the server is reported Disconnected rather than silently succeeding.

Mutation A/B on the redirect guard. I patched out the stopAgentPluginRedirect condition in mcp-client.ts, rebundled, and re-ran the identical case. The redirect target then received 4 requests carrying x-plugin-token: redirect-secret-must-not-leak. The guard is load-bearing, not incidental. (Source and bundle restored afterwards.)

5. PLUGIN_DATA identity across the lifecycle

Install → extensions update → uninstall → reinstall. I dropped a state file into PLUGIN_DATA before the update.

plugin data

All three server starts report the same PLUGIN_DATA, the state file survives uninstall + reinstall, exactly one data directory exists on disk, and the server's cwd is PLUGIN_DATA as configured. The only PLUGIN_* variables in its environment are the two the host owns.

6. Containment, schema gating, and existing formats

precedence and symlinks

  • A package shipping three symlinks that escape the plugin root installs cleanly with all three dropped; the file they pointed at never appears anywhere under QWEN_HOME.
  • An agent-plugins.org schema at a version other than 1.0.0 is refused with an explicit message rather than being guessed at or falling through to another format.
  • A root plugin.json with no Agent Plugins $schema stays unrelated — the sibling qwen-extension.json still wins.
  • Claude standalone (.claude-plugin/plugin.json) → Origin: Claude with its commands; native Qwen extension → Origin: QwenCode with its commands. Both unchanged.
  • The archive-install error message now lists plugin.json (Agent Plugins) among the accepted manifests.

7. Unit tests

packages/core — 430 passed across the 8 touched files. packages/cli — 75 passed across consent, extensions/utils, FileCommandLoader. No failures.


Two observations — neither blocks merge

a. Format precedence is silent. getAgentPluginSchemaStatus() runs before the qwen-extension.json check in convertCompatibleExtension, so a package carrying both a v1 plugin.json and a qwen-extension.json loads as an Agent Plugin: the Qwen manifest's name, version, and commands/ are ignored with no diagnostic (last panel above — installed as dual-manifest 7.7.7, not dual-manifest-qwen 1.1.1). That is a defensible precedence, but an author who adds a plugin.json to an existing Qwen extension would lose their commands silently. A line in docs/users/extension/agent-plugins.md, or a debugLogger.warn when both manifests are present, would cover it.

b. Cosmetic empty section in extensions list. For Agent Plugins the manager always assigns mcpServers ({} when there are none), while Qwen extensions leave it undefined. Since extensionToOutputString gates on truthiness, an Agent Plugin with no MCP servers prints a bare MCP servers: header with nothing under it. Visible in the symlink-plugin and dual-manifest output above. A Object.keys(...).length > 0 guard fixes it.

Not covered

macOS only — no Windows or Linux run. Install sources exercised were local path, link, and local archive; git / GitHub-release / npm / marketplace sources for Agent Plugins were not. Skill and MCP tool discovery and connectivity are verified, but I did not drive a model turn that actually invokes them.

Verdict: LGTM. The behavior matches what the PR description claims, and the security-relevant guards hold up under adversarial fixtures and a mutation A/B.

中文版本

本地端到端验证(维护者手动执行)

两侧均从源码构建,跑的是真实链路:bundle 后的 CLI、真实 stdio 与 Streamable HTTP MCP server、真实 qwen serve daemon,每个用例使用隔离的 QWEN_HOMEReviewer Test Plan 中的项目全部复现。 文末有两条不阻塞合并的观察。

环境

PR head 0f8a8ff
Base af372e5(与 main 的 merge-base)
构建 各 worktree 内 npm ci && npm run bundledist/cli.js
平台 macOS 15(darwin 25.6.0),Node v24.18.1

跑用例前先做过一次基本核对:agent-plugins.org/schemas 只出现在 head/distbase/dist 中不存在,确认 A/B 对比的确实是本 PR 的代码。

这里的 MCP server 是取证记录器而非空壳:stdio probe 启动时会把宿主实际传入的 argv、cwd、PLUGIN_ROOTPLUGIN_DATA 写入 PLUGIN_DATA 内的 ledger;HTTP 端点在服务端记录每一次请求的完整 header。下文关于变量展开和 header 处理的结论均取自服务端记录,而非 CLI 输出。

1. 前后对比,插件包全程未做任何修改

base 两个入口都拒绝;head 两个入口都通过,并且额外验证了插件包被嵌套一层目录的 .tar.gz 归档安装。

Agent Plugin 的 consent 界面正确地省略了「正在安装来自 {origin} 的扩展」这条跨生态警告,同时仍然列出将要运行的 MCP server 和将要安装的 Skill。

2. 安装后的包就是原始包

四个文件按 sha256 逐一比对一致,QWEN_HOME 下不存在任何生成的 manifest。stdio server 从安装副本启动并连接成功。

3. 能力边界与组件级错误隔离

fixture 刻意携带了全部超出 portable core 的内容:bundled commands、agents、hooks,一个嵌套 Skill、一个无 frontmatter 的 Skill、一个 name 与目录不一致的 Skill,以及六个 MCP entry(其中五个非法或不受支持)。plugin.json 不含 version 字段。

计数取自真实 daemon 的 GET /workspace/extensions,因此不是从 list 输出格式推断出来的:磁盘上 4 个 Skill 只加载 1 个,6 个 MCP entry 只加载 1 个,commandCount / agentCount / hookCount / contextFileCount / channelCount 全为 0hasSettings: false。版本按预期回落到 1.0.0。损坏的同级组件不会连累有效组件。

被拒绝的五个 MCP entry 分别覆盖了各条拒绝路径:legacy sse、未知 transport、逃逸插件根目录的 cwd、绝对路径 command,以及试图自行设置 PLUGIN_DATA 的 entry。

4. Streamable HTTP 策略——在网络层验证

七个 entry 中四个在加载期即被拒绝(非 loopback 明文 HTTP、URL user-info、URL fragment、file:)。loopback HTTP 与真实 HTTPS(自签 CA,经 NODE_EXTRA_CA_CERTS 信任)均连接成功。

插件在自有 header 之外还配置了 AuthorizationUser-AgentContent-TypeHost。服务端实际收到的是:完全没有 authorizationhost: 127.0.0.1:39181(而非配置的 attacker.example),content-type: application/jsonuser-agent: undici;而 x-plugin-tokenx-trace-id 原样送达。

重定向用例中,我让插件指向一个对 MCP POST 返回 307 跳转到另一个 origin 的端点。重定向源记录到 1 次请求,重定向目标记录到 0 次,且该 server 被报告为 Disconnected,没有静默成功。

针对重定向防护的变异 A/B。 我把 mcp-client.ts 中的 stopAgentPluginRedirect 判断改掉、重新 bundle,再跑同一个用例:重定向目标随即收到 4 次请求,并且带着 x-plugin-token: redirect-secret-must-not-leak。说明这道防护是真正起作用的,而非顺带产生的效果。(源码与 bundle 事后均已还原。)

5. PLUGIN_DATA 在整个生命周期中的一致性

install → extensions update → uninstall → reinstall,并在 update 之前往 PLUGIN_DATA 写入一个状态文件。

三次 server 启动上报的 PLUGIN_DATA 完全相同,状态文件在 uninstall + reinstall 后仍然存在,磁盘上始终只有一个数据目录,server 的 cwd 也确实是配置的 PLUGIN_DATA。其环境中的 PLUGIN_* 变量只有宿主注入的那两个。

6. 边界收敛、schema 门禁与既有格式

  • 携带三个逃逸插件根目录符号链接的包可以正常安装,三个链接全部被丢弃;被指向的文件从未出现在 QWEN_HOME 中的任何位置。
  • 版本不是 1.0.0 的 agent-plugins.org schema 会被明确报错拒绝,既不猜测也不回落到其他格式。
  • 根目录 plugin.json 若不带 Agent Plugins $schema,判定仍为 unrelated,同级的 qwen-extension.json 依旧生效。
  • Claude standalone(.claude-plugin/plugin.json)→ Origin: Claude 且命令正常加载;原生 Qwen extension → Origin: QwenCode 且命令正常加载,两者行为均未改变。
  • 归档安装的报错信息中已包含 plugin.json (Agent Plugins)

7. 单元测试

packages/core 涉及的 8 个文件共 430 条通过;packages/cliconsentextensions/utilsFileCommandLoader 共 75 条通过。无失败。


两条观察——均不阻塞合并

a. 格式优先级是静默的。 convertCompatibleExtensiongetAgentPluginSchemaStatus() 先于 qwen-extension.json 检查执行,因此同时携带 v1 plugin.jsonqwen-extension.json 的包会被当作 Agent Plugin 加载:Qwen manifest 的 name、version 和 commands/ 会被忽略且没有任何提示(见最后一张图,安装结果是 dual-manifest 7.7.7 而不是 dual-manifest-qwen 1.1.1)。这个优先级本身是合理的,但如果作者给现有 Qwen extension 补一个 plugin.json,其命令会无声失效。建议在 docs/users/extension/agent-plugins.md 补一句说明,或在两种 manifest 同时存在时打一条 debugLogger.warn

b. extensions list 的空小节(仅观感问题)。 Agent Plugins 分支总会给 mcpServers 赋值(没有 MCP 时为 {}),而 Qwen extension 保持 undefinedextensionToOutputString 按真值判断,于是没有 MCP server 的 Agent Plugin 会打印一个空的 MCP servers: 标题。上文 symlink-plugindual-manifest 的输出中可见。加一个 Object.keys(...).length > 0 判断即可。

未覆盖范围

仅 macOS,未跑 Windows 与 Linux。安装来源覆盖了本地路径、link 和本地归档,未覆盖 Agent Plugins 的 git / GitHub-release / npm / marketplace 来源。Skill 与 MCP 工具的发现和连通性已验证,但未驱动真实模型回合去实际调用它们。

结论:LGTM。 实际行为与 PR 描述一致,安全相关的防护在对抗性 fixture 和变异 A/B 下均成立。

@callmeYe

Copy link
Copy Markdown
Collaborator Author

Thank you for the thorough maintainer E2E verification and LGTM. GitHub still reports CHANGES_REQUESTED because the two earlier bot reviews remain blocking, while the latest bot result and this LGTM are comments rather than approving reviews. Could you please submit a formal approval and, if you have permission, dismiss the stale bot change-request reviews? The branch protection also needs a second approving review. I will keep the two explicitly non-blocking observations as follow-up items so this late review round does not widen the PR.

@wenshao

wenshao commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@wenshao
wenshao enabled auto-merge August 11, 2026 19:33
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 1067 passed · 0 failed · 1067 total

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

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

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

Verification report

<!-- qwen-triage:verify -->
<!-- qwen-triage:verify-substantive -->

PR 8834 Deep Verification — Round 3 — feat(extensions): support Agent Plugins v1

Verdict: merge-ready — 1067/1067 scripted assertions passed, 0 failed.
Verified head: 0f8a8ffa46f66408b741f1be42fa75181fa9f717 (git rev-parse HEAD^2, matches the metadata snapshot), merged onto base 962dc8eadc842274b29f4aa408c2c54ab70159b4 (HEAD^1) — the same merge content as round 2, so this round is a full fresh re-measurement of an unchanged head.

中文 — 判定:✅ 通过 · 可合入(agent 判定)· 第三轮(跟进轮)

本轮为跟进验证:HEAD^1(962dc8eadc)与 HEAD^2(0f8a8ffa)与第二轮逐字节相同(commit OID 即内容寻址证明,工作树干净)。按跟进规则未对比旧报告,而是全部重新测量:A/B、wire oracle、安全矩阵、delta 探针、变异矩阵、定向门禁均为本轮新跑。

  • 结论:merge-ready。1067 个脚本化断言全部通过:A/B 20、delta 探针 14、HTTP wire 6、stdio 实物 wire 7、安全矩阵 53、变异矩阵 7(4 杀 3 按预期存活)、定向门禁 960(core 782 + cli 178,与第二轮计数逐字一致)。
  • A/B 结论(核心主张成立):同一未改动 Agent Plugins v1 包,HEAD 安装/链接成功、Origin: AgentPlugins、skill 被发现、仅 stdio 与 Streamable HTTP 加载、安装产物逐字节一致且不生成 qwen-extension.jsonPLUGIN_DATA 跨更新/重装保持;BASE 对同一包精确复现 Configuration file not found .../qwen-extension.json,双臂阳性对照(普通扩展安装成功)。见 01-ab-install-link-base-vs-head.png
  • 第二轮四项发现状态:F1(重定向凭据守卫仅作用于 Agent Plugins)依旧(c4/c5 复测:普通配置跨 307 仍转发已配置头;跨域重定向时 Authorization 由 fetch 平台剥离,属平台行为);F2(copyExtension 冗长子句)依旧(M5 存活、M5b 杀死);F3(URL 网关归一化)依旧(十进制/全角点形态归一为 127.0.0.1 被接受,[::ffff:127.0.0.1]10。0.0.1 被拒绝);nit-1(非普通 manifest 测试沿目录轴未钉住守卫)依旧并复测:FIFO plugin.json 在守卫存在时 0.06 ms 返回 unrelated(该守卫承重轴为 FIFO 不阻塞)。均不阻塞。
  • 未覆盖:Windows 行为、真实 GitHub/归档/npm 传输、整仓 lint/typecheck、完整 CLI 二进制 E2E、第一轮 68 格矩阵少量边角格、acp-bridge/sdk-typescript 仅类型联合扩展(未单测,类型层由 PR CI 覆盖)。

Closure identity (round 2 → round 3)

Both parent OIDs are byte-identical to round 2's verified head/base (HEAD^1 = 962dc8eadc…, HEAD^2 = 0f8a8ffa…; git commit OIDs are content-addressed, so the trees are identical), the working tree was clean at round start, and package.json/package-lock.json are untouched by the PR. The input closure is therefore provably identical to round 2's. Per the follow-up rule I did not carry measurements forward on that basis alone — every measurement below was re-executed fresh this round; the closure proof is cited to explain why the results are expected to (and do) agree with round 2.

Previous-finding status (round 2 → this head)

# finding (round 2) severity status at 0f8a8ffa (re-measured this round)
F1 Redirect credential guard scoped to Agent Plugins only; ordinary extensions still forward configured headers across redirects Suggestion standshttp-wire.mjs c4: ordinary config with a configured x-api-key (applied to the request the way the SDK transport does) follows the 307 and the target receives the header; c5: ordinary config follows with request Authorization (the header itself is stripped cross-origin by the fetch platform — INFO c5 authorization-forwarded…=false — so F1's practical surface is configured custom headers). Guard code unchanged, explicitly keyed on agentPluginV1 === true. Not a regression; same accepted-scope conclusion.
F2 Redundant clause in copyExtension symlink handling Nit stands — re-mutated: M5 (drop the explicit isSymbolicLink() early-return) survived again; M5b (lstatstat) killed again by the outside-link absence assertion. Defense-in-depth.
F3 URL-gate normalization: decimal/fullwidth-dot forms accepted, [::ffff:127.0.0.1] rejected Nit stands — re-measured in security-matrix.mjs: http://2130706433/, http://127.1/, http://127.0.0。1/ accepted (WHATWG URL normalizes to 127.0.0.1 before validation and connection — same parser both sides, no differential); http://[::ffff:127.0.0.1]/ and http://10。0.0.1/ rejected (fail-closed).
N1 New "non-regular root manifest" test does not pin the guard along the directory axis; guard's load-bearing axis is FIFO non-blocking Nit stands — M6 (delete isFile() guard) survived again on the directory fixture (the surrounding catch already returns unrelated on EISDIR); FIFO probe: with the guard in place, getAgentPluginSchemaStatus on a FIFO plugin.json returns unrelated in 0.06 ms (delta-probes.mjs). The fixture that would pin the FIFO axis remains absent.

Central claim + A/B

Central claim (unchanged): an unmodified Agent Plugins v1 package installs and links through the existing extension lifecycle without conversion — identified as AgentPlugins, portable skills and stdio/Streamable HTTP MCP loaded, stable PLUGIN_DATA, byte-identical package, no generated qwen-extension.json — where base fails with Configuration file not found .../qwen-extension.json.

Base arm: git worktree add tmp/base-tree HEAD^1, rebuilt only packages/core there. This round improved the control over round 2: symlinking the head tree's packages/core/node_modules (the nested dedupe-conflict directory: diff, mime, ajv, fdir, ignore, picomatch, undici) into the base tree reduced the base build's pre-existing type errors from 16 to 1 (@lydell/node-pty declaration resolution, in a PR-untouched file not on the harness import path; emit complete). The PR touches neither package.json nor the lockfile, so both arms share one dependency tree; packages/core has no internal @qwen-code/* dependencies (verified from its package.json), and each arm's harness asserts the loaded extensionManager.js realpath is inside that arm's tree. Evidence: 01-ab-install-link-base-vs-head.png.

cell oracle base (962dc8eadc) head (0f8a8ffa)
realpath control loaded module inside arm tree
control: qwen-extension installs install succeeds ctrl-ext ctrl-ext
install agent plugin result Configuration file not found .../qwen-extension.json (expected red = PASS) ✅ installed
link agent plugin result ❌ same (expected red = PASS) ✅ linked
link path/format metadata path === source, agent-plugins-v1
origin / version / format metadata AgentPlugins, 1.0.0, agent-plugins-v1
skills discovery [direct], allowed-tools validated but not granted
non-portable inactive commands/agents/context/hooks/settings/channels ✅ all empty/undefined
MCP gating loaded keys [local, remote] (sse skipped), both agentPluginV1
consent payload origin + skills AgentPlugins, skills listed, commands/subagents empty
byte fidelity 4 files + no qwen-extension.json + escaping symlink dropped ✅ 6/6
env expansion PLUGIN_ROOT/PLUGIN_DATA/args/cwd ✅ all expanded, data dir outside package
update + reinstall same PLUGIN_DATA, state.txt survives, version bumps ✅ both
default version manifest without version 1.0.0

Counts: base 4/4, head 16/16 — 20/20 A/B assertions (ab-install.mjs).

Delta probes — the two fix commits (14/14)

Commit attribution reconstructed pairwise from locally present commit objects (79003284..68f678ac: 10 files +175/−8; 68f678ac..0f8a8ffa: 6 files +75/−5 — matching round 2's attribution; the depth-2 graft hides commit 3's parent link, and rev-list HEAD^1..HEAD^2 returns 1, so per-commit rows are cited only for the two fix commits whose pairwise diffs were locally computable). Evidence: 02-delta-fix-commit-probes.png.

  1. FileCommandLoader exclusion — through the real cli FileCommandLoader (dist) with a config shim: an agent-plugin extension (format: 'agent-plugins-v1') carrying commands/deploy.toml AND a qwen-format extension with originSource: 'AgentPlugins' carrying commands/conv.toml both load zero commands (both OR clauses exercised), while an ordinary extension's hello.toml in the same run still loads (bystander control).
  2. Escaping-symlink plugin.json — detection returns supported (deliberate, per round 1/2), and installExtension then fails closed with Path "…" resolves outside plugin root "…" — never installs, never falls through to another format.
  3. FIFO plugin.json — returns unrelated in 0.06 ms (N1's load-bearing axis, measured live).
  4. ${PLUGIN_DATA} cwd creation + escape rejection${PLUGIN_DATA}/work created under createDataDir: true; ${PLUGIN_DATA}/../evil rejected at normalize (not created, valid sibling loads); a symlinked component inside the data root pointing outside is rejected (realpath containment) and nothing is created through it.
  5. Marketplace precedence + carried manifest removal — explicit selection → Claude + requested name + carried plugin.json absent from the converted copy; without a selection the root agent manifest wins (AgentPlugins, dir unchanged).
  6. Link-metadata isolationsource: undefined | 42 | '' entries: refreshCache() resolves, valid linked agent-plugin sibling loads, broken entries don't.
  7. Symlinked source root — install through a dir symlink succeeds, files copied, installMetadata.source is the symlink path (exercises the copyExtension realpath change).

Wire oracles

  • HTTP redirect guard (http-wire.mjs, 6/6 — 03-http-redirect-wire.png): real loopback redirector→target pair driven through the real createStreamableHttpCompatibilityFetch with real fetch. Agent plugin + configured headers → 307 returned, target sees 0 requests; agent plugin + request Authorization → same; agent plugin without secrets → redirect followed; agent plugin with the configured header present on the request → still stopped; ordinary config → follows and forwards x-api-key (F1 re-measure).
  • Real MCP stdio connection (stdio-wire.mjs, 7/7 — 04-stdio-mcp-wire.png): a real @modelcontextprotocol/sdk server (the reference implementation as oracle) runs as the plugin's ./bin/server.mjs; core's loadAgentPluginMcpServers normalizes the config, createTransport spawns it, an SDK Client connects, and the child reports what it actually received: expanded PLUGIN_ROOT/PLUGIN_DATA, expanded custom env and args, cwd = ${PLUGIN_DATA}/work (the delta-4 mkdir exercised through the real connection path). A tampered config missing runtime roots is rejected before spawn.

Security matrix (53/53)

security-matrix.mjs05-security-matrix.png: 18 URL-gate accept/reject shapes (including the F3 normalization cells and http://999.0.0.1/ opaque-host rejection), client-owned header silent drop, custom headers kept, duplicate-case/invalid-name/control-char-value header rejection, 11 stdio containment shapes with a valid-sibling isolation assertion plus Linux case-sensitivity of the reserved-env check, transport gating (sse/unknown/future-schema/unknown-top-field/mcp.json-as-directory), skill discovery gating (only valid direct-child loads; nested, name-mismatched, description-less, bad-case, symlinked, and file-as-skills all excluded), manifest schema gating (supported/unsupported/unrelated/directory/absent/invalid-JSON) and name validation.

Mutation matrix (4 killed / 3 survived-as-classified, tree clean after)

Each mutant applied to source, pinned vitest target run, tree restored (GIT_CLEAN_AFTER_MATRIX=true). Positive controls green before (core pinned files 148/148, cli 41/41) and after (gates below). Evidence: 06-mutation-matrix-as-recorded.png, per-mutant logs logs/mutant-M*.log.

mutant guard pinned target result
M1 FileCommandLoader agent-plugin exclusion FileCommandLoader.test.ts new test killedexpected [ { name: 'deploy', … } ] to deeply equal []
M3 link-source guard, loadExtension site extensionManager.test.ts isolation tests survived — isolation holds anyway: a bogus source fails manifest load and the entry is skipped (defense-in-depth)
M3b link-source guard, fingerprint site same killedpromise rejected "TypeError: The "path" argument must be of…" (ERR_INVALID_ARG_TYPE) instead of resolving: without it one corrupt metadata file crashes the whole refresh
M4 stdio cwd mkdir in PLUGIN_DATA mcp.test.ts new test killedENOENT: … stat '…/data/work'
M5 copyExtension explicit symlink drop install test outside-link assertion survived — the lstat + isFile()/isDirectory() filter already drops symlinks (F2)
M5b copyExtension lstatstat same killedoutside-link existence flips false→true
M6 manifest isFile() guard manifest.test.ts non-regular test survived — directory fixture pins nothing the catch didn't already (N1); the FIFO axis is what the guard carries

Every kill failed the intended behavioral assertion (quoted above), not an import/compile break. Survivors M3/M5/M6 are classified defense-in-depth/coverage-gap observations consistent with rounds 1–2 — not counted as failures.

Targeted gates

  • packages/core: src/extension/** + src/tools/mcp-client.test.ts27 files, 782/782 passed (identical count to round 2).
  • packages/cli: src/services/FileCommandLoader.test.ts + src/commands/extensions/**13 files, 178/178 passed (identical count to round 2).

Corrections

None this round. One mechanism clarification, not a correction: round 2's F1 cell applied configured headers to the request the way the SDK transport does; this round's first attempt left them off the request and measured forwarded=false — confirming the configured headers are attached by the transport layer, not by the compatibility fetch wrapper, and that the wrapper's guard only decides the redirect policy. The F1 statement stands as written.

Findings

No new findings. The four carried items (F1 Suggestion; F2, F3, N1 nits) all stand, re-measured above. None block.

Not covered

  • Windows behavior (PR self-reports ⚠️): reservedEnvironmentName case-folding, path.win32 bare-command root check, backslash rejections — code reading + unit tests only; this run is Linux.
  • Real GitHub / archive / npm transports: unit tests only (in the gate); no network in this sandbox.
  • Full CLI binary E2E (qwen extensions install <dir>): lifecycle driven at the ExtensionManager API level; FileCommandLoader through its constructor seam with a minimal config shim (the class under test is real; the Config collaborator is a thin object).
  • Repo-wide lint/typecheck: not re-run (PR CI covers them). Base control build carried 1 pre-existing type error in a PR-untouched file after the nested-node_modules fix (16 before it); emit complete in both cases.
  • Round-1 68-cell matrix edge cells (astral/length-boundary skill frontmatter shapes): not rebuilt; those surfaces are covered by the green unit-test gate.
  • packages/acp-bridge / packages/sdk-typescript changes: type-only union additions of 'AgentPlugins'; no behavioral surface to A/B; covered by PR CI typecheck.
  • Per-commit attribution: commits 1–3 reachable only as pairwise diffs under the depth-2 graft; the aggregate HEAD^1..HEAD diff (33 files, +2475/−64) is what was verified end to end.

Methodology

Environment: the CI verify container (node:22-bookworm), working tree at refs/pull/8834/merge (depth 2; HEAD merge, HEAD^1 base tip, HEAD^2 PR head), npm ci + npm run build pre-run at HEAD. A/B: base worktree at HEAD^1 with only packages/core rebuilt there (root tsc on PATH; the head tree's packages/core/node_modules symlinked in as the nested dependency directory — the PR changes no dependency manifests, so both arms share one dependency tree). Harnesses (harness/ab-install.mjs, http-wire.mjs, stdio-wire.mjs, security-matrix.mjs, delta-probes.mjs, mutation-matrix.mjs) import compiled dist output by explicit file URL and run against real filesystem fixtures, real loopback HTTP servers, and a real @modelcontextprotocol/sdk stdio server — no stubs of code under test. Mutations applied one at a time in-tree (exact string replacement), each followed by its pinned vitest target and git checkout -- restore; final git status clean. Gates ran from the package directories with vitest. Raw logs in logs/ (per-arm A/B, per-mutant vitest, gates, base build), six evidence captures in evidence/ (01–05 live re-runs through scripts/verify-capture.mjs; 06 renders the recorded matrix log). Assertion accounting: A/B 20 + delta probes 14 + HTTP wire 6 + stdio wire 7 + security matrix 53 + mutation matrix 7 + vitest gates 960 = 1067 executed, 0 failed.

Evidence images

01-ab-install-link-base-vs-head

02-delta-fix-commit-probes

03-http-redirect-wire

04-stdio-mcp-wire

05-security-matrix

06-mutation-matrix-as-recorded

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

Qwen Code · sandboxed verification

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅ Full review at this head in the stage comments — sandboxed verification and maintainer E2E both green; the two stale change-requests on earlier commits are superseded by this approval.

@wenshao
wenshao added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit a64d129 Aug 11, 2026
214 of 215 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.11.

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.

3 participants