Skip to content

feat(core): allow sub-agents to spawn nested sub-agents up to a configurable depth - #6189

Merged
tanzhenxin merged 9 commits into
mainfrom
feat/nested-subagents
Jul 3, 2026
Merged

feat(core): allow sub-agents to spawn nested sub-agents up to a configurable depth#6189
tanzhenxin merged 9 commits into
mainfrom
feat/nested-subagents

Conversation

@tanzhenxin

@tanzhenxin tanzhenxin commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Sub-agents can now launch sub-agents of their own, up to a configurable nesting depth. A new model.maxSubagentDepth setting (default 5) bounds how many levels of delegation are allowed: 1 reproduces the previous behavior exactly (sub-agents exist but cannot delegate further), and values below 1 are clamped so the knob can never disable sub-agents outright.

Enforcement is layered so the cap holds even against misbehaving models. At schema-preparation time, a sub-agent is only offered the agent-spawning tool while another level is still permitted — a sub-agent at the deepest allowed level never sees it. At runtime, a guard on the spawning tool independently rejects any attempt that would exceed the cap, returning a clear error telling the model to finish the task with its own tools. Both layers derive from one shared depth predicate so they cannot drift apart.

Nesting is deliberately scoped in this first version, and the scoping removes no existing capability: teammates, fork children, and workflow-launched sub-agents could not spawn sub-agents before this change (the spawning tool was unconditionally excluded from each of their toolsets), and they still cannot. The explicit guards this PR adds for them exist because the exclusion is no longer a single unconditional rule — depth gating re-admits the spawning tool for ordinary sub-agents, and forks and workflow agents share the same wildcard tool path, so without their own guards they would have silently gained it as a side effect. Fork children additionally get a runtime backstop so even a hallucinated spawn call is rejected. The workflow tool itself stays excluded from all sub-agents, unchanged. One capability is deliberately granted: in-process interactive agents (Arena sessions), which previously could never spawn, now carry a proper agent identity and can nest like any first-level agent.

The PR also hardens every path where an agent's nesting identity could previously be lost: a resumed background agent restores its original depth and its launch-time depth cap (both persisted with the agent's metadata) instead of being treated as a fresh top-level agent after a restart; deferred tool-approval continuations re-enter the agent's context at its original depth rather than depth zero; and in-process interactive agents (Arena sessions and in-process teammates) now carry a proper agent identity, so they are depth-gated as agents instead of being mistaken for the top-level session.

This PR now also includes the TUI tree display of nesting: the stacked UI PR (#6191 — indented parent/child rows in the live agent panel and background-tasks view, depth-aware navigation and cancellation) has been reviewed and merged into this branch, so merging this PR brings both the backend enforcement and the tree rendering.

Why it's needed

Delegation is currently hard-capped at one level: the main session can spawn a sub-agent, but that sub-agent is a leaf. For larger tasks — a research agent that wants to fan out its own focused readers, or a migration agent that delegates per-module work — the single level forces everything back through the top-level context. Allowing bounded recursive delegation lets sub-agents decompose their own work while the depth cap, the existing global background-concurrency limit, and serial foreground execution together keep the blast radius controlled.

Reviewer Test Plan

How to verify

All scenarios run headless with auto-approval; the decisive evidence is which tools each sub-agent's API request advertises (enable request logging and compare tool lists between levels — the allowed level has exactly one more tool, the agent tool, than the leaf level).

  1. Nested spawn (default settings): ask the CLI to launch a sub-agent whose task is to launch another sub-agent that replies with a marker word, and report the word back. Expect the chain to complete and the marker word to reach the top-level output; logs show two distinct sub-agent IDs, with the first one's request schema including the agent tool.
  2. Depth cap boundary: set "model": { "maxSubagentDepth": 2 } in the project settings and repeat. Expect the level-2 sub-agent's schema to exclude the agent tool and no third-level agent to appear.
  3. Old behavior at cap 1: set the cap to 1 and repeat. Expect the first sub-agent to lack the agent tool entirely and report it cannot delegate — identical to the pre-feature contract.
  4. No regression: a plain one-level delegation ("spawn a sub-agent that replies BLUE") behaves exactly as before.
  5. Unit-covered guards (not practical to verify end-to-end): depth restored across background resume and deferred approvals, launch-time cap persisted across restarts, fork children blocked from spawning, teammates still excluded, in-process interactive agents framed as agents. See the collocated unit tests for each.

Evidence (Before & After)

Before: a sub-agent's tool schema never includes the agent tool; asking for a nested chain makes the sub-agent report it cannot delegate. After: with the default cap, the nested chain completes and the marker word propagates; at the cap boundary the leaf level's schema drops exactly the agent tool. Full E2E table (4 groups, all passing, with API-log evidence) will be posted as a PR comment.

Tested on

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

Environment (optional)

Local bundle (npm run build && npm run bundle, then node dist/cli.js) with real model calls; unit suites via vitest per package.

Risk & Scope

  • Main risk or tradeoff: the feature ships on by default (cap 5), which is a behavior change for every existing setup — any sub-agent may now delegate further, and while concurrency stays bounded (existing global background-agent cap, serial foreground execution), the cumulative token spend of a deep tree is not separately budgeted. Setting model.maxSubagentDepth to 1 restores the old behavior. A tree-wide spawn/cost budget is the natural follow-up.
  • Not validated / out of scope: nesting for teammates, forks, and workflow-launched agents (excluded by design in v1); a per-agent-definition depth override.
  • Breaking changes / migration notes: none in APIs; behavioral default change as noted above.

Linked Issues

None.

中文说明

本 PR 的内容

子代理现在可以启动自己的子代理,嵌套层数由新的 model.maxSubagentDepth 设置项控制(默认 5)。设为 1 时完全复现旧行为(子代理存在但不能继续委派),小于 1 的值会被钳制为 1,因此该设置永远不会彻底禁用子代理。

强制机制分为两层,即使模型行为异常,深度上限也依然有效。在工具模式准备阶段,只有在仍允许再嵌套一层时,子代理才会看到用于派生代理的工具——处于最深允许层级的子代理根本看不到它。在运行时,派生工具上还有一道独立的守卫,会拒绝任何超出上限的派生请求,并返回明确的错误提示,让模型改用自身工具完成任务。两层机制共享同一个深度判定函数,因此不会出现不一致。

第一版有意收窄了范围,且这种收窄没有移除任何既有能力:在本次变更之前,队友(teammate)、fork 子代理和 workflow 启动的子代理本来就无法派生子代理(派生工具在它们各自的工具集中被无条件排除),现在依然如此。本 PR 为它们添加显式守卫,是因为排除规则不再是单一的无条件规则——深度门控会为普通子代理重新引入派生工具,而 fork 和 workflow 代理走的是同一条通配符工具路径,没有各自的守卫就会作为副作用悄悄获得该工具。fork 子代理还额外获得一道运行时兜底,即使模型凭空调用派生工具也会被拒绝。workflow 工具本身对所有子代理保持排除,不变。有一项能力是有意授予的:进程内交互式代理(Arena 会话)之前完全无法派生,现在拥有正确的代理身份,可以像任何一级代理一样嵌套。

本 PR 还加固了所有可能丢失代理嵌套身份的路径:后台代理恢复时会还原其原始深度和启动时的深度上限(二者均随代理元数据持久化),重启后不会被当作全新的顶层代理;延迟的工具审批续接会以原始深度重新进入代理上下文,而不是深度 0;进程内交互式代理(Arena 会话与进程内队友)现在拥有正确的代理身份,会按代理而非顶层会话来做深度门控。

本 PR 现在同时包含 TUI 的嵌套树形展示:叠加的 UI PR(#6191 —— 实时代理面板与后台任务视图中的父/子行缩进、感知深度的导航与取消)已经过评审并合入本分支,因此合并本 PR 会同时带入后端强制机制和树形渲染。

为什么需要

目前委派被硬性限制在一层:主会话可以派生子代理,但子代理是叶子节点。对于更大的任务——例如想要展开多个专注阅读器的研究代理,或按模块委派工作的迁移代理——单层限制迫使所有内容都回流到顶层上下文。允许有界的递归委派后,子代理可以自行分解工作,同时深度上限、现有的全局后台并发限制和前台串行执行共同控制影响范围。

审阅者测试计划

如何验证

所有场景均以无头模式加自动批准运行;决定性证据是每个子代理的 API 请求中声明了哪些工具(开启请求日志,对比不同层级的工具列表——允许嵌套的层级恰好比叶子层级多一个工具,即派生代理的工具)。

  1. 嵌套派生(默认设置): 让 CLI 启动一个子代理,其任务是再启动一个回复标记词的子代理,并把标记词报告回来。预期链路完整执行,标记词到达顶层输出;日志中出现两个不同的子代理 ID,且第一个的请求模式包含派生工具。
  2. 深度上限边界: 在项目设置中写入 "model": { "maxSubagentDepth": 2 } 后重复。预期第 2 层子代理的模式中不含派生工具,且不出现第三层代理。
  3. 上限为 1 时的旧行为: 将上限设为 1 后重复。预期第一个子代理完全没有派生工具,并报告无法继续委派——与功能之前的契约一致。
  4. 无回归: 普通的单层委派(“派生一个回复 BLUE 的子代理”)行为与之前完全一致。
  5. 由单元测试覆盖的守卫(端到端验证不实际):后台恢复与延迟审批时深度还原、启动时上限跨重启持久化、fork 子代理禁止派生、队友仍被排除、进程内交互式代理按代理框定。详见各处的单元测试。

证据(前后对比)

之前:子代理的工具模式从不包含派生工具;要求嵌套链时子代理会报告无法委派。之后:默认上限下嵌套链完整执行且标记词逐层传回;在上限边界处,叶子层级的模式恰好少了派生工具这一项。完整的 E2E 表格(4 组全部通过,附 API 日志证据)将作为 PR 评论发布。

已测试平台

macOS ✅;Windows / Linux 未本地验证(依赖 CI)。

风险与范围

  • 主要风险或权衡:该功能默认开启(上限 5),对所有现有环境是行为变更——任何子代理现在都可以继续委派;并发仍受限(现有全局后台代理上限、前台串行执行),但深层树的累计 token 消耗没有单独预算。将 model.maxSubagentDepth 设为 1 可恢复旧行为。树级派生/成本预算是自然的后续工作。
  • 未验证 / 超出范围:队友、fork、workflow 启动的代理的嵌套(v1 有意排除);按代理定义的深度覆盖。
  • 破坏性变更 / 迁移说明:API 无破坏性变更;默认行为变更如上所述。

关联 Issue

无。

@tanzhenxin

Copy link
Copy Markdown
Collaborator Author

E2E verification report

Binary: local bundle with the full feature + hardening. Model under test: glm-5.2 (environment default). Evidence source: --openai-logging request logs — the schema-enforcement signal is a tool-count delta of exactly one (the agent tool) between an allowed level and a leaf level.

Group Scenario Pre-implementation (baseline) Post-implementation (this PR) Result
A Nested spawn, default cap 5 Sub-agent lacks the agent tool; no nesting possible Two chained sub-agent IDs; level-1 schema includes the agent tool; marker word propagated to top-level output ✅ PASS
B Cap 2 boundary n/a (no nesting at any cap) Level-1 schema includes the agent tool, level-2 excludes it; no level-3 ID in logs ✅ PASS
C One-level delegation regression Works Works identically (BLUE returned) ✅ PASS
D Cap 1 = old contract This IS the old behavior Level-1 schema excludes the agent tool; agent reports it cannot delegate; no nested spawn in logs ✅ PASS

Not E2E-tested (covered by collocated unit tests): depth restoration across background resume and deferred-approval continuations, launch-time cap persistence across restarts, fork-child spawn blocking, teammate exclusion, in-process interactive agent framing.

@tanzhenxin
tanzhenxin marked this pull request as ready for review July 2, 2026 11:44
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓ — all required sections present, bilingual 中文说明 included, reviewer test plan with "How to verify" steps and before/after table filled in.

On direction: this is a well-motivated, high-value feature. Sub-agent nesting without a depth limit is a real operational risk — runaway recursive spawning has been a recurring complaint in agent CLIs broadly. Claude Code's own CHANGELOG confirms the same direction landed recently: "Fixed foreground subagents spawning unbounded nested chains; they now respect the same 5-level depth limit as background subagents". That's a strong external signal that qwen-code is converging on the same user-facing need. The PR also closes a parity gap between foreground and background sub-agents that previously only the background path enforced. Aligned. ✓

On approach: the layered design is sound and the scope feels right for what it's trying to do:

  • A single shared predicate canSpawnNestedAgent() consumed by both prepareTools() (schema gating) and AgentTool.execute() (runtime backstop) so the two enforcement layers can't drift apart — this is the kind of defense-in-depth that's actually worth the duplication.
  • AsyncLocalStorage-based depth tracking via runWithAgentContext() with a depthOverride param for resume paths is the right choice — threading depth through every call site would have been far more invasive.
  • The edge-case coverage is thorough: background resume, deferred approvals, fork containment, teammate exclusion, workflow-orchestrator exclusion, interactive (Arena) agents.
  • The --max-subagent-depth CLI flag + model.maxSubagentDepth setting + VS Code schema entry + docs update is a complete surface — no missing pieces.

One concern worth flagging (not a blocker): packages/core/src/config/config.ts carries a meaningful amount of Prettier-driven formatting churn (union-type reformatting, import line wrapping) mixed in with the actual logic. This is the kind of thing AGENTS.md calls out as scope creep that should ideally be split. Since it's already there and the tests pass, it's fine to ship, but worth noting for future PRs.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓ — 必填章节齐全,包含双语中文说明、带有 "How to verify" 步骤的 reviewer test plan,以及 before/after 表格。

方向:这是一个动机明确、价值较高的功能。没有深度限制的 sub-agent 嵌套是一个真实的运维风险——递归失控 spawning 在各类 agent CLI 中一直是一个反复出现的投诉。Claude Code 自身的 CHANGELOG 也印证了同样的方向最近已经落地:"Fixed foreground subagents spawning unbounded nested chains; they now respect the same 5-level depth limit as background subagents"。这是一个强有力的外部信号,说明 qwen-code 与业界在解决同一个用户痛点上方向一致。这个 PR 还填补了 foreground 与 background sub-agent 之间的对等性缺口——之前只有 background 路径强制执行深度限制。方向对齐 ✓。

方案:分层设计合理,范围与目标匹配:

  • 单一共享谓词 canSpawnNestedAgent() 同时被 prepareTools()(schema 层面 gating)和 AgentTool.execute()(运行时兜底)消费,使两层强制执行不会漂移——这种防御纵深是值得的重复。
  • 通过 runWithAgentContext()AsyncLocalStorage 深度追踪,配合 depthOverride 参数处理恢复路径,是正确的选择——把深度线程穿过每一个调用点侵入性会大得多。
  • 边界情况覆盖全面:background resume、deferred approval、fork containment、teammate exclusion、workflow-orchestrator exclusion、interactive(Arena)agent。
  • --max-subagent-depth CLI 标志 + model.maxSubagentDepth 设置 + VS Code schema 条目 + 文档更新,覆盖面完整,没有遗漏。

一个值得标记的顾虑(不是阻断项):packages/core/src/config/config.ts 中夹杂了不少 Prettier 驱动的格式化改动(联合类型重新格式化、import 行折行),与真正的逻辑改动混在一起。这是 AGENTS.md 指出的 scope creep 类型,理想情况下应该拆分。既然已经在里面了且测试通过,可以合并,但未来 PR 值得注意。

进入代码审查 🔍

Qwen Code · qwen3.7-max

Sub-agents may now spawn sub-agents up to a configurable maximum nesting
depth (default 5; 1 reproduces the previous no-nesting behavior).
Enforced in two layers sharing one predicate: prepareTools() hides the
agent tool from leaf-depth sub-agents, and AgentTool.execute() rejects
over-depth spawns as an authoritative backstop. Teammates, forks, and
the workflow tool remain excluded from nesting. Launch depth is
persisted in the agent meta sidecar and restored on resume (including
deferred-approval continuations and in-process AgentInteractive frames)
so a resumed nested agent cannot regain spawn capacity.

See knowledge/qwen-code/design/nested-subagents.md.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration.

中文

请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 79.09% 79.09% 84.75% 80.77%
Core 84.82% 84.82% 86.19% 84.92%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   79.09 |    80.77 |   84.75 |   79.09 |                   
 src               |    77.2 |     76.5 |   81.13 |    77.2 |                   
  gemini.tsx       |   67.06 |    72.07 |   81.25 |   67.06 | ...-976,1015-1019 
  ...ractiveCli.ts |   77.44 |    75.09 |   74.07 |   77.44 | ...2033-2035,2070 
  ...liCommands.ts |   88.94 |    84.54 |     100 |   88.94 | ...43,412,446,567 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   58.45 |    63.75 |   84.61 |   58.45 |                   
  acpAgent.ts      |   58.34 |    63.79 |   84.83 |   58.34 | ...7890-7892,7908 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.83 |    96.96 |   92.85 |   97.83 |                   
  filesystem.ts    |   97.83 |    96.96 |   92.85 |   97.83 | 46-47,215-216     
 ...ration/session |   86.92 |    80.23 |   90.32 |   86.92 |                   
  ...ryReplayer.ts |   76.84 |    85.33 |   85.71 |   76.84 | ...50-365,378-379 
  Session.ts       |   87.54 |    79.55 |   91.59 |   87.54 | ...5656,5683-5687 
  ...entTracker.ts |   91.39 |    89.47 |   88.88 |   91.39 | ...31,195,266-275 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   84.21 |    83.33 |     100 |   84.21 | ...37-153,209-211 
  tasksSnapshot.ts |   94.06 |    86.66 |     100 |   94.06 | 60-66             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ssion/emitters |   96.25 |    94.25 |   96.96 |   96.25 |                   
  BaseEmitter.ts   |    92.3 |    81.81 |     100 |    92.3 | 23-24             
  ...ageEmitter.ts |   95.23 |    95.23 |     100 |   95.23 | 48-55             
  PlanEmitter.ts   |     100 |      100 |     100 |     100 |                   
  ...allEmitter.ts |   98.44 |    94.62 |     100 |   98.44 | 318-319,420,428   
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
 ...ession/rewrite |    91.3 |    88.09 |   94.44 |    91.3 |                   
  LlmRewriter.ts   |      81 |       84 |     100 |      81 | ...,88-89,155-159 
  ...Middleware.ts |   96.74 |    86.84 |     100 |   96.74 | 135,143-145       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/commands      |   86.53 |    70.43 |   62.96 |   86.53 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   56.25 |      100 |       0 |   56.25 | 16-20,28-36       
  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        |      96 |      100 |      50 |      96 | 36                
  serve.ts         |   85.61 |    67.67 |     100 |   85.61 | ...68-571,585-589 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
 ...mmands/channel |   77.83 |     83.6 |   80.85 |   77.83 |                   
  ...l-registry.ts |    6.66 |      100 |       0 |    6.66 | 6-32,35-53        
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |     100 |      100 |     100 |     100 |                   
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |    95.3 |     86.6 |   96.29 |    95.3 | ...96-497,566-567 
  pairing.ts       |   26.31 |      100 |       0 |   26.31 | ...30,40-50,52-65 
  pidfile.ts       |   96.77 |    88.46 |     100 |   96.77 | ...77-178,242-243 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  runtime.ts       |   70.39 |    81.81 |     100 |   70.39 | ...43-147,211-214 
  start.ts         |   73.19 |    68.65 |      65 |   73.19 | ...97,503-506,517 
  status.ts        |   75.38 |       40 |     100 |   75.38 | 35-37,47-48,61-72 
  stop.ts          |   39.02 |    33.33 |     100 |   39.02 | 17-19,28-54       
 ...nds/extensions |   87.25 |     89.3 |   85.24 |   87.25 |                   
  consent.ts       |   72.53 |       90 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |      100 |     100 |     100 |                   
  enable.ts        |     100 |      100 |     100 |     100 |                   
  install.ts       |   85.05 |    83.33 |      75 |   85.05 | ...05-208,211-220 
  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     |    37.5 |      100 |   33.33 |    37.5 | 23-45,57-64,67-70 
  update.ts        |   96.29 |      100 |     100 |   96.29 | 101-105           
  utils.ts         |      75 |    53.84 |     100 |      75 | ...27-131,133-137 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.15 |    84.39 |   83.33 |   90.15 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   92.59 |    83.87 |      80 |   92.59 | ...62-164,180-181 
  reconnect.ts     |   78.73 |    66.66 |   85.71 |   78.73 | 42-55,168-190     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   10.02 |      100 |       0 |   10.02 |                   
  cleanup.ts       |   17.94 |      100 |       0 |   17.94 | ...01-106,108-109 
  fetch-pr.ts      |   11.36 |      100 |       0 |   11.36 | ...80-201,203-204 
  load-rules.ts    |   11.32 |      100 |       0 |   11.32 | ...41-153,155-156 
  pr-context.ts    |    6.22 |      100 |       0 |    6.22 | ...97-312,314-315 
  presubmit.ts     |    9.35 |      100 |       0 |    9.35 | ...62-287,289-290 
 ...nds/review/lib |      30 |      100 |       0 |      30 |                   
  gh.ts            |   22.58 |      100 |       0 |   22.58 | ...49,53-54,62-69 
  git.ts           |   22.72 |      100 |       0 |   22.72 | 15-18,29-39,43-44 
  paths.ts         |   52.94 |      100 |       0 |   52.94 | ...26,37-38,42-43 
 ...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        |   93.42 |    87.11 |   94.53 |   93.42 |                   
  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 
  config.ts        |   86.33 |    85.35 |   83.33 |   86.33 | ...2232,2234-2242 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   87.37 |    85.84 |   92.85 |   87.37 | ...43-544,550-551 
  hot-reload.ts    |     100 |    89.74 |     100 |     100 | 47,160,220        
  keyBindings.ts   |    97.1 |       50 |     100 |    97.1 | 212-215           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  mcpApprovals.ts  |   96.55 |    95.65 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      92 |     90.9 |     100 |      92 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  settings.ts      |   88.05 |    88.06 |   89.65 |   88.05 | ...-966,1000-1006 
  ...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 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   93.78 |    94.82 |     100 |   93.78 | ...43-344,380-391 
 ...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    |   69.39 |    66.66 |   63.15 |   69.39 |                   
  ...tputBridge.ts |   69.48 |     67.3 |    64.7 |   69.48 | ...82-383,391-394 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   83.22 |       80 |    86.2 |   83.22 |                   
  index.ts         |    65.4 |    76.92 |      80 |    65.4 | ...70-271,294-299 
  languages.ts     |   96.92 |    86.66 |     100 |   96.92 | 134-135,167,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 |   78.99 |    76.11 |   81.03 |   78.99 |                   
  session.ts       |   83.18 |       75 |   93.47 |   83.18 | ...63-964,973-983 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...00-601,604-605 
 ...active/control |   75.88 |    88.46 |      80 |   75.88 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.69 |       92 |   88.88 |   91.69 | ...49-367,384,387 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |   27.87 |    44.44 |    37.5 |   27.87 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   31.32 |     38.7 |      40 |   31.32 | ...68-577,592-597 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   24.52 |       40 |   33.33 |   24.52 | ...64-476,485-514 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |    98.1 |     94.2 |   95.23 |    98.1 |                   
  ...putAdapter.ts |   98.02 |    93.36 |   98.07 |   98.02 | ...1303,1398-1399 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 83-84,124-125     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   83.12 |    73.43 |    87.5 |   83.12 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   83.77 |    74.19 |   92.85 |   83.77 | ...05-306,317-320 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |    87.3 |    84.37 |   88.56 |    87.3 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |    93.4 |    93.05 |     100 |    93.4 | ...16-317,320-322 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    96.29 |     100 |     100 | 419               
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...supervisor.ts |   97.59 |    89.25 |   95.91 |   97.59 | ...07,523,538,712 
  daemon-logger.ts |   98.24 |    86.95 |   96.29 |   98.24 | 119-120,196       
  ...s-provider.ts |   67.01 |    51.42 |     100 |   67.01 | ...40-245,278-286 
  daemon-status.ts |   98.07 |    84.69 |     100 |   98.07 | ...10,712-713,764 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   90.47 |    78.57 |     100 |   90.47 | ...20-123,189-196 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.88 |    89.02 |     100 |   94.88 | ...08,683,699,709 
  fast-path.ts     |   91.11 |    81.69 |   95.45 |   91.11 | ...42-451,517-518 
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.43 |    88.17 |     100 |   92.43 | ...81-283,295-297 
  ...qwen-serve.ts |   81.43 |    83.27 |   67.52 |   81.43 | ...2978,3000-3003 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   95.61 |    96.29 |   79.16 |   95.61 | ...11-718,818-825 
  ...t-event-id.ts |     100 |    91.66 |     100 |     100 | 12                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |     86.2 |     100 |   91.07 | ...79-182,216-219 
  ...ace-agents.ts |   62.47 |    70.34 |   90.47 |   62.47 | ...1332,1342-1352 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |   87.17 |    78.46 |     100 |   87.17 | ...56-363,423-430 
  ...ers-status.ts |   97.22 |    80.73 |     100 |   97.22 | ...53,156,288-294 
  ...ber-errors.ts |     100 |      100 |     100 |     100 |                   
  ...e-remember.ts |   95.63 |    93.75 |     100 |   95.63 | ...99,119-124,206 
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
  ...lls-status.ts |     100 |     90.9 |     100 |     100 | 100               
 ...serve/acp-http |   73.21 |    75.04 |   93.28 |   73.21 |                   
  ...r-registry.ts |   93.15 |    83.33 |     100 |   93.15 | 206,220-225       
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |   97.53 |    88.38 |   97.36 |   97.53 | 993,1013-1027     
  dispatch.ts      |   66.95 |    70.32 |     100 |   66.95 | ...3829,3877-3883 
  index.ts         |   76.97 |     73.4 |   88.46 |   76.97 | ...1493,1522-1524 
  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.18 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |       80 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |   85.31 |    81.43 |     100 |   85.31 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.82 |    77.08 |     100 |   77.82 | ...64,493-497,510 
  policy.ts        |   90.32 |    89.18 |     100 |   90.32 | 142-150           
  ...ile-system.ts |    84.3 |    79.27 |     100 |    84.3 | ...2061,2088-2089 
 src/serve/routes  |   82.42 |    77.63 |   89.51 |   82.42 |                   
  a2ui-action.ts   |     100 |     94.2 |     100 |     100 | 120,124,169,273   
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  daemon-status.ts |   83.67 |    83.33 |     100 |   83.67 | 82-89             
  health-demo.ts   |    92.3 |    83.33 |     100 |    92.3 | 55-59             
  permission.ts    |     100 |     91.3 |     100 |     100 | 39,78             
  session.ts       |   80.62 |    81.81 |      80 |   80.62 | ...1274,1283-1300 
  sse-events.ts    |   85.71 |    86.11 |   77.77 |   85.71 | ...69,375,392-395 
  ...space-auth.ts |    83.7 |       75 |     100 |    83.7 | ...23,328,340-344 
  ...extensions.ts |   84.42 |    72.72 |   86.36 |   84.42 | ...63-965,984-987 
  ...-file-read.ts |   94.41 |    76.92 |     100 |   94.41 | ...28-329,390-392 
  ...file-write.ts |    82.1 |    60.52 |     100 |    82.1 | ...42-244,247-249 
  ...-lifecycle.ts |     100 |    91.66 |     100 |     100 | 65                
  ...cp-control.ts |   71.42 |    83.72 |     100 |   71.42 | ...04-210,215-218 
  ...ermissions.ts |   87.38 |    76.19 |     100 |   87.38 | ...05-106,132-133 
  ...e-settings.ts |   43.26 |       55 |   66.66 |   43.26 | ...71-281,286-291 
  ...tup-github.ts |   77.52 |    70.27 |   84.21 |   77.52 | ...87,309,352-353 
  ...ace-status.ts |    73.1 |    57.69 |     100 |    73.1 | ...45-146,155-156 
  ...pace-tools.ts |   77.77 |       75 |     100 |   77.77 | 47-52,62-67,91-94 
  ...pace-trust.ts |   76.84 |    72.22 |      50 |   76.84 | ...,63-64,117-118 
  ...pace-voice.ts |   87.09 |     82.6 |    90.9 |   87.09 | ...96,322-323,452 
 src/serve/server  |    85.9 |    86.84 |    92.1 |    85.9 |                   
  access-log.ts    |   97.72 |    95.45 |     100 |   97.72 | 51                
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |   98.38 |    88.23 |     100 |   98.38 | 81                
  ...r-handlers.ts |   81.81 |       50 |     100 |   81.81 | 16,23,27-28       
  ...r-response.ts |   80.34 |    75.92 |     100 |   80.34 | ...67-491,550-559 
  fs-factory.ts    |     100 |    83.33 |     100 |     100 | 27,35             
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |   66.66 |    66.66 |   33.33 |   66.66 | 28-33,36-41       
  ...st-helpers.ts |   93.97 |    93.47 |     100 |   93.97 | ...31-133,387-392 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   91.13 |    94.44 |     100 |   91.13 | 103-109           
  ...on-archive.ts |   94.32 |     90.1 |    87.5 |   94.32 | ...02-304,369-372 
  session-list.ts  |     100 |    90.47 |     100 |     100 | 38,95,144,146     
  telemetry.ts     |   95.62 |    96.89 |     100 |   95.62 | ...27-129,199-201 
 src/serve/voice   |   70.58 |    95.74 |   72.72 |   70.58 |                   
  ...ice-config.ts |   13.33 |      100 |       0 |   13.33 | 35-63,71-87       
  voice-ws.ts      |   78.03 |    95.74 |   84.21 |   78.03 | ...84,399,437-439 
 ...kspace-service |   85.99 |    83.55 |      92 |   85.99 |                   
  index.ts         |   85.49 |    83.22 |    90.9 |   85.49 | ...31-736,796-861 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   91.83 |    88.18 |   98.24 |   91.83 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 101-114           
  ...killLoader.ts |     100 |    93.33 |     100 |     100 | 48,67             
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   75.84 |    80.64 |   83.33 |   75.84 | ...10-211,277-278 
  ...mandLoader.ts |     100 |    97.14 |     100 |     100 | 66                
  ...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 |                   
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.5 |    81.81 |     100 |    90.5 | ...35-436,443-444 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.71 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   85.99 |    87.09 |     100 |   85.99 | ...68,275,329-343 
  ...e-settings.ts |     100 |    95.45 |     100 |     100 | 19                
  ...ranscriber.ts |   90.01 |       81 |   95.83 |   90.01 | ...29-631,634-636 
 ...ght/generators |    88.3 |    85.49 |   92.59 |    88.3 |                   
  DataProcessor.ts |   88.22 |    85.48 |      95 |   88.22 | ...1341,1345-1352 
  ...tGenerator.ts |   98.21 |    85.71 |     100 |   98.21 | 46                
  ...teRenderer.ts |   45.45 |      100 |       0 |   45.45 | 13-51             
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.35 |    84.84 |     100 |   97.35 |                   
  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       |   80.53 |     74.6 |     100 |   80.53 |                   
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.01 |    83.33 |      80 |   94.01 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   68.95 |    70.18 |   61.11 |   68.95 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |      70 |    65.48 |   57.14 |      70 | ...3642,4155-4159 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |   29.23 |      100 |       0 |   29.23 | 25-75             
  ...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 |   56.25 |    33.33 |      40 |   56.25 | ...30-231,236-241 
  ...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.45 |    66.18 |   51.06 |   58.45 |                   
  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.03 |    70.73 |   57.69 |   60.03 | ...87,791,800,803 
  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   |    79.7 |    82.39 |    88.2 |    79.7 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |   89.47 |    81.25 |     100 |   89.47 | 92-93,95-100      
  arenaCommand.ts  |   62.81 |    58.73 |   65.21 |   62.81 | ...90-595,680-688 
  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.1 |     84.9 |     100 |    92.1 | ...4-69,94-99,178 
  clearCommand.ts  |   79.64 |       68 |     100 |   79.64 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   70.86 |    74.07 |      75 |   70.86 | ...,61-93,117-122 
  ...ig-command.ts |   93.06 |    88.33 |     100 |   93.06 | ...04-312,318-320 
  ...extCommand.ts |    65.8 |    68.25 |   84.61 |    65.8 | ...57-590,601-602 
  copyCommand.ts   |   98.49 |    95.78 |     100 |   98.49 | ...80,280,321,327 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |     87.5 |     100 |     100 | ...61,224-225,238 
  ...ryCommand.tsx |   81.43 |     88.4 |    90.9 |   81.43 | ...59-264,311-318 
  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 |   83.67 |    81.25 |     100 |   83.67 | 46-51,66-69,90-95 
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |    50.3 |    48.14 |   69.23 |    50.3 | ...08,262-314,375 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   91.46 |    84.44 |      90 |   91.46 | ...87-190,202-205 
  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   |   84.33 |    72.72 |     100 |   84.33 | 68,82-87,89-94    
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   92.17 |    82.69 |     100 |   92.17 | ...39,159,168-178 
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   82.39 |    88.32 |   85.71 |   82.39 | ...23-528,705-710 
  ...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             
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   85.71 |    86.04 |     100 |   85.71 | ...02-209,216-221 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |    90.6 |    77.95 |     100 |    90.6 | ...91-694,785-792 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.43 |      100 |      50 |    6.43 | 31-330            
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |    66.5 |    78.27 |   71.65 |    66.5 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   77.41 |    66.66 |      50 |   77.41 | 34-40             
  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 |   16.27 |      100 |       0 |   16.27 | 19-58             
  ...TextInput.tsx |   86.72 |    86.66 |     100 |   86.72 | ...00-302,355-359 
  Composer.tsx     |   94.39 |    66.66 |     100 |   94.39 | ...-71,83,138,151 
  ...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 | 18                
  ...ification.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-594             
  DiffDialog.tsx   |   31.17 |    19.51 |   30.76 |   31.17 | ...07-712,722-735 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   75.54 |       54 |     100 |   75.54 | ...09-214,232-236 
  ...ngSpinner.tsx |   68.42 |       80 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   83.33 |    76.92 |     100 |   83.33 | 24-30             
  Header.tsx       |   98.62 |    94.28 |     100 |   98.62 | 162,164           
  Help.tsx         |   98.32 |       90 |     100 |   98.32 | ...24,381,447-448 
  ...emDisplay.tsx |   73.66 |    64.19 |     100 |   73.66 | ...46,449,452-458 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   81.76 |    80.27 |   77.77 |   81.76 | ...2074,2100,2160 
  ...Shortcuts.tsx |   20.87 |      100 |       0 |   20.87 | ...6,49-51,67-125 
  ...Indicator.tsx |   98.14 |    97.82 |     100 |   98.14 | 157-158           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   98.43 |    94.82 |   66.66 |   98.43 | 89,166-170        
  MemoryDialog.tsx |   64.84 |     77.9 |    62.5 |   64.84 | ...02,421,470-472 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   84.61 |    76.76 |     100 |   84.61 | ...80-796,853-857 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...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 |    84.21 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    74.08 |   69.23 |   71.49 | ...1252,1258-1259 
  ...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 |   92.78 |    82.35 |      75 |   92.78 | ...5,77-79,93,124 
  ...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 |    5.46 |      100 |       0 |    5.46 | 24-215            
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.33 |    88.23 |     100 |   96.33 | 137-140           
  ...nsDisplay.tsx |    92.9 |       85 |     100 |    92.9 | ...04,207,234-236 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  ...ingViewer.tsx |   74.01 |    55.55 |     100 |   74.01 | ...02,111-118,130 
  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 |    81.81 |     100 |     100 | 71-86             
  ...ification.tsx |       0 |        0 |       0 |       0 | 1-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 |   91.42 |    64.28 |     100 |   91.42 | 15,21,24          
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   53.71 |    70.87 |   42.85 |   53.71 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   64.78 |    29.41 |   33.33 |   64.78 | ...51,269,277-279 
  AgentFooter.tsx  |   17.07 |      100 |       0 |   17.07 | 28-66             
  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.38 |    68.69 |   73.68 |   42.38 |                   
  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-164             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |   81.04 |    80.44 |   90.56 |   81.04 |                   
  ...sksDialog.tsx |   75.72 |    75.15 |      80 |   75.72 | ...1687,1709-1715 
  ...TasksPill.tsx |   67.03 |     86.2 |     100 |   67.03 | ...02-122,130-138 
  ...gentPanel.tsx |   97.14 |    86.45 |     100 |   97.14 | 132,455-459,527   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 256               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.58 |    78.18 |   83.33 |   84.58 |                   
  ...gerDialog.tsx |   82.46 |    77.77 |     100 |   82.46 | ...89,191-198,258 
  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.15 |    84.74 |   58.82 |   46.15 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.13 |    88.09 |   66.66 |   75.13 | ...52,173,202-208 
  ...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 |   66.18 |    67.65 |   66.66 |   66.18 |                   
  DiscoverTab.tsx  |   57.21 |     63.2 |   55.55 |   57.21 | ...98,661-665,669 
  InstalledTab.tsx |   71.62 |    68.65 |   83.33 |   71.62 | ...68,773-774,811 
  SourcesTab.tsx   |   69.25 |     70.4 |   66.66 |   69.25 | ...16,535,607-619 
 ...tensions/views |   23.73 |    44.82 |       5 |   23.73 |                   
  ...tionsView.tsx |    6.02 |      100 |       0 |    6.02 | 52-65,68-368      
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.56 |      100 |       0 |    9.56 | 40-67,70-158      
 ...mponents/hooks |   86.85 |    81.37 |   91.89 |   86.85 |                   
  ...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.96 |    61.53 |   70.58 |   40.96 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |      33 |    26.19 |      40 |      33 | ...81,883,896-902 
  ...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 |   54.25 |    74.31 |   57.14 |   54.25 |                   
  ...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 |    64.8 |    62.26 |   33.33 |    64.8 | ...75-284,295-317 
  ...rListStep.tsx |   88.46 |    81.25 |     100 |   88.46 | ...63,169,174-179 
  ...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 |    87.2 |    83.67 |   80.45 |    87.2 |                   
  ...ionDialog.tsx |   86.88 |    81.25 |      80 |   86.88 | ...21,539,557-559 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    91.83 |     100 |     100 | 27,31,33,35       
  ...onMessage.tsx |   91.93 |    82.35 |     100 |   91.93 | 57-59,61,63       
  ...nMessages.tsx |   89.92 |    86.66 |    90.9 |   89.92 | ...13-319,376-382 
  DiffRenderer.tsx |   93.19 |    86.17 |     100 |   93.19 | ...09,237-238,304 
  ...tsDisplay.tsx |   97.82 |    77.27 |     100 |   97.82 | 87,89             
  ...usMessage.tsx |   76.31 |     42.1 |   66.66 |   76.31 | ...99,101,124,155 
  ...tsDisplay.tsx |    95.6 |    88.46 |     100 |    95.6 | ...48,150,183-188 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   16.66 |      100 |       0 |   16.66 | 22-38             
  ...sMessages.tsx |   58.65 |       50 |    37.5 |   58.65 | ...20-125,146-158 
  ...ryMessage.tsx |   14.28 |      100 |       0 |   14.28 | 23-62             
  ...onMessage.tsx |   82.31 |    74.02 |   33.33 |   82.31 | ...69-471,478-480 
  ...upMessage.tsx |   98.23 |       95 |     100 |   98.23 | 173-176,390       
  ToolMessage.tsx  |   90.79 |    81.87 |    92.3 |   90.79 | ...88-793,820-822 
 ...ponents/shared |    85.5 |    81.53 |   94.62 |    85.5 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  MaxSizedBox.tsx  |   83.01 |    86.25 |   88.88 |   83.01 | ...12-513,618-619 
  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 |    82.7 |    84.84 |     100 |    82.7 | 46-64,71-74       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   88.54 |    83.64 |      90 |   88.54 | ...15,745-773,869 
  text-buffer.ts   |   85.94 |    81.73 |   97.91 |   85.94 | ...2651,2749-2750 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-678             
 ...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.04 |    53.19 |    37.5 |   14.04 |                   
  ...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.42 |    59.52 |     100 |   35.42 | ...20-432,437-439 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   69.77 |    72.38 |   61.11 |   69.77 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   87.87 |    73.68 |     100 |   87.87 | 69-76             
  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   |   81.99 |    79.01 |   83.33 |   81.99 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   92.45 |    62.79 |      50 |   92.45 | ...69-270,272-276 
  ...deContext.tsx |   88.88 |      100 |       0 |   88.88 | 21                
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   82.72 |    82.81 |     100 |   82.72 | ...1284,1292-1294 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   78.68 |    73.77 |   91.66 |   78.68 | ...86-389,398-401 
  ...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             
  ...erContext.tsx |     100 |      100 |      50 |     100 |                   
  ...edContext.tsx |     100 |      100 |     100 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 147-148           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 226-227           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
 src/ui/daemon     |   90.65 |    73.61 |   95.45 |   90.65 |                   
  ...ui-adapter.ts |   90.65 |    73.61 |   95.45 |   90.65 | ...44,762-763,849 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   83.59 |    81.59 |   88.48 |   83.59 |                   
  ...dProcessor.ts |   80.38 |    81.48 |     100 |   80.38 | ...53-654,660-665 
  ...ention-ref.ts |   97.67 |       84 |     100 |   97.67 | 63                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...86-287,292-293 
  ...dProcessor.ts |   84.49 |    63.98 |   84.21 |   84.49 | ...1114,1135-1139 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...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 |    90.6 |     87.9 |     100 |    90.6 | ...28-435,475-484 
  ...ifications.ts |   86.91 |    96.29 |     100 |   86.91 | 116-130           
  ...tIndicator.ts |   83.49 |    70.96 |     100 |   83.49 | ...58,166,168-176 
  ...waySummary.ts |   96.22 |    69.69 |     100 |   96.22 | 125-127,169       
  ...ndTaskView.ts |   94.73 |    76.59 |     100 |   94.73 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   93.37 |     73.8 |     100 |   93.37 | ...37,186,259-262 
  ...ompletion.tsx |   96.75 |    81.81 |     100 |   96.75 | ...78-279,289-290 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   94.11 |    89.65 |     100 |   94.11 | ...32-133,137-138 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   78.53 |    88.57 |     100 |   78.53 | ...96-104,112-113 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |     97.7 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |    93.5 |     92.3 |     100 |    93.5 | ...87-291,304-310 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |    83.6 |    80.12 |   95.45 |    83.6 | ...3418,3503-3511 
  ...BranchName.ts |     100 |    91.66 |     100 |     100 | 30                
  ...oryManager.ts |   97.94 |    98.24 |     100 |   97.94 | 139-142           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |       0 |        0 |       0 |       0 | 1-90              
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...delCommand.ts |     100 |     92.3 |     100 |     100 | 40                
  ...ouseEvents.ts |   94.25 |    97.22 |   83.33 |   94.25 | 76-80             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |   86.95 |    77.41 |   91.66 |   86.95 | ...70,311-323,371 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   88.54 |    91.83 |     100 |   88.54 | ...73-278,381-391 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...tleRepaint.ts |     100 |      100 |     100 |     100 |                   
  ...umeCommand.ts |   93.66 |    72.41 |     100 |   93.66 | ...17,155,196-201 
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-73              
  ...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.14 |    92.56 |     100 |   97.14 | ...78-382,483-490 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   53.06 |       50 |   66.66 |   53.06 | ...53,61-68,79-85 
  ...rminalSize.ts |   76.19 |      100 |      50 |   76.19 | 21-25             
  ...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 |      100 |     100 |     100 |                   
  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    |    90.9 |    90.62 |     100 |    90.9 |                   
  ...AppLayout.tsx |   90.72 |       90 |     100 |   90.72 | 57-59,101-106     
  ...AppLayout.tsx |   91.17 |    91.66 |     100 |   91.17 | 70-75             
 src/ui/models     |   80.24 |    79.16 |   71.42 |   80.24 |                   
  ...ableModels.ts |   80.24 |    79.16 |   71.42 |   80.24 | ...,61-71,123-125 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/state      |   94.91 |    81.81 |     100 |   94.91 |                   
  extensions.ts    |   94.91 |    81.81 |     100 |   94.91 | 68-69,88          
 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      |    84.2 |    83.43 |   93.59 |    84.2 |                   
  ...Colorizer.tsx |   80.42 |    85.41 |     100 |   80.42 | ...00-201,298-324 
  ...nRenderer.tsx |   68.83 |    70.14 |      50 |   68.83 | ...52-254,274-293 
  ...wnDisplay.tsx |   88.67 |    89.69 |     100 |   88.67 | ...30,747,777-796 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.08 |    80.45 |      95 |   92.08 | ...76-679,723-728 
  ...odeDisplay.ts |   96.55 |     90.9 |     100 |   96.55 | 34                
  asciiCharts.ts   |   96.77 |    87.62 |     100 |   96.77 | 173-180,281       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   51.92 |    72.72 |   91.66 |   51.92 | ...21,624-633,636 
  commandUtils.ts  |    96.1 |    88.77 |     100 |    96.1 | ...73,175-176,320 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   90.38 |    73.91 |     100 |   90.38 | 23,25,29,31,33    
  formatters.ts    |    95.4 |    98.41 |     100 |    95.4 | 123-126           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |    96.77 |     100 |     100 | 43                
  historyUtils.ts  |    95.6 |    95.16 |     100 |    95.6 | 96-99             
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |    8.23 |      100 |       0 |    8.23 | ...31-132,135-136 
  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 |   90.21 |    85.71 |     100 |   90.21 | ...,91-95,107-108 
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...ToolGroups.ts |   98.65 |    96.72 |     100 |   98.65 | 48-49             
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    73.77 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   94.84 |    88.74 |     100 |   94.84 | ...57,442,446-447 
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |   99.02 |    97.56 |     100 |   99.02 | 106               
  ...storyUtils.ts |   68.54 |    78.07 |   93.33 |   68.54 | ...41-463,589-590 
  ...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 
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   93.99 |    90.56 |   93.33 |   93.99 | ...89-290,425-426 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   89.33 |    93.47 |     100 |   89.33 | ...,66-78,180-181 
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 30-42             
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |      57 |     40.8 |   79.41 |      57 |                   
  collect.ts       |   55.92 |    50.58 |   86.36 |   55.92 | ...25-640,642-647 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   58.11 |    20.51 |      80 |   58.11 | ...13-314,328-363 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |      40 |      100 |       0 |      40 | 11-13             
 ...ort/formatters |    3.38 |      100 |       0 |    3.38 |                   
  html.ts          |    9.61 |      100 |       0 |    9.61 | ...28,34-76,82-84 
  json.ts          |      50 |      100 |       0 |      50 | 14-15             
  jsonl.ts         |     3.5 |      100 |       0 |     3.5 | 14-76             
  markdown.ts      |    0.94 |      100 |       0 |    0.94 | 13-295            
 src/ui/voice      |   81.12 |    73.04 |    79.1 |   81.12 |                   
  ...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.14 |     64.7 |   92.85 |   91.14 | ...76,282,292-295 
  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 |     100 |    88.88 |     100 |     100 | 18                
  ...am-session.ts |   87.45 |    63.33 |   81.81 |   87.45 | ...03,320-322,339 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |    74.1 |    89.01 |   91.31 |    74.1 |                   
  acpModelUtils.ts |   95.49 |    94.23 |     100 |   95.49 | 44,68-69,73-74    
  apiPreconnect.ts |   96.72 |    97.14 |     100 |   96.72 | 165-168           
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |   82.53 |    93.33 |      80 |   82.53 | 74,105-115        
  commands.ts      |     100 |      100 |     100 |     100 |                   
  commentJson.ts   |   90.51 |    91.89 |     100 |   90.51 | 67-76,116         
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   90.85 |    96.36 |    92.3 |   90.85 | 69-70,298-310     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |    92.7 |    84.09 |     100 |    92.7 | ...07-110,158-161 
  ...AutoUpdate.ts |    92.2 |    95.23 |   88.88 |    92.2 | 130-141           
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.71 |    94.18 |     100 |   97.71 | ...57,274-275,320 
  languageUtils.ts |   98.47 |    97.72 |     100 |   98.47 | 153-154           
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.15 |    90.97 |     100 |   94.15 | ...26,432,435-439 
  ...iveHelpers.ts |   95.33 |    92.08 |     100 |   95.33 | ...51-452,550,563 
  osc.ts           |    97.5 |      100 |   88.88 |    97.5 | 195-196           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  processUtils.ts  |     100 |      100 |     100 |     100 |                   
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   93.22 |    81.25 |     100 |   93.22 | 65-67,80          
  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       |       0 |        0 |       0 |       0 | 1-1042            
  ...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.03 |    88.81 |      90 |   82.03 | ...11-729,736-744 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   27.55 |    76.11 |   45.83 |   27.55 | ...44-845,848-867 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       60 |     100 |     100 | 23,32             
  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 |   94.11 |    83.33 |     100 |   94.11 | 13                
  ...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          |   84.82 |    84.92 |   86.19 |   84.82 |                   
 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.19 |    82.69 |   94.96 |   90.19 |                   
  ...transcript.ts |    92.6 |     87.5 |     100 |    92.6 | ...46,365-366,497 
  ...ent-resume.ts |   83.67 |    72.72 |   79.41 |   83.67 | ...1286-1290,1293 
  ...ound-tasks.ts |   96.85 |    89.36 |     100 |   96.85 | ...1198,1218-1221 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.65 |    89.28 |     100 |   95.65 | ...12-413,485-489 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.25 |     67.5 |   78.94 |   76.25 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.01 |    64.22 |   78.57 |   75.01 | ...1874,1880-1881 
  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 |   77.89 |    84.85 |   76.28 |   77.89 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   90.17 |    84.12 |   93.33 |   90.17 | ...71,673,675-676 
  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 |   88.63 |    86.05 |   83.47 |   88.63 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |    79.8 |     76.4 |   67.34 |    79.8 | ...1930,1957-2004 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   87.93 |    79.06 |   63.63 |   87.93 | ...00-401,404-405 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.19 |    82.35 |     100 |   98.19 | 127,151,192,225   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.79 |    87.79 |   82.35 |   91.79 | ...1774,1823-1826 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...ow-sandbox.ts |   96.87 |    94.51 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   81.86 |    84.09 |    87.4 |   81.86 |                   
  TeamManager.ts   |    72.1 |     79.6 |   78.84 |    72.1 | ...1628,1651-1652 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...37-141,148-152 
  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        |   81.66 |    85.15 |   68.83 |   81.66 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   80.44 |    84.54 |   65.73 |   80.44 | ...6130,6135-6136 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.63 |    91.86 |   89.58 |   94.63 | ...15-416,419-420 
 ...nfirmation-bus |   98.29 |    97.14 |     100 |   98.29 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   89.22 |    84.65 |   92.19 |   89.22 |                   
  baseLlmClient.ts |   87.19 |    79.68 |      80 |   87.19 | ...18,631,685-687 
  client.ts        |   88.06 |    81.17 |   90.32 |   88.06 | ...2730,2798-2799 
  ...tGenerator.ts |   88.07 |       75 |     100 |   88.07 | ...84-388,396-400 
  ...lScheduler.ts |   88.25 |    82.84 |   95.06 |   88.25 | ...4383,4411-4422 
  geminiChat.ts    |   89.14 |     86.9 |   95.06 |   89.14 | ...3325,3392-3393 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |    95.83 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   92.59 |       75 |      50 |   92.59 | 41-42             
  ...on-helpers.ts |   86.72 |    73.68 |     100 |   86.72 | ...00-201,215-224 
  ...issionFlow.ts |   98.79 |       96 |     100 |   98.79 | 97                
  prompts.ts       |   88.93 |    89.55 |   72.72 |   88.93 | ...-910,1113-1114 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    89.28 |     100 |     100 | 25,60-61          
  ...allIdUtils.ts |   98.23 |     92.1 |     100 |   98.23 | 36,45             
  ...okTriggers.ts |   99.43 |     91.5 |     100 |   99.43 | 175,186           
  ...terruption.ts |     100 |       92 |     100 |     100 | 86,104            
  turn.ts          |   97.79 |       90 |     100 |   97.79 | ...57,584-585,631 
 ...ntentGenerator |   95.36 |    83.11 |   94.54 |   95.36 |                   
  ...tGenerator.ts |   96.93 |    84.81 |   93.93 |   96.93 | ...1167,1195-1197 
  converter.ts     |   94.51 |    80.72 |     100 |   94.51 | ...06-607,617,823 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   89.93 |    71.83 |   93.33 |   89.93 |                   
  ...tGenerator.ts |    88.3 |    71.21 |   92.85 |    88.3 | ...19-325,343-344 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   94.61 |    84.69 |    92.1 |   94.61 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   94.51 |    83.39 |   91.66 |   94.51 | ...1113-1114,1142 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.89 |    85.75 |   94.04 |   88.89 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   88.21 |    83.25 |   96.29 |   88.21 | ...1572,1741-1756 
  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.51 |    89.93 |     100 |   95.51 | ...07-708,716,784 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |    90.2 |     87.5 |     100 |    90.2 | ...39-343,373-374 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.49 |    89.65 |   96.55 |   96.49 |                   
  dashscope.ts     |   97.47 |    91.97 |      95 |   97.47 | ...78-379,521-522 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |    97.5 |    96.55 |   88.88 |    97.5 | 122-123,193       
  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     |   77.79 |    79.89 |   84.61 |   77.79 |                   
  ...-converter.ts |   78.29 |    70.87 |     100 |   78.29 | ...1108,1153-1154 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |    73.8 |       75 |     100 |    73.8 | 44-54             
  ...ionManager.ts |   60.68 |    71.42 |   55.17 |   60.68 | ...1613,1638-1639 
  ...references.ts |     100 |    89.58 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |   92.65 |    91.89 |     100 |   92.65 | ...28-232,312-313 
  ...-converter.ts |    75.9 |    83.33 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   84.71 |     85.4 |     100 |   84.71 | ...61-662,670-671 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |    95.83 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   87.11 |    84.28 |     100 |   87.11 | ...44,348-354,429 
  npm.ts           |   74.67 |    71.64 |     100 |   74.67 | ...19-421,428-432 
  override.ts      |   94.11 |    88.88 |     100 |   94.11 | 63-64,81-82       
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   93.96 |    83.14 |     100 |   93.96 | ...35-341,362-363 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.75 |    83.33 |     100 |   88.75 | ...28-231,234-237 
 src/followup      |   76.05 |    74.12 |   90.62 |   76.05 |                   
  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   |   63.01 |    40.29 |   71.42 |   63.01 | ...73-574,577-582 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 96                
  ...nGenerator.ts |   67.96 |    77.58 |      80 |   67.96 | ...67-218,297-299 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   89.57 |    83.57 |   94.44 |   89.57 |                   
  ...eGoalStore.ts |    85.1 |    95.45 |   84.61 |    85.1 | ...63-166,174-182 
  goalHook.ts      |   97.26 |    91.66 |     100 |   97.26 | 100-105           
  goalJudge.ts     |   84.33 |    74.28 |     100 |   84.33 | ...57-358,366-368 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   87.01 |    85.68 |    88.1 |   87.01 |                   
  ...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.35 |    90.69 |     100 |   96.35 | ...00-301,382,384 
  ...entHandler.ts |   95.34 |    85.05 |   94.11 |   95.34 | ...74,931-932,942 
  hookPlanner.ts   |   86.29 |    83.33 |   85.71 |   86.29 | ...15-219,226-237 
  hookRegistry.ts  |   91.48 |    84.61 |     100 |   91.48 | ...97,416,420,424 
  hookRunner.ts    |   62.42 |    72.04 |   66.66 |   62.42 | ...64-765,774-775 
  hookSystem.ts    |   87.05 |      100 |   68.88 |   87.05 | ...21-722,728-729 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   96.37 |     90.9 |      90 |   96.37 | 342-350,424-425   
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   96.66 |    91.66 |     100 |   96.66 | ...90,209-210,223 
  ssrfGuard.ts     |   77.22 |    86.74 |     100 |   77.22 | ...57,261-267,273 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   92.83 |       94 |    87.5 |   92.83 | ...87-488,573-577 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.51 |     84.8 |   78.68 |   76.51 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   68.16 |    84.24 |    67.5 |   68.16 | ...1028,1057-1065 
  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           |   43.47 |     58.9 |   52.48 |   43.47 |                   
  ...nfigLoader.ts |   78.28 |     64.7 |      95 |   78.28 | ...35-437,441-447 
  ...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 |   25.31 |    62.06 |   41.66 |   25.31 | ...85-704,710-740 
  ...eLspClient.ts |   32.77 |       80 |   17.64 |   32.77 | ...84-288,294-295 
  ...LspService.ts |   51.85 |    65.98 |   68.57 |   51.85 | ...1339,1399-1409 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |   82.39 |    77.73 |   78.33 |   82.39 |                   
  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.52 |    58.06 |     100 |   79.52 | ...33-940,947-949 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.24 |    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.27 |   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        |   82.27 |    80.37 |   85.08 |   82.27 |                   
  ...nel-memory.ts |    88.7 |    80.95 |      90 |    88.7 | ...00-204,209-212 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |      66 |    73.33 |      50 |      66 | 51,108-149        
  ...entPlanner.ts |     100 |       80 |     100 |     100 | 124,134           
  entries.ts       |   63.77 |    79.16 |      50 |   63.77 | ...72-180,183-189 
  extract.ts       |   91.36 |    72.41 |     100 |   91.36 | ...99,118-121,189 
  ...entPlanner.ts |   91.47 |       75 |     100 |   91.47 | ...03,112-115,289 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   46.21 |    61.53 |   44.44 |   46.21 | ...06,213,216-348 
  indexer.ts       |   94.14 |    83.67 |     100 |   94.14 | ...32-233,334,337 
  manager.ts       |   78.61 |    82.29 |   77.77 |   78.61 | ...1477,1490-1492 
  ...ent-config.ts |   80.75 |    76.11 |   82.35 |   80.75 | ...15,234,241-247 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   80.48 |    92.53 |     100 |   80.48 | ...45-346,354-355 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   96.96 |     86.2 |     100 |   96.96 | ...22,225,560-561 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   97.77 |    85.41 |     100 |   97.77 | 50,70,213,228     
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   58.33 |    67.34 |   56.25 |   58.33 | ...61-282,358-403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   93.33 |    81.25 |     100 |   93.33 | ...,94-95,119-120 
  ...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 |   79.38 |    78.33 |   81.81 |   79.38 | ...58-272,286-291 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   91.16 |    88.48 |   89.74 |   91.16 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   90.55 |    91.42 |     100 |   90.55 | 146,152,155-164   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.66 |    92.75 |     100 |   98.66 | 163,325,331       
  modelRegistry.ts |     100 |    98.91 |     100 |     100 | 177               
  modelsConfig.ts  |   87.95 |    86.54 |   85.36 |   87.95 | ...1349,1378-1379 
  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   |   82.94 |    91.32 |   69.69 |   82.94 |                   
  autoMode.ts      |   97.78 |    94.08 |     100 |   97.78 | ...42,570-577,686 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.44 |     100 |      94 | 158-165,385-389   
  ...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 |   84.91 |     89.1 |      80 |   84.91 | ...1026,1132-1136 
  rule-parser.ts   |   97.42 |    93.82 |     100 |   97.42 | ...-890,1039-1041 
  ...-semantics.ts |   70.36 |    91.07 |   46.66 |   70.36 | ...2237,2300-2303 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/plan-gate     |   76.16 |    91.42 |      80 |   76.16 |                   
  ...viewAgents.ts |   52.28 |    88.46 |   66.66 |   52.28 | ...24-220,242-243 
  ...provalGate.ts |   92.47 |    92.85 |   85.71 |   92.47 | ...86-187,268-274 
  state.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 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     |   79.06 |    74.45 |   68.75 |   79.06 |                   
  all-providers.ts |   69.23 |      100 |       0 |   69.23 | 71-72,76-82,86-92 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   92.78 |    84.12 |     100 |   92.78 | ...39-240,313-314 
  ...der-config.ts |    72.6 |    69.49 |   73.91 |    72.6 | ...94-495,502-511 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.56 |    89.28 |   55.55 |   97.56 |                   
  ...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 |                   
  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.3 |     78.8 |   95.89 |    85.3 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.55 |    73.71 |   90.62 |   82.55 | ...1183-1199,1229 
  ...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      |   88.41 |    85.14 |   94.91 |   88.41 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.35 |    85.34 |     100 |   97.35 | ...94,117,417-418 
  ...ionService.ts |   96.65 |    95.57 |     100 |   96.65 | ...76,692,821-829 
  ...ingService.ts |   87.18 |    83.14 |   83.72 |   87.18 | ...1456,1471-1472 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |   99.52 |    96.42 |     100 |   99.52 | 98                
  cronScheduler.ts |   95.34 |    91.21 |     100 |   95.34 | ...1011,1320-1321 
  cronTasksFile.ts |   93.78 |     87.5 |     100 |   93.78 | ...72-173,182-183 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   82.07 |       92 |      80 |   82.07 | ...43,149-150,155 
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   91.27 |    82.69 |    90.9 |   91.27 | ...94,196,294-301 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |   69.86 |    69.35 |   93.33 |   69.86 | ...2066,2094-2095 
  ...ionService.ts |   98.09 |    97.07 |     100 |   98.09 | ...90-591,638-639 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   96.06 |    91.48 |   96.96 |   96.06 | ...49,850,864-866 
  ...orRegistry.ts |   97.27 |    91.22 |     100 |   97.27 | ...50-451,606-607 
  ...ttachments.ts |   97.24 |    90.34 |     100 |   97.24 | ...08,646,661-662 
  sessionRecap.ts  |     9.7 |      100 |       0 |     9.7 | 42-172            
  ...ionService.ts |    87.9 |    80.61 |   96.22 |    87.9 | ...1918,1988-2008 
  sessionTitle.ts  |   93.87 |    71.15 |     100 |   93.87 | ...32-235,266-267 
  ...ionService.ts |   84.03 |    77.77 |   96.96 |   84.03 | ...2381,2387-2392 
  ...pInhibitor.ts |   97.34 |    92.68 |     100 |   97.34 | ...28,167,361-362 
  ...Estimation.ts |     100 |    86.66 |     100 |     100 | 96-97             
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...oryService.ts |   89.03 |    65.38 |     100 |   89.03 | ...23-325,330-331 
  ...reeCleanup.ts |   14.56 |      100 |   33.33 |   14.56 | 58-185            
  ...ionService.ts |   87.98 |    86.72 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.35 |    95.69 |     100 |   99.35 |                   
  microcompact.ts  |   99.35 |    95.69 |     100 |   99.35 | 224-225,618       
 ...s/visionBridge |   97.01 |    94.73 |   94.11 |   97.01 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   96.08 |     91.8 |      90 |   96.08 | ...14,221,309,406 
 src/skills        |    88.2 |    86.98 |   90.16 |    88.2 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |     93.1 |     100 |     100 | 93,112            
  skill-load.ts    |   94.84 |     87.3 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   83.44 |    82.16 |   82.35 |   83.44 | ...1202,1209-1213 
  skill-paths.ts   |   89.65 |    86.95 |     100 |   89.65 | ...11-112,117-118 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |       98 |     100 |   97.91 | 277-278           
 ...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     |      86 |     85.9 |   94.33 |      86 |                   
  ...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 |   81.51 |    80.66 |   91.17 |   81.51 | ...1450,1527-1528 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   78.98 |    87.16 |   80.85 |   78.98 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   98.96 |    79.48 |     100 |   98.96 | 169,183           
  ...on-tracing.ts |   74.55 |    73.21 |   70.58 |   74.55 | ...95,336-338,354 
  ...attributes.ts |   97.47 |    93.15 |     100 |   97.47 | 39-44             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   52.84 |    68.88 |      60 |   52.84 | ...1318,1335-1355 
  metrics.ts       |   76.07 |    78.57 |   78.94 |   76.07 | ...1021,1024-1035 
  ...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       
  sdk.ts           |   86.75 |     88.4 |   66.66 |   86.75 | ...17-621,659-681 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.06 |    88.25 |   96.55 |   90.06 | ...1541,1572-1575 
  ...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         |   78.83 |    85.27 |   83.54 |   78.83 | ...1301,1305-1312 
  uiTelemetry.ts   |   93.07 |    92.85 |   83.33 |   93.07 | ...62,290,410-411 
 ...ry/qwen-logger |    69.9 |    83.01 |   65.51 |    69.9 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |    69.9 |    82.85 |   64.91 |    69.9 | ...1079,1117-1118 
 src/test-utils    |   93.44 |    96.15 |   77.77 |   93.44 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   91.71 |    97.36 |   74.19 |   91.71 | ...54,218-219,232 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   83.77 |     83.3 |   87.52 |   83.77 |                   
  ...erQuestion.ts |   90.74 |    82.43 |    92.3 |   90.74 | ...23-424,431-432 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  cron-create.ts   |   88.69 |    94.73 |   66.66 |   88.69 | ...,45-46,183-191 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.16 |    93.75 |    87.5 |   98.16 | 50-51             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |   82.35 |    73.68 |   85.71 |   82.35 | ...,86-91,124-138 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |    81.7 |    73.41 |     100 |    81.7 | ...28-531,561-564 
  glob.ts          |   95.92 |    87.69 |    92.3 |   95.92 | ...16,172,303,306 
  grep.ts          |   83.09 |    86.66 |   80.95 |   83.09 | ...60-661,711-712 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  loop-wakeup.ts   |   99.24 |    92.85 |     100 |   99.24 | 44                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.77 |    60.09 |   90.32 |   72.77 | ...1211,1213-1214 
  ...nt-manager.ts |   81.32 |    79.44 |    85.1 |   81.32 | ...3160,3162-3163 
  mcp-client.ts    |   75.61 |     83.6 |   86.04 |   75.61 | ...1926,1930-1933 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   91.66 |    89.74 |   96.77 |   91.66 | ...20-721,771-772 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.65 |    84.05 |   88.46 |   91.65 | ...87,600,796-801 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    89.74 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   94.75 |    90.32 |   81.81 |   94.75 | ...04,307,390-391 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ripGrep.ts       |   95.87 |     88.4 |   94.73 |   95.87 | ...56-657,663-664 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |    82.3 |    89.65 |    62.5 |    82.3 | ...37-243,326-334 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   77.34 |    81.92 |   91.48 |   77.34 | ...4807,4870-4871 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |    90.2 |     93.1 |   88.88 |    90.2 | ...64,468,497-519 
  ...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     |   89.27 |    82.05 |   92.85 |   89.27 | ...50-555,577-578 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   76.09 |     76.1 |   81.39 |   76.09 | ...62-863,871-872 
  tool-search.ts   |    94.1 |    89.47 |   93.33 |    94.1 | ...69,384-393,447 
  tools.ts         |   93.97 |     90.9 |   95.23 |   93.97 | ...99-500,516-522 
  web-fetch.ts     |   90.12 |    85.71 |   92.85 |   90.12 | ...11-312,326-327 
  write-file.ts    |   84.28 |    82.79 |   84.61 |   84.28 | ...87-690,727-762 
 src/tools/agent   |   83.51 |    84.03 |   81.52 |   83.51 |                   
  agent.ts         |   83.56 |    84.15 |   81.17 |   83.56 | ...3420,3442-3452 
  fork-subagent.ts |   82.35 |    77.77 |   85.71 |   82.35 | 83-101,133-134    
 ...tools/artifact |   95.58 |    91.01 |   88.37 |   95.58 |                   
  artifact-tool.ts |   90.23 |    81.39 |   69.23 |   90.23 | ...81-282,290-293 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   87.46 |    79.41 |   85.71 |   87.46 |                   
  workflow.ts      |   87.46 |    79.41 |   85.71 |   87.46 | ...51-652,664-667 
 src/utils         |   90.68 |    88.89 |   95.13 |   90.68 |                   
  LruCache.ts      |       0 |        0 |       0 |       0 | 1-41              
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.76 |    93.26 |     100 |   94.76 | ...30-531,634-638 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.11 |    89.47 |     100 |   91.11 | ...46-147,154-155 
  cronDisplay.ts   |     100 |    91.66 |     100 |     100 | 15,43,57          
  cronParser.ts    |   95.34 |     93.1 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.42 |    94.11 |   88.23 |   96.42 | 185-189           
  editHelper.ts    |   93.63 |    83.52 |     100 |   93.63 | ...28-429,463-464 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.78 |    89.13 |      95 |   96.78 | ...51-252,257,403 
  errorParsing.ts  |    97.7 |    97.05 |     100 |    97.7 | 72-73             
  ...rReporting.ts |   88.46 |       90 |     100 |   88.46 | 69-74             
  errors.ts        |   80.82 |    87.28 |   57.89 |   80.82 | ...08-324,328-334 
  fetch.ts         |   72.45 |    81.81 |   71.42 |   72.45 | ...31,142-143,162 
  fileUtils.ts     |   92.64 |    86.88 |   95.23 |   92.64 | ...1204,1236-1242 
  forkedAgent.ts   |   91.98 |    80.85 |   93.75 |   91.98 | ...90,598,603-610 
  formatters.ts    |   81.81 |       75 |     100 |   81.81 | 15-16             
  ...eUtilities.ts |   89.21 |    86.66 |     100 |   89.21 | 16-17,49-55,65-66 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,330-335 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  gitDiff.ts       |   92.36 |    80.09 |     100 |   92.36 | ...55-856,928-929 
  gitDirect.ts     |   98.46 |    90.17 |     100 |   98.46 | 148,268,352       
  ...noreParser.ts |   93.84 |     91.3 |     100 |   93.84 | ...03-104,185-186 
  gitUtils.ts      |   72.91 |    90.32 |   83.33 |   72.91 | ...,77-78,102-153 
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   93.13 |     92.3 |     100 |   93.13 | ...16-317,356-359 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.01 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   93.77 |    89.02 |     100 |   93.77 | ...13-319,406-407 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.18 |     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  |   90.85 |    87.87 |     100 |   90.85 | ...97-199,222-227 
  partUtils.ts     |     100 |    98.63 |     100 |     100 | 206               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.72 |    92.59 |     100 |   93.72 | ...47-448,450-452 
  pdf.ts           |   93.68 |    87.05 |     100 |   93.68 | ...96-297,321-325 
  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 |   58.57 |       76 |     100 |   58.57 | ...4,88-89,95-100 
  ...noreParser.ts |   92.45 |     90.9 |     100 |   92.45 | ...72-173,186-187 
  rateLimit.ts     |   93.75 |    88.34 |     100 |   93.75 | ...13,218-219,262 
  readManyFiles.ts |   95.13 |    85.18 |     100 |   95.13 | ...24-226,252-253 
  retry.ts         |   95.93 |    91.83 |     100 |   95.93 | ...33,524-525,543 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.52 |    96.84 |     100 |   97.52 | ...05,255-256,282 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   50.94 |    85.71 |      70 |   50.94 | ...54-255,268-346 
  ...sDiscovery.ts |   97.42 |    92.85 |     100 |   97.42 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |      83 |    86.77 |   95.45 |      83 | ...68,593,622-631 
  ...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 |   74.07 |    83.33 |     100 |   74.07 | 40-46             
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   90.78 |    88.23 |     100 |   90.78 | ...41-42,93,95-96 
  ...aValidator.ts |   92.09 |    83.56 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.72 |    92.12 |     100 |   91.72 | ...36-539,615-616 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |     83.8 |     100 |   95.98 | ...70,386,466,485 
  shell-utils.ts   |   86.24 |    89.61 |     100 |   86.24 | ...2003,2010-2014 
  ...lAstParser.ts |   95.57 |    85.88 |     100 |   95.57 | ...1066-1068,1078 
  ...ContextEnv.ts |     100 |      100 |     100 |     100 |                   
  ...nlyChecker.ts |   95.08 |    91.66 |     100 |   95.08 | ...15-316,324-325 
  sideQuery.ts     |   86.82 |     86.2 |     100 |   86.82 | ...81-187,189-195 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   81.48 |    77.77 |     100 |   81.48 | 54-59             
  ...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 
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    92.85 |     100 |     100 | 71                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  tool-utils.ts    |    93.6 |     91.3 |     100 |    93.6 | ...58-159,162-163 
  ...ultCleanup.ts |   15.74 |    33.33 |      25 |   15.74 | 33-134            
  ...Compaction.ts |   95.68 |    95.32 |     100 |   95.68 | ...29-334,533-534 
  truncation.ts    |   75.55 |    85.71 |   71.42 |   75.55 | ...44-449,453-477 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |     87.5 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.68 |    80.38 |   94.69 |   83.68 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   82.47 |    76.22 |      95 |   82.47 | ...1525,1559-1560 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   68.81 |    73.82 |   83.87 |   68.81 |                   
  ...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.

DragonnZhang
DragonnZhang previously approved these changes Jul 2, 2026

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

Implements nested sub-agent depth limiting (maxSubagentDepth, default 5) with a clean separation of concerns: schema-level gating in prepareTools(), runtime guard in execute(), and depth persistence for background/foreground resume and deferred approval. Fork and teammate exclusion rules are properly enforced. Depth arithmetic is consistent across childLaunchDepth(), canSpawnNestedAgent(), and runWithAgentContext(depthOverride). Comprehensive test coverage including edge cases (frameless prepareTools, fork spawn blocking, teammate routing from nested agents). CI all pass. No issues found.

— qwen3-coder via Qwen Code /review

// control-plane tool follows the static exclusion set unchanged.
const isExcluded = (name: string | undefined): boolean => {
if (!name) return false;
if (name === ToolNames.AGENT) return !nestingAllowed;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] This re-admits agent for every non-team, non-fork agent frame while depth allows it, but workflow-launched agents are also wrapped in runWithAgentContext and their workflow deny list does not include agent. That means a workflow leaf now receives the spawning tool, even though the PR description says workflow agents remain non-nesting. A workflow child can then launch arbitrary sub-agents outside the workflow orchestrator's agent accounting and return-value contract. Please either add ToolNames.AGENT to the workflow subagent deny floor or add an explicit workflow-agent execution guard here before allowing nesting.

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 2c50077 — added agent to the workflow-subagent disallowed floor, so workflow-spawned agents never receive the tool regardless of remaining depth. Both spawn paths (default dispatch and custom agentType, which unions the floor) are covered, and the orchestrator tests now assert it.

Comment thread packages/core/src/tools/agent/agent.ts Outdated
// check), so a well-behaved model never reaches here. Teammate spawns
// returned above and are not gated by depth. See
// knowledge/qwen-code/design/nested-subagents.md.
const maxSubagentDepth = this.config.getMaxSubagentDepth();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] The depth guard is now the only check before a nested spawn proceeds, but the spawn path below loads the requested child config from scratch. It does not propagate the parent's effective tool constraints, so a parent subagent limited with tools: [read_file, agent] or disallowedTools: [run_shell_command] can call agent and get a default general-purpose child with tools: ['*'], regaining tools the parent was explicitly denied. Please either prevent agent from being offered to constrained parents, or carry the parent's effective allow/deny set into nested children and intersect/union it with the child config.

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'd push back on this one. Keeping the child's tool surface independent of the parent's is the reference behavior — claude-code assembles the worker's pool independently, with an explicit code comment that workers "aren't affected by the parent's tool restrictions". The reasoning holds here too:

  • A subagent's tools list is a focus mechanism, not a privilege boundary. The privilege boundary is the permission system, which gates every nested child's tool executions exactly as it does the parent's.
  • Spawn capability is opt-in: an explicit tools list only carries agent if its author granted it, and the child types it can name are agent definitions from the same trust domain (the operator's own configs plus builtins).
  • Intersecting surfaces would break legitimate patterns — e.g. a read-only coordinator agent that delegates edits to a writer child.

If we want subtree-wide restriction later, per-agent constraints on spawnable child types would be a cleaner mechanism than silently intersecting tool sets. Happy to file that as follow-up work, but I'd keep this PR aligned with the reference semantics.

Comment thread packages/core/src/config/config.ts Outdated
this.maxSubagentDepth =
params.maxSubagentDepth == null
? 5
: Math.max(1, Math.floor(params.maxSubagentDepth));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] This clamp preserves non-finite values. JSON settings like { "model": { "maxSubagentDepth": 1e309 } } parse to Infinity; Math.floor(Infinity) and Math.max(1, Infinity) both remain Infinity, so canSpawnNestedAgent(maxDepth) never reaches the cap. Since this setting is the main recursion guardrail, please require a finite integer and cap or reject absurdly large values before storing it.

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 2c50077 — non-finite values (NaN, Infinity from JSON 1e309) now fall back to the default of 5, and finite values clamp to the range 1–100, mirroring the maxToolCalls typo ceiling. Tests cover Infinity, NaN, and an absurd 5000.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Design doc reference: multiple comment blocks across the PR reference knowledge/qwen-code/design/nested-subagents.md but this file does not exist in the repository. Consider creating it or inlining the key design decisions into the code comments.

Test coverage gaps (needs human review):

  • No direct unit tests for canSpawnNestedAgent/childLaunchDepth/isTopLevelSession primitives in agent-context.test.ts
  • No prepareTools() fork-context test in agent-core.test.ts
  • No background-agent-resume depth restoration test
  • No test for nested sub-agent requesting fork fallback to regular sub-agent
  • buildSpawnBlockedResult returnDisplay shape not asserted in depth guard tests (only llmContent checked)
  • AgentInteractive nested-construction depth pinning untested (only top-level construction covered)

Comment thread packages/core/src/config/config.ts Outdated
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
this.bugCommand = params.bugCommand;
this.maxSessionTurns = params.maxSessionTurns ?? -1;
// Default 5 (nesting on). Explicit values below 1 clamp to 1 so the knob

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] No NaN/Infinity guard on maxSubagentDepth. Math.floor(NaN) propagates NaN (blocks all nesting silently), Infinity passes through (unbounded nesting, defeating the safety cap). The Number.isFinite pattern is already used at line 1224 for maxToolCalls. Also no upper-bound clamp — maxToolCalls caps at 1,000,000 "to catch typos" but this knob has no equivalent.

Suggested change
// Default 5 (nesting on). Explicit values below 1 clamp to 1 so the knob
this.maxSubagentDepth =
params.maxSubagentDepth == null
? 5
: Math.min(
100,
Math.max(
1,
Math.floor(
Number.isFinite(params.maxSubagentDepth)
? params.maxSubagentDepth
: 5,
),
),
);

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Applied in 2c50077 with one tweak on the suggestion: a non-finite value falls back to the default (5) before the range clamp, and the ceiling is 100. Tests cover Infinity, NaN, and the cap.

export function runWithAgentContext<T>(
agentId: string,
fn: () => Promise<T>,
depthOverride?: number,

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] Stale comment at line 38: the AgentContext.depth docstring says "Auto-incremented; callers do not pass it" but this new depthOverride parameter explicitly allows callers to pin the depth (used by background-resume, AgentInteractive, and deferred-approval paths). Update to e.g. "Auto-incremented by default; depthOverride restores the original launch depth on resume paths."

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 2c50077 — the docstring now says the depth is auto-incremented by default and that resume paths (background resume, AgentInteractive, deferred approvals) pin the original launch depth via depthOverride.

Comment thread packages/core/src/tools/agent/agent.ts Outdated
// Authoritative runtime backstop for sub-agent nesting: reject the spawn
// when it would exceed maxSubagentDepth. AgentCore.prepareTools() also
// hides the AgentTool from leaf-depth sub-agents (same canSpawnNestedAgent
// check), so a well-behaved model never reaches here. Teammate spawns

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] No debugLogger call when the nesting depth guard or fork spawn guard fires. The rejection is only visible in the LLM-facing ToolResult — invisible to operators, log aggregators, and alerting. The file has 20+ debugLogger calls elsewhere for similar events. Consider adding:

debugLogger.debug(
  '[AgentTool] Nesting depth guard blocked spawn: depth=%d childLevel=%d max=%d type=%s',
  getCurrentAgentDepth(), childLaunchDepth() + 1, maxSubagentDepth, this.params.subagent_type,
);

(Same for the fork guard below.)

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added in 2c50077 — both the depth guard and the fork containment guard now emit a debug log (child level, cap, and requested type for the depth guard) before returning the blocked result.

isForkRequested &&
isForkSubagentEnabled(this.config) &&
// v1: fork is a top-level-only capability. A sub-agent — which may now
// carry the AgentTool via nesting — that requests a fork falls back to

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] Silent fork-to-subagent downgrade. When a nested sub-agent requests subagent_type: "fork", isTopLevelSession() makes isFork false and the request silently falls through to a regular isolated sub-agent. The model asked for context-sharing execution but gets isolation with no diagnostic. Consider adding a debug log:

if (isForkRequested && !isFork && !isTopLevelSession()) {
  debugLogger.debug('[AgentTool] Fork downgraded to regular sub-agent at depth %d', getCurrentAgentDepth());
}

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added in 2c50077 — the downgrade now logs its reason (forks do not nest vs. forking unavailable in this session), and a new test pins the fallback: a nested fork request resolves to the awaitable general-purpose sub-agent.

const toolsList: FunctionDeclaration[] = [];

const excludedFromSubagents = getExcludedToolsForCurrentContext();

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] Stale comment on EXCLUDED_TOOLS_FOR_SUBAGENTS (line 113): says "AgentTool prevents recursive subagent spawning" implying unconditional exclusion, but isExcluded() now depth-gates AgentTool — it IS available to sub-agents when nesting is permitted. The set's ToolNames.AGENT entry is now a dead fallback. Consider updating the comment to: "AgentTool is depth-gated (excluded when canSpawnNestedAgent() returns false); see isExcluded() in prepareTools()."

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated in 2c50077. One correction to the note: the ToolNames.AGENT entry is not dead — the fork spawn path filters the parent's inline tool declarations through the raw set (and background-agent-resume consults it too), so the entry stays as the fail-closed floor for consumers of the set itself. The comment now spells out the depth-gating relationship.

argv.maxSessionTurns ?? settings.model?.maxSessionTurns ?? -1,
maxWallTimeSeconds: resolveMaxWallTimeSeconds(argv, settings),
maxToolCalls: resolveMaxToolCalls(argv, settings),
// Undefined flows through to Config's default (5) and clamp logic.

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] No --max-subagent-depth CLI flag, unlike sibling settings --max-session-turns (resolved via resolveMaxSessionTurns(argv, settings)) and --max-tool-calls (resolved via resolveMaxToolCalls(argv, settings)). Users cannot override nesting depth for a single run from the command line. Consider adding a --max-subagent-depth flag with a resolver for consistency.

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added in 2c50077--max-subagent-depth mirrors the sibling budget flags: flag takes precedence over model.maxSubagentDepth, validates loudly as an integer in 1–100 (yargs NaN from a typo fails at startup instead of silently falling back), and the setting is now documented in settings.md alongside the flag.

- Deny the agent tool to workflow-spawned subagents: depth gating would
  otherwise re-admit it, letting a workflow leaf spawn outside the
  orchestrator's concurrency cap, agent accounting, and token budget.
- Reject non-finite maxSubagentDepth values (JSON 1e309 parses to
  Infinity and would unbound the recursion cap; NaN would silently block
  all nesting) and cap the knob at 100 to catch typos.
- Add a --max-subagent-depth CLI flag mirroring sibling budget flags,
  with loud validation for flag typos, and document the setting.
- Log guard rejections (depth, fork containment) and silent
  fork-to-subagent downgrades through the agent debug logger.
- Refresh stale comments (depthOverride resume pinning, depth-gated
  AgentTool exclusion) and drop references to a design doc that lives
  outside the repository.
- Fill review-noted test gaps: nesting predicate primitives, fork-context
  prepareTools, persisted-depth restoration on background resume,
  nested AgentInteractive depth pinning, nested fork fallback, and the
  blocked-spawn returnDisplay shape.
@tanzhenxin

Copy link
Copy Markdown
Collaborator Author

Re the review-level notes (design doc + coverage), addressed in 2c50077:

Design doc references — dropped all of them. The path pointed at a doc in my local knowledge workspace, not this repository; the key design decisions (two-layer enforcement sharing one predicate, resume depth pinning, fork/teammate/workflow exclusions) were already inlined in the comments at each enforcement point, so the references added nothing for repo readers.

Test gaps — all six are now covered:

  • direct unit tests for canSpawnNestedAgent / childLaunchDepth / isTopLevelSession, including a depthOverride-pinned frame
  • a prepareTools() fork-context test (AgentTool stripped even when depth would permit nesting)
  • a background-resume test asserting the persisted launch depth is restored into the resumed agent's frame
  • a nested fork request test pinning the fallback to the awaitable general-purpose sub-agent
  • the blocked-spawn returnDisplay shape (task_execution / failed / terminateReason) asserted in the depth-guard test
  • an AgentInteractive test pinning construction-time depth when built inside a sub-agent frame (start() runs outside the frame, so it proves the pin)

DragonnZhang
DragonnZhang previously approved these changes Jul 2, 2026

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review Summary

Nested Sub-agents (PR #6189) — Introduces configurable sub-agent nesting depth via model.maxSubagentDepth (default 5).

Analysis

Well-structured implementation of recursive sub-agent spawning with proper depth tracking:

  • Depth tracking: runWithAgentContext extended with depthOverride for resume correctness. New predicates (isTopLevelSession, childLaunchDepth, canSpawnNestedAgent) provide a clean API.
  • Dual guards: Schema-level gating in prepareTools() (prevents tool exposure) + runtime guard in execute() (defense in depth).
  • Persistence: AgentMeta.depth and AgentPersistedCliFlags.maxSubagentDepth ensure resumed agents retain their nesting level.
  • Exclusions: Teammates, forks, and workflow-spawned agents are correctly excluded from nesting in v1.
  • Fork downgrade: Nested agents requesting fork type gracefully fall back to regular sub-agents.

Comprehensive test coverage across all edge cases (depth limits, resume, fork containment, teammate exclusion, deferred approvals).

No high-confidence issues found.

— qwen3-coder via Qwen Code /review

The exhaustive CliArgs mock in gemini.test.tsx missed the new field,
failing CI's clean tsc build (the local incremental build skipped the
test file).
Comment thread packages/core/src/tools/agent/agent.ts Outdated
// runtime backstop necessary. Blocks ALL agent calls from a fork child
// (not just fork-in-fork). This runs before the fork branch below, so the
// recursive-fork case is subsumed here.
if (isInForkExecution()) {

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.

Defense-in-depth asymmetry: execute() backstops forks but not teammates

prepareTools() gates nesting on three exclusions — !isTopLevelSession() && !isTeammate() && !isInForkExecution() && canSpawnNestedAgent(...). But the runtime guards here in execute() only re-check depth (L1833) and isInForkExecution() (this line); there is no !isTeammate() equivalent.

The PR frames the fork guard as a backstop against a hallucinated spawn call even when schema-hiding holds. By that same threat model a teammate is uncovered at this layer: with maxSubagentDepth >= 2, a teammate at depth 0 passes the depth guard (childLevel 2 <= max), isInForkExecution() is false, and the name-routing branch above is skipped (either no name, or !isTopLevelSession() short-circuits it) — so an unadvertised agent call would spawn a regular nested sub-agent, violating the v1 "teammates do not nest" rule.

Not reachable today: the in-process teammate path runs through the AgentCore reasoning loop, which rejects any call outside prepareTools()'s output (allowedToolNames, agent-core.ts:1298), and isTeammate() reliably strips agent from the teammate schema. So this is defense-in-depth only. But since the fork backstop exists here precisely for the non-filtering/wildcard path, a symmetric !isTeammate() guard — or folding all three exclusions into one shared predicate mirroring prepareTools() — would stop the two layers from drifting apart.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch — agreed the backstops should cover the same exclusions as the schema gate. Added a teammate guard in 07c002b, symmetric with the fork guard (debug log + blocked result), with a test pinning it (teammate frame, depth would permit the spawn, guard fires anyway).

On folding all three into one shared predicate: the layers intentionally differ by exactly one term. prepareTools() only ever serves agents, so it uses !isTopLevelSession() to fail closed on a missing frame; execute() must allow the top-level session — it is the normal spawn path. That asymmetry is why they share canSpawnNestedAgent() but not a full predicate; the guard comment now spells this out so the layers don't drift silently.

execute() backstopped depth and fork containment but not the teammate
exclusion, so its guards covered less than prepareTools() gates. A
teammate spawn call that slipped past schema-hiding would have nested.
Block it symmetrically with the fork guard, log the rejection, and pin
the behavior in a test.
Comment thread packages/core/src/tools/agent/agent.ts Outdated
ov.getMaxToolCalls = () => flags.maxToolCalls;
}
if (flags.maxSubagentDepth !== undefined) {
ov.getMaxSubagentDepth = () => flags.maxSubagentDepth;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] persistedCliFlags.maxSubagentDepth is trusted directly when rebuilding the resumed agent config, so the resume path bypasses the new Config clamp/default logic. A malformed or tampered sidecar with maxSubagentDepth: 5000 or JSON 1e309 would make getMaxSubagentDepth() return that raw value after restart, effectively removing the documented 1-100 nesting cap for resumed agents. Please normalize the persisted value before overriding the getter, using the same semantics as Config.

Suggested change
ov.getMaxSubagentDepth = () => flags.maxSubagentDepth;
const maxSubagentDepth = Number.isFinite(flags.maxSubagentDepth)
? Math.min(100, Math.max(1, Math.floor(flags.maxSubagentDepth)))
: 5;
ov.getMaxSubagentDepth = () => maxSubagentDepth;

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 5477164 — and it was worse than the 1e309 case: JSON.stringify turns a legitimate in-memory Infinity into null, which passed the !== undefined guard and made the getter return null. Rather than duplicating the clamp, I extracted it into a shared normalizeMaxSubagentDepth() used by both the Config constructor and the flag-restore path, so the two cannot drift. The resume test now persists 5000 and asserts the restored config reports 100.

requiresRestart: false,
default: 5,
description:
'Maximum number of nested sub-agent levels. 1 disables nesting (sub-agents cannot spawn sub-agents); the default 5 allows a sub-agent to spawn sub-agents up to five levels deep. Values below 1 are clamped to 1. Teammates, forks, and the workflow tool are excluded from nesting.',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This schema description is already stale relative to the runtime and settings.md: it only mentions clamping values below 1 and says "the workflow tool" is excluded, but the implementation now caps values at 100, falls back to the default for non-finite values, and the scoped exclusion is workflow-spawned agents. The generated VS Code schema carries the same wording, so settings UI/schema consumers will see behavior that disagrees with the actual config handling.

Suggested change
'Maximum number of nested sub-agent levels. 1 disables nesting (sub-agents cannot spawn sub-agents); the default 5 allows a sub-agent to spawn sub-agents up to five levels deep. Values below 1 are clamped to 1. Teammates, forks, and the workflow tool are excluded from nesting.',
'Maximum sub-agent nesting depth (1-based levels: a top-level sub-agent is level 1). 1 keeps sub-agents available but disables nesting; the default 5 allows nesting up to five levels deep. Values clamp to the range 1-100; non-finite values fall back to the default. Teammates, forks, and workflow-spawned agents never nest regardless of this setting. Overridable via --max-subagent-depth.',

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 5477164 — took the suggested wording for settingsSchema.ts and regenerated the VS Code schema from it (scripts/generate-settings-schema.ts), so both now match settings.md and the runtime behavior.

The resume path trusted the raw sidecar value, bypassing the Config
clamp — a tampered or malformed sidecar (1e309 parses to Infinity;
JSON.stringify turns Infinity into null) would remove the nesting cap
for resumed agents. Extract the clamp into a shared
normalizeMaxSubagentDepth used by both the Config constructor and the
flag-restore path, and refresh the stale settings schema description
(clamp range, non-finite fallback, workflow-agent wording).
// tampered sidecar (JSON `1e309` parses to Infinity; JSON.stringify
// turns Infinity into null) must not bypass the nesting cap for
// resumed agents. Same semantics as the Config constructor.
const maxSubagentDepth = normalizeMaxSubagentDepth(flags.maxSubagentDepth);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This resume-side normalization now intentionally handles persisted null values, which can happen when a non-finite in-memory value is serialized through JSON. The new resume regression test covers 5000 -> 100, but it does not pin the null -> default 5 case that motivated this branch of the normalization.

Please add or parameterize a resume-path test so a sidecar with persistedCliFlags.maxSubagentDepth: null asserts that overriddenConfig.getMaxSubagentDepth() returns 5.

— gpt-5 via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added in ed1177b — the resume test is now parameterized over both cases (5000 → 100 and null → 5), and the persisted flag type is widened to number | null with a comment documenting the JSON.stringify(Infinity) origin of the null.

…epth

JSON.stringify(Infinity) === 'null', so a sidecar can legitimately carry
null; widen the persisted flag type to admit it and parameterize the
resume test over both the clamp (5000 -> 100) and the null fallback
(null -> 5).
wenshao
wenshao previously approved these changes Jul 3, 2026

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM.

— gpt-5 via Qwen Code /review

@wenshao

wenshao commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the depth-gating design end to end (schema layer, runtime guards, resume/deferred-approval restoration, and the containment story for teammates/forks/workflow agents). The two-layer enforcement built on a shared canSpawnNestedAgent() is solid, and the test coverage for the boundary cases is thorough. I verified a few suspicions that did not pan out, for the record: a hallucinated agent call from a workflow subagent is already rejected at dispatch (processFunctionCalls validates against the prepared declaration list before any registry lookup), so the schema-level WORKFLOW_SUBAGENT_DISALLOWED_TOOLS entry is sufficient there; and the formatting churn in config.ts is prettier-compliance, fine.

8 findings below as inline comments, most severe first:

  1. meta.depth is pinned unvalidated on resume (background-agent-resume.ts:1035) — the one field of the sidecar that can still bypass the cap the PR hardens against.
  2. Monitor notifications from in-process interactive agents are now silently dropped (agent-interactive.ts:151) — a regression from framing runLoop(): owned monitors route only through agentNotificationCallbacks, which nothing registers for these agents.
  3. Nested background spawns have a broken completion contract (agent.ts:2049) — the launcher is told to use send_message/task_stop it doesn't have, and the terminal notification lands in the top-level conversation.
  4. A nested sub-agent's name is dropped with zero signal (agent.ts:1825) — the model believes it delegated to a teammate; not even the debug log fires on this path.
  5. Spawn-eligibility policy duplicated between prepareTools() and execute() (agent.ts:1866).
  6. maxSubagentDepth?: number | null widening defends an impossible state, and its justifying comment is factually wrong (agent-transcript.ts:149).
  7. The 5/1/100 triple is hand-duplicated across three sites (packages/cli/src/config/config.ts:1260).
  8. Constructor-time ambient depth capture in AgentInteractive rests on undocumented non-local invariants (agent-interactive.ts:94) — a note, not a blocker.

1–4 are correctness issues worth addressing before merge (1 and 2 especially); 5–8 are cleanups that could also be follow-ups.

🤖 Generated with Claude Code — Claude Fable 5

// its original nesting level (and spawn eligibility) instead of
// recomputing to depth 0 from this top-level resume frame.
const framedRunBody = () =>
runWithAgentContext(meta.agentId, runBody, meta.depth);

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.

meta.depth flows into the depth override unvalidated — the other half of the tampered-sidecar defense is missing.

meta comes from readAgentMeta(), which is a bare JSON.parse(...) as AgentMeta, and nothing downstream clamps the value: runWithAgentContext only does depthOverride ?? ... (catches null/undefined only), and childLaunchDepth() / canSpawnNestedAgent() do raw arithmetic.

So a malformed or hand-edited sidecar with "depth": -50 pins the resumed frame at −50 → childLaunchDepth() = −49 → canSpawnNestedAgent() passes for every cap, and the resumed subtree gains ~50 levels beyond maxSubagentDepth. Worse, "depth": -1e309 parses to -Infinity, and since -Infinity + 1 === -Infinity, every descendant inherits it — the cap is permanently defeated for the whole subtree.

This is exactly the threat model the same resume path already defends against for the sibling field: applyPersistedCliFlagOverrides re-normalizes persistedCliFlags.maxSubagentDepth because "a malformed or tampered sidecar … must not bypass the nesting cap". The cap check is effectively depth + 2 <= maxDepth; right now the right-hand operand is hardened and the left-hand operand is trusted raw from the same JSON file. This is also the only place a disk-persisted depth re-enters the runtime, so it's the complete fix site.

Suggest mirroring the normalize pattern before pinning:

const restoredDepth = Number.isFinite(meta.depth)
  ? Math.max(0, Math.floor(meta.depth!))
  : undefined; // fall back to auto-increment
const framedRunBody = () =>
  runWithAgentContext(meta.agentId, runBody, restoredDepth);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 4b0c5acnormalizeResumedAgentDepth() (next to the AgentMeta type) now guards the depthOverride. Absent values resume as a fresh launch; anything but an integer in 0–100 fails CLOSED to the depth ceiling — clamping a corrupt value down to 0 would fail open by granting full spawn capacity, so the resumed agent keeps running but cannot spawn. Unit tests cover -50, ±Infinity, NaN, fractionals, and >100; the resume-path test is parameterized over a tampered -50 sidecar asserting the frame pins at 100.

*/
private async runLoop(): Promise<void> {
private runLoop(): Promise<void> {
return runWithAgentContext(

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.

Regression: framing runLoop() makes Monitor notifications from in-process interactive agents silently disappear.

Every tool body now runs under this agent's identity frame, so a monitor call stamps ownerAgentId = getCurrentAgentId() (monitor.ts:318). But MonitorRegistry.dispatchNotification (services/monitorRegistry.ts:591-601) routes owned monitors only through agentNotificationCallbacks, with no session fallback:

const callback = entry.ownerAgentId
  ? this.agentNotificationCallbacks.get(entry.ownerAgentId)
  : this.notificationCallback;
if (!callback) { /* "Dropping monitor notification …" */ return; }

The only registration sites are the AgentTool spawn paths (agent.ts:1064) and background-agent-resume.ts:860 — nothing registers a callback for agents spawned via InProcessBackend (Arena sessions, in-process teammates). And emitTerminalNotification sets entry.notified = true before dispatch, so the one-shot completion notice is consumed even when dropped.

Before this PR, runLoop() was frame-less, these monitors were session-owned, and their notifications reached the session callback. After it: MONITOR is absent from both EXCLUDED_TOOLS_FOR_SUBAGENTS and EXCLUDED_TOOLS_FOR_TEAMMATES, Arena/teammate spawns pass no toolConfig, and the Monitor tool is start-only (no poll action; task_stop is excluded from their toolsets) — so an Arena agent that starts a build/test under a monitor now waits forever with no way to learn it finished.

Options, in order of preference: register an agentNotificationCallbacks entry for in-process interactive agents (routing into their AsyncMessageQueue, analogous to registerOwnedMonitorNotifications); or exclude MONITOR from their toolsets the way WORKFLOW_SUBAGENT_DISALLOWED_TOOLS already does for workflow agents; or make owned-monitor dispatch fall back to the session callback when the owner has no registered callback.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch — this was a real regression from framing runLoop(). Fixed in 4b0c5ac with your first-preference option: InProcessBackend.spawnAgent now registers an agent notification callback that routes owned-monitor notifications into the agent's message queue (enqueueMessage self-wakes the pump, so no lifecycle callback is needed), and releaseAgentResources cancels running monitors and drops the callback — mirroring AgentTool's registerOwnedMonitorNotifications lifecycle. A test pins registration on spawn, delivery into the queue, and teardown on stop.

// the awaitable general-purpose sub-agent (via effectiveSubagentType
// below) instead of opening a nested fork. Fork nesting is deferred
// past v1.
isTopLevelSession();

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.

Nested background spawns are left ungated here, and their completion contract is broken for the launcher.

Fork requests from a nested sub-agent get downgraded on this exact line — but run_in_background: true (or an agent type defined with background: true) from a nested launcher goes through with only the concurrency cap (assertCanStartBackgroundAgent), and then:

  • The success llmContent (~agent.ts:2917-2926) tells the launcher to "Use send_message to continue this agent, or task_stop to cancel" — but both tools are in EXCLUDED_TOOLS_FOR_SUBAGENTS, and the new isExcluded() re-admits only agent. The launcher is instructed to use tools it provably doesn't have.
  • "You will be notified automatically when it completes" is also wrong for it: BackgroundTaskRegistry has a single session-level notificationCallback and register() records no owner, so the child's terminal <task-notification> is injected into the top-level conversation (with a tool-use-id foreign to that history), while the launcher — which typically returns before the child finishes — never hears back. The child's work is orphaned unless the launcher happens to tail the output file.

This state is newly reachable: pre-PR no sub-agent ever carried the AgentTool, and it's on by default (cap 5). Suggest handling it the way the fork case is handled right here: downgrade run_in_background to a foreground (awaited) run when !isTopLevelSession(), deferring nested background delegation until notifications can be routed to the launching agent — or at minimum make the background branch top-level-only in the schema text and fix the returned guidance for nested launchers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 4b0c5ac, taking the downgrade option: a background request (run_in_background or an agent type's background: true) from a nested launcher now runs as an awaited foreground task, exactly parallel to the fork downgrade — with a debug log and a schema-text note that background is top-level-only. Nested background delegation stays deferred until notifications can be routed to the launching agent. Test asserts the nested request completes inline (result text returned, registered with isBackgrounded: false).

// sub-agent could pass `name` and reach executeTeammate, bypassing both
// the v1 "teammates do not nest" rule and the depth guard below. A nested
// sub-agent's `name` falls through to the normal path.
if (this.params.name && !isTeammate() && isTopLevelSession()) {

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.

A nested sub-agent's name is now dropped with zero signal — not even the debug log fires.

With a team active, a nested sub-agent (which now legitimately holds this tool at the default cap of 5) calling agent with name: "alice" skips this block via the new isTopLevelSession() term, and params.name is never referenced again on the fall-through path — a fresh generic one-shot agent spawns at the next level. The debugLogger.debug("Ignoring teammate name …") line can't fire for this case: it's inside the skipped block and gated on !getTeamManager().

The security direction is right (and the depth-1 test pins it), but the silent-success path at default depth is untested and inconsistent with this function's own conventions: the schema served to nested agents still advertises name ("spawn as a named teammate via the active team" — prepareTools filters whole tools, it doesn't rewrite schemas), and every sibling guard (depth, teammate, fork, plan_mode_required) returns a model-visible Error:. Here the model walks away believing alice handled the task — it may report that upward or try to follow up with her.

Suggest either rejecting with an explicit error (mirroring the plan-mode guard) or spawning but prepending a note to the returned llmContent that name was ignored because teammate delegation is top-level-only, plus a debug log on this branch.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 4b0c5ac — the fall-through now logs ("Ignoring teammate name … from a nested sub-agent; spawning a regular sub-agent instead"), and a test pins the silent-success path at the default cap: team active, nested frame, name passed → spawnTeammate never called, loadSubagent called with the requested type.

Comment thread packages/core/src/tools/agent/agent.ts Outdated
// frame — that asymmetry is why the two layers share canSpawnNestedAgent
// rather than one full predicate.) Teammate spawns via `name` returned
// in the team-routing branch above, which requires !isTeammate().
if (isTeammate()) {

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.

Cleanup: the three-exclusion spawn policy is now maintained in two hand-written copies.

prepareTools() composes !isTopLevelSession() && !isTeammate() && !isInForkExecution() && canSpawnNestedAgent(...) (agent-core.ts:519-523); execute() re-states the same teammate/fork/depth exclusions as three sequential guards in a different order. Only the depth term is shared — the symmetry of the other two is maintained by the "symmetric with the fork guard below" comment, and the fork guard's own rationale (wildcard/fallback lists) shows what a missed runtime-side entry costs: a silent spawn bypass. Missed on the schema side it burns model turns on guaranteed-rejected calls.

The long comment above this line argues the two layers can't share one full boolean predicate — which is true, but a reason-enum dissolves the asymmetry:

// agent-context.ts
export function spawnBlockReason(maxDepth: number): 'depth' | 'teammate' | 'fork' | null;

execute() switches on the reason for its per-cause messages (evaluated in the current guard order, preserving which reason wins for a teammate at leaf depth); prepareTools() checks !isTopLevelSession() && spawnBlockReason(...) === null, keeping the fail-closed frame check local, exactly as the comment prescribes. All four predicates are pure ALS reads, so the composition is order-insensitive on the schema side; the fork-before-downgrade ordering in execute() is positional and untouched; no import cycle (identity.ts and fork-subagent.ts don't reach back into agent-context.ts). ~15 net lines, deletes this comment, and turns a comment-enforced invariant into a structural one — the same anti-drift rationale canSpawnNestedAgent's own doc gives.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Taken as proposed in 4b0c5acspawnBlockReason(maxDepth): 'depth' | 'teammate' | 'fork' | null lives in agent-context.ts, evaluated in execute()'s guard order so the winning reason stays stable. execute() switches on it for per-cause messages (with an exhaustiveness check), prepareTools() composes !isTopLevelSession() && spawnBlockReason(...) === null, and the hand-symmetry comment is gone. Unit tests pin the reason precedence including the teammate-at-leaf-depth case.

* serialization (JSON.stringify(Infinity) === 'null'); the resume path
* normalizes it back to the default.
*/
maxSubagentDepth?: number | null;

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.

The | null widening defends a state this codebase cannot produce, and the justifying comment is factually wrong.

The only writer of persistedCliFlags is capturePersistedCliFlags (agent.ts:469, via the two writeAgentMeta call sites), which persists config.getMaxSubagentDepth() — and that is a normalized finite integer 1–100 at every definition: the Config constructor (this.maxSubagentDepth = normalizeMaxSubagentDepth(...)) and the resume override closure both normalize. JSON.stringify(Infinity) === 'null' is true of JavaScript, but Infinity can never be in memory for this field, so "null occurs when a non-finite in-memory value crossed JSON serialization" describes an impossible path. (Pre-PR sidecars just lack the key → undefined, never null.)

Only a hand-tampered/foreign sidecar can carry null — and normalizeMaxSubagentDepth's value == null check in the resume path already covers that without the type widening (reverting to number still typechecks; the runtime hardening stays). AGENTS.md's first principle is "No error handling for impossible scenarios."

Suggest: type it plain number, reword this comment (and the matching one in background-agent-resume.test.ts, "the sidecar can legitimately carry null") to attribute null to malformed/tampered sidecars — the honest framing applyPersistedCliFlagOverrides already uses — and keep or drop the null test row under that label.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right — the in-memory value is normalized at every writer, so the JSON.stringify(Infinity) story described an impossible path. Fixed in 4b0c5ac: the type is plain number again, and the comments here, in the resume override, and in the test row now attribute null to malformed/hand-edited sidecars (the test keeps the null row under that honest label, cast explicitly as tampered input).

Comment thread packages/cli/src/config/config.ts Outdated
): number | undefined {
const value = argv.maxSubagentDepth;
if (value !== undefined && value !== null) {
if (!Number.isInteger(value) || value < 1 || value > 100) {

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.

Cleanup: the {default 5, min 1, max 100} triple is hand-duplicated at three sites.

This validator (bounds in the condition and the error text), normalizeMaxSubagentDepth in core config.ts, and settingsSchema.ts's default: 5 (the vscode settings.schema.json is generated from it, so that one's free). If core's cap or default ever changes, this flag validator drifts — and the failure mode is precisely the one this function's docstring says it exists to prevent: an explicitly passed --max-subagent-depth accepted here, then silently clamped by core.

The codebase already has the exact pattern for this: DEFAULT_STOP_HOOK_BLOCK_CAP and SENSITIVE_SPAN_ATTRIBUTE_MAX_LENGTH_LIMIT are exported from core and consumed by settingsSchema.ts (both as default: and maximum:). Suggest exporting DEFAULT_MAX_SUBAGENT_DEPTH / MAX_SUBAGENT_DEPTH_LIMIT next to normalizeMaxSubagentDepth, using them there, here (condition + interpolated message), and in the schema default.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 4b0c5ac following the DEFAULT_STOP_HOOK_BLOCK_CAP pattern — DEFAULT_MAX_SUBAGENT_DEPTH and MAX_SUBAGENT_DEPTH_LIMIT are exported from core next to the normalizer and consumed by it, the CLI flag validator (condition + interpolated error message), and settingsSchema's default:. The vscode schema stays generated.

constructor(config: AgentInteractiveConfig, core: AgentCore) {
this.config = config;
this.core = core;
this.agentDepth = childLaunchDepth();

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.

Note (non-blocking): constructor-time ambient capture is correct today only via invariants enforced in other files.

Sampling childLaunchDepth() here is safe right now because the single construction site (InProcessBackend.spawnAgent) sits on the spawner's await chain, and both entry paths are top-level-gated elsewhere (Arena via the slash command; teammates via the isTopLevelSession() gate in agent.ts). None of that is visible or documented at the call site, and InProcessBackend.ts isn't touched by this PR — so a future factory/queue/deferred construction would silently record depth 0. That's the same deferral-loses-frame class this PR fixes explicitly for resume (persisted meta.depth) and deferred approvals (inheritedAgentDepth); exposure is bounded (a lost frame grants only level-1 capacity), which is why this is a note rather than a bug.

Cheap hardening: accept an optional explicit depth in AgentInteractiveConfig (the identity is already half-explicit — agentId lives there) and have InProcessBackend pass childLaunchDepth() at the spawn site, or at least document the same-frame precondition at the new AgentInteractive(...) call.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Documented in 4b0c5ac — the constructor now carries the invariant at the capture site: correct only while construction stays on the spawner's await chain, a deferred construction would silently record depth 0 (the same deferral-loses-frame class the resume path solves via persisted meta.depth), and the escape hatch if construction ever moves off the spawn chain is threading depth through AgentInteractiveConfig.

- Normalize persisted meta.depth on resume: the sidecar is untrusted
  JSON, and a tampered negative depth (or -1e309 → -Infinity) would pin
  the resumed frame below zero and pass canSpawnNestedAgent for every
  cap. Invalid values fail closed to the depth ceiling — the agent
  keeps running but cannot spawn.
- Register monitor notification routing for in-process interactive
  agents: framing runLoop() made their monitors agent-owned, and owned
  dispatch has no session fallback, so notifications were silently
  dropped. InProcessBackend now routes them into the agent's message
  queue and tears the routing down on release.
- Downgrade background spawn requests from nested launchers to awaited
  foreground runs: a nested launcher cannot honor the background
  completion contract (send_message/task_stop excluded, notifications
  session-scoped), which orphaned the child's results.
- Extract spawnBlockReason() as the single spawn-exclusion policy
  shared by prepareTools() and execute(), replacing two hand-kept
  copies of the depth/teammate/fork rules.
- Share DEFAULT_MAX_SUBAGENT_DEPTH / MAX_SUBAGENT_DEPTH_LIMIT across
  the core normalizer, the CLI flag validator, and the settings schema.
- Log dropped teammate names from nested spawns; revert the impossible
  |null persisted-flag widening to an honest tampered-sidecar framing;
  document the constructor-time depth capture invariant.
@wenshao

wenshao commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Re-reviewed 4b0c5ac66 against my earlier review — all 8 findings are addressed, and the fix commit holds up under the same scrutiny:

  1. meta.depth hardeningnormalizeResumedAgentDepth() fails closed to the depth ceiling on any tampered/corrupt value (nice touch: clamping down to 0 would have failed open), with the -1e309 → -Infinity case pinned in tests.
  2. Monitor routing for in-process agentsInProcessBackend.spawnAgent now registers the owned-monitor callback into the agent's message queue, and releaseAgentResources tears it down plus cancels running monitors. I verified setAgentNotificationCallback(id, undefined) deletes the map entry, so the teardown path is correct.
  3. Nested background downgrade — mirrors the fork downgrade, schema text updated, foreground result pinned in a test.
  4. spawnBlockReason() — the shared predicate landed cleanly in both consumers; I checked the new agent-context → identity/fork-subagent imports for cycles (fork-subagent's Config import is type-only, no cycle).
  5. | null widening / comment, constants, ambient-capture doc, dropped-name logging — all resolved as discussed.

Ran the six touched suites locally at 4b0c5ac66 (agent-transcript, agent-context, InProcessBackend, background-agent-resume, agent.test, agent-core): 283/283 pass. No new issues found in the delta. LGTM from my side once CI is green.

🤖 Generated with Claude Code — Claude Fable 5

settingsSchema.ts now imports the shared constant, so CLI tests that
mock @qwen-code/qwen-code-core with an explicit export list need the
new export.
* feat(core): allow bounded nested sub-agent spawning via maxSubagentDepth

Sub-agents may now spawn sub-agents up to a configurable maximum nesting
depth (default 5; 1 reproduces the previous no-nesting behavior).
Enforced in two layers sharing one predicate: prepareTools() hides the
agent tool from leaf-depth sub-agents, and AgentTool.execute() rejects
over-depth spawns as an authoritative backstop. Teammates, forks, and
the workflow tool remain excluded from nesting. Launch depth is
persisted in the agent meta sidecar and restored on resume (including
deferred-approval continuations and in-process AgentInteractive frames)
so a resumed nested agent cannot regain spawn capacity.

See knowledge/qwen-code/design/nested-subagents.md.

* feat(cli): display nested sub-agents as a tree in the TUI

Render nested agents depth-first with indent + dim '↳' in the live agent
panel and background tasks view; promote orphaned children to root with a
'· from <parent>' annotation. Detail view gains a level badge, Parent
breadcrumb, and Sub-agents section. The [blocking] tag and two-step cancel
confirm now apply only to provably user-blocking foreground chains. Parent
completion summaries carry a '· N sub-agents' tail (guard-rejected spawns
now record as failed tool calls so the count stays honest). Also fixes the
live-panel Enter-for-detail order mismatch by sharing one display order
between the panel render and the composer keyboard mapping.

* fix(core): address round-1 review on nested sub-agent spawning

- Derive launch metadata (hooks, spans, task rows, meta sidecar) from the
  resolved subagent config instead of the raw requested type, so a fork
  request that falls back to the awaitable path no longer reports "fork".
- Pin the blocked-spawn failure contract in tests: error is set and
  returnDisplay.status is 'failed' for both the depth and fork guards; also
  document the failure-path routing at buildSpawnBlockedResult.
- Drop source-comment references to private knowledge/ design docs that do
  not exist in this repository.

* test: address round-2 review on sub-agent counting and fork fallback

- Exercise the legacy 'task' alias in the scrollback sub-agent count so
  the migration-aware name set is covered, not just the canonical name.
- Pin the nested-fork downgrade: a sub-agent requesting a fork falls back
  to the awaitable general-purpose subagent even in interactive mode.
- Drop a duplicated 'nesting depth guard' describe block left behind by
  the automated base-branch merge (kept the copy with the failure-shape
  assertions).

* fix(core): keep actionable guidance in blocked-spawn error messages

The scheduler's failure path sends only error.message to the model and
the scrollback, discarding llmContent. With the terse terminateReason as
the message, a blocked spawn lost its "do the task yourself instead"
instruction, inviting retry loops. Carry the full guidance text in
error.message and keep terminateReason for the display card.

* test(cli): pin the tree indent clamp at depth beyond TREE_INDENT_MAX_LEVELS

Maintainer mutation-testing on the PR found that removing the clamp in
treeRowPrefix survived the suite. Assert a depth-4 row indents 3 levels
(12 spaces), plus the base marker/indent behavior.

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
@tanzhenxin

Copy link
Copy Markdown
Collaborator Author

Closing the loop on the review notes @wenshao posted on the stacked UI PR (#6191, #6191 (review)), which scoped four findings to this PR's code. All four are now addressed on this branch:

Finding Where it's addressed
depthOverride lacks bounds validation 4b0c5acnormalizeResumedAgentDepth normalizes persisted meta.depth before it's pinned via runWithAgentContext; invalid values fail closed to the depth ceiling (the resumed agent keeps running but cannot spawn), which is stricter than the suggested clamp-to-zero — corruption must not mint spawn capacity. Parameterized resume tests cover negative / -1e309 / NaN inputs.
Fork fallback from nested sub-agent untested 2c50077 (depth-guard suite) + #6191's 484b9c9 (Fork-dispatch suite, interactive mode, asserts no fork is created — isolates the top-level-only gate).
Nested AgentInteractive construction untested 2c50077 — depth-pinning test in agent-interactive.test.ts.
Inline declaration-filter widening untested Covered by the filters inline declarations using the full subagent exclusion floor test (from #6087, present on this branch), which runs against the widened isExcluded predicate and asserts non-AGENT control-plane tools (send_message, task_update, plan lifecycle) are stripped from inline FunctionDeclarations; 2c50077 adds the fork-context prepareTools case on top.

Just verified the three suites locally on this branch: 81/81 green.

@wenshao

wenshao commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

✅ Maintainer local verification — real binary + tmux E2E

Built the real bundle at PR head 699cb26 (npm ci && npm run bundlenode dist/cli.js, v0.19.4) and drove it end-to-end against a fake OpenAI server that forces a greedy nested agent spawn at each level, capturing every /chat/completions request. The decisive signal (per the PR's own test plan) is which tools each level advertises — I tabulate that per nesting level below.

Verdict: the feature behaves exactly as specified in all scenarios. Recommend merge (one non-blocking note on the PR description at the end).


1) Backend depth-gating — the decisive per-level evidence

backend evidence

Every captured request was classified by its agent's nesting level (via a per-level seed marker that only lands in that agent's own user/system message) and by whether its tools[] advertises agent:

Scenario cap (via) L0 L1 L2 Result
S1 nested (default) 5 · default agent✓·15 agent✓·51 agent✓·51 2-level chain runs; leaf nonce relays to stdout
S2 cap boundary 2 · model.maxSubagentDepth ✓·15 agent✓·51 agent✗·50 L2 not offered agent; no L3
S3 old behavior 1 · --max-subagent-depth ✓·15 agent✗·50 L1 cannot delegate — pre-feature contract
S4 no regression 5 · default ✓·15 agent✓ (leaf) plain one-level delegation unchanged
S5 clamp 0→1 0 → clamped 1 ✓·15 agent✗·50 maxSubagentDepth:0 normalizes to 1 (≡ S3)

An allowed level advertises 51 tools; a leaf level advertises 50exactly the agent tool removed, and the flip lands precisely at each cap boundary. When a leaf level's model is forced to call agent anyway, qwen rejects it with Tool "agent" not found — so a hallucinated over-depth spawn produces no deeper agent. In S1 the leaf returned a random nonce that reappears in the parent's role:tool message and then in top-level stdout, proving the child actually ran and its result propagated up the chain.

2) Both enforcement layers verified

  • Layer 1 — schema gating (prepareTools): observed end-to-end above; the leaf level literally cannot see agent.
  • Layer 2 — runtime backstop (AgentTool.executespawnBlockReason): the 8 changed core suites (629 tests) pass. A mutation neutering the shared depth predicate (canSpawnNestedAgent → true) fails 8 tests across all three layers, including the runtime-guard test "rejects a spawn that would exceed maxSubagentDepth" (expected 'Subagent "file-search" not found' to contain 'nesting depth limit reached') — while the teammate/fork guards stay green (independent branches). This confirms both layers derive from one predicate and cannot drift, exactly as the PR claims.
  • Flag validation: --max-subagent-depth 0|3.5|200|abc are all loudly rejected (must be an integer between 1 and 100); the settings path silently clamps — the intended asymmetry.

3) TUI nested tree (the #6191 tree work is inside this branch)

nested tree

  • Top: captured live in tmux from the running binary — a top-level session spawns a background agent that spawns a nested child; the real LiveAgentPanel renders them as a tree (), status bar shows 2 local agents.
  • Bottom: a render of the real BackgroundTasksDialog with a 3-level fixture — depth-first indent, connectors, and [blocking] correctly only on the foreground root (nested children block their background parent, not the user's turn).

⚠️ One non-blocking note: the description is stale vs. the diff

The body says "This PR is backend-only … the tree-style display … will be submitted as a follow-up PR stacked on this one." That follow-up — #6191 — was merged into feat/nested-subagents on 2026-07-03 (commit 699cb26), so its tree code (agent-forest.ts, LiveAgentPanel, BackgroundTasksDialog, ToolMessage, InputPrompt) is already in this branch and is not yet in main. Merging #6189 therefore ships the TUI tree too. That's fine — both layers are verified here — but the "backend-only" wording should be updated so reviewers know the real merge surface.

Housekeeping

  • Head unchanged at review time (699cb26); Test (ubuntu-latest) is green, mac/win/Integration are the usual named-job skips, blocked is the review gate (not a CI failure).
  • Consistent with the PR's own stated risk: concurrency stays bounded (foreground nested runs are serial; a nested background request is downgraded to an awaited foreground run), but a deep tree's cumulative token spend is not separately budgeted — a tree-wide budget is a reasonable follow-up.
🇨🇳 中文版(完整对应)

✅ 维护者本地验证 — 真实二进制 + tmux 端到端

在 PR head 699cb26 上构建了真实产物(npm ci && npm run bundlenode dist/cli.js,v0.19.4),并用一个"伪 OpenAI"服务器端到端驱动它:该服务器在每一层强制贪婪地派生嵌套 agent,同时记录每一次 /chat/completions 请求。按 PR 自己的测试计划,决定性证据是每一层声明了哪些工具 —— 下面我按嵌套层级逐一列出。

结论:功能在所有场景下的表现与说明书完全一致,建议合并(末尾有一条关于 PR 描述的非阻断说明)。


1)后端深度门控 —— 决定性的逐层证据

(见上方"backend evidence"图)

每条捕获的请求都按其代理的嵌套层级分类(通过只会落到该代理自己 user/system 消息里的逐层种子标记来识别),并判断其 tools[] 是否声明了 agent

场景 上限(来源) L0 L1 L2 结果
S1 嵌套(默认) 5 · 默认 agent✓·15 agent✓·51 agent✓·51 两层链路执行;叶子 nonce 回传到 stdout
S2 上限边界 2 · model.maxSubagentDepth ✓·15 agent✓·51 agent✗·50 L2 未获得 agent;无 L3
S3 旧行为 1 · --max-subagent-depth ✓·15 agent✗·50 L1 无法委派 —— 与功能前契约一致
S4 无回归 5 · 默认 ✓·15 agent✓(叶子) 普通单层委派保持不变
S5 钳制 0→1 0 → 钳制为 1 ✓·15 agent✗·50 maxSubagentDepth:0 归一化为 1(≡ S3)

允许派生的层级声明 51 个工具;叶子层级声明 50 个 —— 恰好少了 agent 这一个工具,而且这个翻转精确地落在每个上限边界处。当叶子层级的模型仍被强制调用 agent 时,qwen 以 Tool "agent" not found 拒绝 —— 所以越界的幻觉派生不会产生更深的代理。S1 中叶子返回的随机 nonce 出现在父代理的 role:tool 消息里、再出现在顶层 stdout,证明子代理确实运行且其结果沿链路逐层回传。

2)两层强制机制均已验证

  • 第一层 —— 模式门控prepareTools):上面已端到端观察到;叶子层级根本看不到 agent
  • 第二层 —— 运行时兜底AgentTool.executespawnBlockReason):8 个改动的 core 测试套件(629 个测试)全部通过。对共享深度判定做变异canSpawnNestedAgent → true)会导致三层共 8 个测试失败,其中包括运行时守卫的测试 "rejects a spawn that would exceed maxSubagentDepth"expected 'Subagent "file-search" not found' to contain 'nesting depth limit reached')—— 而 teammate/fork 守卫保持绿色(独立分支)。这证明两层来自同一判定、不会漂移,与 PR 的说法一致。
  • flag 校验: --max-subagent-depth 0|3.5|200|abc 全部被明确报错拒绝must be an integer between 1 and 100);settings 路径则静默钳制 —— 这是有意的不对称设计。

3)TUI 嵌套树(#6191 的树形工作已在本分支内)

(见上方"nested tree"图)

  • 上:tmux 中从运行中的真实二进制实时捕获 —— 顶层会话派生一个后台代理,后台代理再派生一个嵌套子代理;真实的 LiveAgentPanel 以树形()渲染它们,状态栏显示 2 local agents
  • 下: 用三层 fixture 渲染真实 BackgroundTasksDialog —— 深度优先缩进、 连接线,且 [blocking] 只正确地出现在前台根节点(嵌套子代理阻塞的是其后台父代理,而非用户回合)。

⚠️ 一条非阻断说明:描述与实际 diff 不一致

描述写着 "本 PR 仅包含后端…… 嵌套的树形展示……将作为叠加在本 PR 之上的后续 PR 提交。" 而那个后续 PR —— #6191 —— 已于 2026-07-03 合入 feat/nested-subagents(提交 699cb26),因此它的树形代码(agent-forest.tsLiveAgentPanelBackgroundTasksDialogToolMessageInputPrompt已经在本分支内,且尚未进入 main。也就是说合并 #6189 会一并带入 TUI 树。这没问题 —— 两层这里都已验证 —— 但"仅后端"的措辞应更新,以便审阅者了解真实的合并范围。

其他

  • 审阅时 head 未变(699cb26);Test (ubuntu-latest) 绿色,mac/win/Integration 是惯常的 named-job skip,blocked 是评审门(非 CI 失败)。
  • 与 PR 自述风险一致:并发仍受限(前台嵌套串行执行;嵌套的后台请求会被降级为等待式前台运行),但深层树的累计 token 消耗没有单独预算 —— 树级预算是合理的后续工作。

Verification harness: real dist/cli.js @ 699cb26 · fake-OpenAI forced greedy nesting · per-request tools[] capture · vitest + predicate mutation · live tmux TUI capture. No source modified (throwaway test/driver reverted).

@tanzhenxin

Copy link
Copy Markdown
Collaborator Author

Thanks for the thorough maintainer verification — the per-level tools[] capture and the predicate mutation check are exactly the right decisive signals for this feature.

Description updated per your note: it no longer claims backend-only scope. Both the English and Chinese versions now state that #6191's tree rendering has merged into this branch, so merging this PR brings the backend enforcement and the TUI tree together, and the out-of-scope list drops the stale follow-up-PR line. Agreed on tree-wide token budgeting as the natural follow-up.

@wenshao

wenshao commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR @tanzhenxin!

Template looks good ✓ — all required sections present, bilingual body, clear test plan.

On direction: this is squarely aligned with the project's multi-agent roadmap (roadmap/multi-agent, roadmap/subagents-tools). Bounded recursive delegation is a natural next step after flat sub-agents — a research agent that fans out readers, or a migration agent that delegates per-module work, are real workflows that the single-level cap blocks today. Claude Code has had similar nested agent capabilities since at least mid-2025. This fills a genuine gap.

On approach: the two-layer enforcement design is the right call. Sharing a single spawnBlockReason() predicate between schema gating (prepareTools) and the runtime guard (AgentTool.execute) means the two layers literally cannot drift — that's a security property worth the coupling. The depthOverride mechanism for resume paths (background resume, deferred approvals, AgentInteractive) is a clean solution to what could have been a subtle depth-identity-loss bug. The v1 scoping is disciplined — teammates, forks, and workflow agents explicitly stay leaf-only, with their own guards now that the unconditional exclusion rule is replaced by depth gating.

The scope is large (40 files, ~2700 additions) but cohesive: backend enforcement and TUI tree rendering are tightly coupled (the tree display needs the lineage metadata the backend now persists), and splitting them would have meant shipping a feature with no visible UX until a follow-up PR landed. The agent-forest.ts module is a clean extraction that handles edge cases (cycles, orphaned parents, windowed display) without leaking into the components.

The default-on cap of 5 is a behavior change worth noting — any sub-agent can now delegate further — but maxSubagentDepth: 1 restores the old contract, and the existing concurrency limits (global background cap, serial foreground) bound the blast radius. A tree-wide token budget is the natural follow-up, and the PR acknowledges this honestly.

Moving on to code review. 🔍

中文说明

感谢 @tanzhenxin 的贡献!

模板完整 ✓ — 所有必填部分齐全,双语描述,测试计划清晰。

方向:与项目的多代理路线图(roadmap/multi-agentroadmap/subagents-tools)完全对齐。有界递归委派是扁平子代理之后的自然演进 —— 研究代理展开多个阅读器、迁移代理按模块委派工作,这些都是单层限制今天无法支持的真实场景。Claude Code 自 2025 年中起已具备类似的嵌套代理能力,这是一个真正的差距填补。

方案:两层强制机制设计正确。在模式门控(prepareTools)和运行时守卫(AgentTool.execute)之间共享单一 spawnBlockReason() 判定函数,意味着两层不可能漂移 —— 这个安全属性值得为此耦合。depthOverride 机制用于恢复路径(后台恢复、延迟审批、AgentInteractive)是解决深度身份丢失这个微妙 bug 的干净方案。v1 的范围控制严谨 —— 队友、fork 和工作流代理明确保持叶子节点,并且由于无条件排除规则被深度门控取代,它们现在各自拥有独立的守卫。

范围较大(40 个文件,约 2700 行新增)但内聚:后端强制与 TUI 树形渲染紧耦合(树形展示需要后端持久化的血缘元数据),拆分意味着在没有后续 PR 的情况下功能没有可见 UI。agent-forest.ts 模块是干净的提取,处理了边界情况(循环、孤儿父代理、窗口化展示)且不泄漏到组件中。

默认开启的层数上限 5 是行为变更 —— 任何子代理现在可以继续委派 —— 但 maxSubagentDepth: 1 可恢复旧契约,且现有并发限制(全局后台上限、前台串行)控制了影响范围。树级 token 预算是自然的后续工作,PR 也坦诚承认了这一点。

进入代码审查 🔍

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal (before reading the diff): I'd add a maxSubagentDepth config setting (default 1, opt-in to nesting), gate the AgentTool in prepareTools() based on depth, add a runtime check in execute() as backstop, persist depth in agent metadata for resume, and build a tree rendering module. The tricky parts are (a) keeping schema and runtime gating in sync, (b) preventing depth identity loss on resume, and (c) keeping teammates/forks/workflow agents excluded without accidentally granting them the tool through the new depth-gated path.

Comparison with the diff: the PR's approach matches and exceeds my proposal in several ways:

  1. Shared predicate is the key design decisionspawnBlockReason() in agent-context.ts is the single source for both prepareTools() (boolean) and execute() (tagged union). This is better than my separate checks idea — a mutation test neutering the predicate fails 8 tests across all three layers, confirming the coupling works.

  2. depthOverride for resume is more elegant than re-deriving — background resume passes the persisted meta.depth through normalizeResumedAgentDepth() (which fails closed to the depth ceiling on tampered values, not open — nice touch) and then into runWithAgentContext(id, fn, depthOverride). This avoids the subtle bug where a resumed nested agent gets treated as top-level.

  3. isTopLevelSession() is the right discriminator — using getCurrentAgentId() === null to distinguish "no frame" from "frame at depth 0" is the correct fix for the two ambiguous states that getCurrentAgentDepth() alone can't separate.

  4. Downgrade paths are correct — fork requests from nested agents fall back to general-purpose sub-agents (not an error), background requests from nested agents run foreground. Both preserve functionality while honoring v1 scoping.

  5. agent-forest.ts is a clean extraction — handles cycles (appends flat), orphans (promotes to root with "from" annotation), and windowed display correctly. The computeUserBlockingIds chain-walking logic is right: only a fully-foreground chain to root gets the [blocking] tag.

No critical blockers found. No clear AGENTS.md violations — no over-abstraction, no unnecessary duplication, code in the right packages. The comments are substantive (explaining why each guard exists, not what it does) and load-bearing for future maintainers.

Unit Tests

Ran all 8 key test suites in the worktree:

Suite Tests Status
agent-context.test.ts 22 ✅ pass
agent-transcript.test.ts 27 ✅ pass
agent.test.ts 132 ✅ pass
agent-core.test.ts 25 ✅ pass
background-agent-resume.test.ts 34 ✅ pass
agent-forest.test.ts 20 ✅ pass
BackgroundTasksDialog.test.tsx 43 ✅ pass
LiveAgentPanel.test.tsx 29 ✅ pass
Total 332 ✅ all pass

Build & Typecheck

  • npm run build — ✅ 0 errors (15 pre-existing lint warnings, not introduced by this PR)
  • npm run typecheck — ✅ clean

Real-Scenario Testing (tmux, bundled binary)

Flag validation against node dist/cli.js — all invalid inputs are loudly rejected at the CLI flag level:

$ node dist/cli.js --max-subagent-depth 0 -p 'test'
Error: --max-subagent-depth must be an integer between 1 and 100; got 0.
EXIT_CODE=1

$ node dist/cli.js --max-subagent-depth 3.5 -p 'test'
Error: --max-subagent-depth must be an integer between 1 and 100; got 3.5.
EXIT_CODE=1

$ node dist/cli.js --max-subagent-depth 200 -p 'test'
Error: --max-subagent-depth must be an integer between 1 and 100; got 200.
EXIT_CODE=1

$ node dist/cli.js --max-subagent-depth abc -p 'test'
Error: --max-subagent-depth must be an integer between 1 and 100; got NaN.
EXIT_CODE=1

$ node dist/cli.js --help 2>&1 | grep -A2 'max-subagent-depth'
      --max-subagent-depth  Maximum sub-agent nesting depth (1-based levels).
      1 keeps sub-agents available but disables nesting; capped at 100.
      Overrides model.maxSubagentDepth from settings. Defaults to 5.  [number]

Full E2E with real model calls requires API keys not available in this CI environment. Maintainer @wenshao's independent verification at 699cb26 (posted above) covered all 5 scenarios with a fake OpenAI server driving greedy nesting, confirming: tool counts flip exactly at each cap boundary (51 vs 50), the leaf level hallucinating agent gets Tool "agent" not found, and the nonce propagates through the chain to stdout. That evidence plus the passing test suites gives high confidence in the implementation.

中文说明

代码审查

独立方案(读 diff 之前): 我会添加 maxSubagentDepth 配置项(默认 1,opt-in 开启嵌套),在 prepareTools() 中按深度门控 AgentTool,在 execute() 中添加运行时检查作为兜底,在代理元数据中持久化深度以供恢复,并构建树形渲染模块。难点在于 (a) 保持模式和运行时门控同步,(b) 防止恢复时深度身份丢失,(c) 保持队友/fork/工作流代理被排除且不会通过新的深度门控路径意外获得该工具。

与 diff 的对比: PR 的方案在多个方面匹配并超越了我的方案:

  1. 共享判定函数是关键设计决策agent-context.ts 中的 spawnBlockReason() 同时服务 prepareTools()(布尔值)和 execute()(标记联合)。这比我分别检查的方案更好 —— 对该判定做变异会导致三层共 8 个测试失败,确认耦合有效。

  2. 恢复时的 depthOverride 比重新推导更优雅 — 后台恢复通过 normalizeResumedAgentDepth()(对被篡改的值失败闭合到深度天花板而非开放 —— 好的处理)将持久化的 meta.depth 传入 runWithAgentContext(id, fn, depthOverride)。避免了恢复的嵌套代理被当作顶层的微妙 bug。

  3. isTopLevelSession() 是正确的判别器 — 用 getCurrentAgentId() === null 区分"无帧"和"深度 0 的帧",正确修复了单靠 getCurrentAgentDepth() 无法分离的两种歧义状态。

  4. 降级路径正确 — 嵌套代理的 fork 请求回退到通用子代理(不是报错),嵌套代理的后台请求在前台运行。两者都在遵守 v1 范围的同时保留了功能。

  5. agent-forest.ts 是干净的提取 — 正确处理了循环(平铺追加)、孤儿(提升到根并标注"来自")、和窗口化展示。computeUserBlockingIds 的链遍历逻辑正确:只有到根的完整前台链才获得 [blocking] 标记。

未发现关键阻断问题。 无明显的 AGENTS.md 违规 —— 无过度抽象、无不必要的重复、代码在正确的包中。注释是实质性的(解释每个守卫为什么存在,而非做了什么),对未来维护者有承载价值。

单元测试

在工作树中运行了全部 8 个关键测试套件:332 个测试全部通过。

构建与类型检查

  • npm run build — ✅ 0 错误
  • npm run typecheck — ✅ 干净

真实场景测试(tmux,打包产物)

针对 node dist/cli.js 的 flag 验证 —— 所有无效输入在 CLI flag 层被明确拒绝(见上方终端输出)。

使用真实模型调用的完整 E2E 需要此 CI 环境中不可用的 API 密钥。维护者 @wenshao699cb26 上的独立验证(已在上方发布)覆盖了全部 5 个场景,使用伪 OpenAI 服务器驱动贪婪嵌套,确认:工具数量在每个上限边界精确翻转(51 vs 50),叶子层级幻觉调用 agent 得到 Tool "agent" not found,且 nonce 通过链路传播到 stdout。该证据加上通过的测试套件,对实现给予了高度信心。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Reflection

Stepping back and looking at the whole picture: this PR solves a real problem — single-level sub-agent delegation forces all coordination back through the top-level context, which is a genuine bottleneck for complex tasks like multi-module migrations or fan-out research.

Does the approach match or exceed my independent proposal? Yes. The shared spawnBlockReason() predicate is the standout design decision — it makes the two enforcement layers (schema gating and runtime guard) provably consistent, and the mutation test evidence confirms this. My proposal would have had separate checks that could drift.

Is the code straightforward? The core enforcement code in agent-context.ts is clean and well-factored — four small pure functions (isTopLevelSession, childLaunchDepth, canSpawnNestedAgent, spawnBlockReason) that compose naturally. The agent tool changes are mostly guard additions with clear early returns. The agent-forest.ts module is a textbook extraction of tree-rendering concerns. The resume depth pinning via depthOverride is elegant.

The comments throughout the diff are substantive — they explain why each guard exists (e.g., "a rule missed on the runtime side is a silent spawn bypass, missed on the schema side it burns model turns on guaranteed-rejected calls"), which is exactly the kind of comment that helps future maintainers. This is the right density.

Is every change necessary? The 40-file surface breaks down into: backend enforcement (~15 files), TUI tree rendering (~15 files), tests (~8 files), docs/settings (~2 files). The backend and UI changes are coupled (the tree display needs the lineage metadata the backend now persists), and splitting them would ship a feature with no visible UX. The test additions are proportional — 332 tests covering the enforcement predicates, resume depth, fork/teammate/workflow guards, and tree rendering.

Do the results match the promise? Build clean, typecheck clean, 332 tests pass, flag validation confirmed in tmux. Maintainer @wenshao's independent E2E at 699cb26 verified all 5 scenarios with API-level tool capture — the decisive signal (tool count flipping exactly at each cap boundary) confirms the implementation matches the specification.

The main risk is real and acknowledged: default-on nesting changes behavior for every existing setup. A sub-agent can now delegate further. But the mitigation is straightforward (maxSubagentDepth: 1 restores the old contract), concurrency stays bounded, and the PR is honest that tree-wide token budgeting is the follow-up.

One minor note: the PR body has been updated to reflect that #6191's tree rendering is now in this branch — the description is now consistent with the diff.

This is a well-designed, well-tested feature PR that ships what it promises. The two-layer enforcement with a shared predicate is the right architecture, the resume identity pinning handles the subtle edge cases, and the v1 scoping is disciplined. LGTM.

中文说明

反思

退一步看全局:这个 PR 解决了一个真实问题 —— 单层子代理委派迫使所有协调回流到顶层上下文,这对多模块迁移或扇出研究等复杂任务是真正的瓶颈。

方案是否匹配或超越独立方案? 是的。共享的 spawnBlockReason() 判定函数是最突出的设计决策 —— 它使两层强制机制(模式门控和运行时守卫)可证明地一致,变异测试证据确认了这一点。我的方案会有可能漂移的独立检查。

代码是否直观? agent-context.ts 中的核心强制代码干净且结构良好 —— 四个小型纯函数(isTopLevelSessionchildLaunchDepthcanSpawnNestedAgentspawnBlockReason)自然组合。代理工具的改动主要是带清晰提前返回的守卫添加。agent-forest.ts 模块是树形渲染关注的教科书级提取。通过 depthOverride 的恢复深度锚定优雅。

通篇注释是实质性的 —— 它们解释每个守卫为什么存在,这正是帮助未来维护者的注释类型。密度正确。

每个改动是否必要? 40 个文件的范围分解为:后端强制(约 15 个文件)、TUI 树形渲染(约 15 个文件)、测试(约 8 个文件)、文档/设置(约 2 个文件)。后端和 UI 变更是耦合的(树形展示需要后端现在持久化的血缘元数据),拆分意味着发布一个没有可见 UI 的功能。测试添加与范围相称 —— 332 个测试覆盖了强制判定、恢复深度、fork/队友/工作流守卫和树形渲染。

结果是否符合承诺? 构建干净、类型检查干净、332 个测试通过、tmux 中确认了 flag 验证。维护者 @wenshao699cb26 上的独立 E2E 用 API 级工具捕获验证了全部 5 个场景 —— 决定性信号(工具数量在每个上限边界精确翻转)确认实现与规格匹配。

主要风险是真实且已被承认的: 默认开启的嵌套对所有现有环境是行为变更。子代理现在可以继续委派。但缓解措施直接(maxSubagentDepth: 1 恢复旧契约),并发仍受限,PR 坦诚树级 token 预算是后续工作。

一个小备注: PR 正文已更新以反映 #6191 的树形渲染现在在本分支中 —— 描述与 diff 一致。

这是一个设计良好、测试充分的功能 PR,交付了它所承诺的。共享判定函数的两层强制是正确的架构,恢复身份锚定处理了微妙的边界情况,v1 的范围控制严谨。LGTM。

Qwen Code · qwen3.7-max

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@tanzhenxin
tanzhenxin added this pull request to the merge queue Jul 3, 2026
Merged via the queue into main with commit 8de93b8 Jul 3, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants