Skip to content

fix(core): rebuild tool registry on subagent Config overrides so bound tools resolve to the subagent#3873

Merged
wenshao merged 3 commits into
mainfrom
feat/subagent-tool-registry-isolation
May 7, 2026
Merged

fix(core): rebuild tool registry on subagent Config overrides so bound tools resolve to the subagent#3873
wenshao merged 3 commits into
mainfrom
feat/subagent-tool-registry-isolation

Conversation

@wenshao

@wenshao wenshao commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #3774. Closes the bound-tool gap that the prior PR explicitly deferred to a later change: subagent Config overrides built via Object.create(parent) did NOT relocate the parent's already-bound core tools (EditTool / WriteFileTool / ReadFileTool), so subagent mutations still walked through tool instances whose this.config was the parent — reaching the parent's FileReadCache and approval mode rather than the subagent's.

The bug, in one paragraph

Config.createToolRegistry() runs once at parent initialize() time. Its lazy factories close over this, so when they later instantiate EditTool etc. they bind this.config = parent. PR-B added a per-Config lazy-init for FileReadCache so an Object.create(parent) wrapper would get its own cache — but only for code that reads through the wrapper Config directly. Bound tools from the parent registry kept reading from the parent. This was called out in PR-B's review #4234090906 as the follow-up to fix here.

What this changes

A shared helper rebuildToolRegistryOnOverride(override, base) in agent.ts rebuilds the tool registry on the override Config — the same pattern InProcessBackend.createPerAgentConfig already uses:

const override = Object.create(base);
override.getApprovalMode = () => mode; // (or content-generator overrides)
const agentRegistry = await override.createToolRegistry(undefined, {
  skipDiscovery: true,
});
agentRegistry.copyDiscoveredToolsFrom(base.getToolRegistry());
override.getToolRegistry = () => agentRegistry;
override[TOOL_REGISTRY_REBUILT] = true;  // Symbol marker

Called from three spawn sites:

  • agent.ts:createApprovalModeOverride (foreground / background / fork from the AgentTool)
  • subagent-manager.ts:maybeOverrideContentGenerator (inherits and non-inherits branches)
  • background-agent-resume.ts resume path (via the now-async exported createApprovalModeOverride; the local pre-rebuild copy was removed)

After this, the subagent's bound tools resolve this.config to the override Config, which in turn resolves getFileReadCache() / getApprovalMode() to the per-subagent state via the lazy own-property machinery.

Scope note: discovered tools (MCP / command-discovered) are reference-copied from the parent registry rather than re-discovered, so MCP tool instances keep this.config = parent. This is deliberate to avoid re-running discovery — bound-tool isolation here is specifically for the core file tools that read FileReadCache and approval mode.

createApprovalModeOverride becomes async; its existing call sites already ran inside async blocks.

Avoiding double-rebuild + listener leak

createAgentHeadless flows are layered: agent.ts wraps the parent (child1), then passes that wrapper into subagent-manager.ts's maybeOverrideContentGenerator which would otherwise wrap again (child2). Background path adds yet another layer (bgConfig = Object.create(agentConfig)). Doing redundant rebuilds at downstream layers would:

  1. waste work re-registering ~10 lazy factories and re-copying discovered tools,
  2. leak listeners — every later AgentTool / SkillTool factory invocation on the second-layer registry registers a change-listener on shared SubagentManager / SkillManager, and
  3. split the cache so client-level cache clears would target an empty child2 cache while bound tools (in child1) keep using child1's.

maybeOverrideContentGenerator skips the rebuild when an upstream wrapper has already done it. Detection uses a Symbol.for('qwen-code:tool-registry-rebuilt') marker installed by rebuildToolRegistryOnOverride — Symbol property reads walk the prototype chain via normal lookup, so a marker stored on any ancestor (even one or two Object.create layers up, like bgConfig over agentConfig) is correctly observed. A plain hasOwnProperty(base, 'getToolRegistry') check would have missed those wrapper-on-wrapper layers and triggered redundant rebuilds.

Lifecycle

The per-subagent registry is stopped in finally blocks of three spawn paths — foreground non-fork, background non-fork, background fork — so every AgentTool / SkillTool the model instantiated disposes its change-listener on shared managers. The foreground-fork path is missed in this PR and gets a small follow-up (#3887).

Tests

Two new files exercise the bound-tool path end-to-end (real Config + real ToolRegistry + real tool factories — no global mocks of tool-registry / tools):

  • packages/core/src/tools/agent/agent-override.test.ts — verifies createApprovalModeOverride returns a Config whose registry is a distinct instance, that EditTool / WriteFileTool / ReadFileTool instantiated from that registry have tool.config === override, that the bound tool's getFileReadCache() resolves to the override's cache (not the parent's), that the override approval mode is preserved through bound tools, and that discovered tools survive the rebuild via copyDiscoveredToolsFrom. Plus a dedicated TOOL_REGISTRY_REBUILT marker propagation describe that pins the Symbol-marker contract through Object.create wrappers.
  • packages/core/src/subagents/subagent-manager-override.test.ts — same shape for SubagentManager.maybeOverrideContentGenerator's inherits AND non-inherits branches, plus dedicated tests for the chained-override case (base already has its own registry → no rebuild → child inherits via prototype, bound tools still resolve to the upstream wrapper).

Existing test fixtures in agent.test.ts, subagent-manager.test.ts, and background-agent-resume.test.ts were updated to provide createToolRegistry / tools: new Map() / stop stubs on their mock configs since the override path now exercises those methods.

Test plan

  • npx vitest run packages/core/src — 268 files, 6943 passed, 3 skipped
  • npm run build — clean
  • npx eslint on changed files — clean

Known follow-ups

  • fix(core): stop per-subagent ToolRegistry on foreground-fork path #3887: foreground-fork path missed the stop() cleanup added here — same shape, separate small PR.
  • forkedAgent.ts:createYoloConfig / extractionAgentPlanner.ts:scopedConfig / dreamAgentPlanner.ts:scopedConfig all have the same Object.create + method override + hand to AgentHeadless pattern but bypass the subagent manager and therefore the rebuild — out of scope here, separate follow-up.
中文版本 (Chinese version)

概要

#3774 的后续 PR。补完上一个 PR 明确推迟到后续的"bound-tool"漏洞:通过 Object.create(parent) 构造的 subagent Config override 没有把父进程已经绑定的核心工具(EditTool / WriteFileTool / ReadFileTool)一起搬过来,所以 subagent 的写操作仍然走那些 this.config = parent 的工具实例 —— 读到的是父进程的 FileReadCache 和 approval mode,而不是 subagent 自己的。

Bug 一句话总结

Config.createToolRegistry() 只在父进程 initialize() 时跑一次。它的 lazy factory 闭包里捕获了 this,所以后续实例化 EditTool 等工具时绑定的是 this.config = parent。PR-B 给 FileReadCache 加了 per-Config 的 lazy-init —— 让 Object.create(parent) wrapper 拿到自己的 cache —— 但这只对直接通过 wrapper Config 读取的代码生效。从父注册表里出来的 bound tool 还是读父进程的 cache。这一点 PR-B 的 review #4234090906 已经标记为 follow-up,本 PR 修复。

这次改了什么(Java 类比)

可以把 Config 想成 Spring 的 ApplicationContext,ToolRegistry 想成 BeanFactory,EditTool 等是 prototype-scoped Bean —— 它们在 BeanFactory 创建时就被注入了 ApplicationContext。PR-B 相当于让 child ApplicationContext 持有自己的 cache 字段,但 BeanFactory 还是父的;本 PR 让 child 也建一个自己的 BeanFactory(createToolRegistry),把 MCP 等"发现型 Bean"从父 BeanFactory 复制过来(copyDiscoveredToolsFrom),从而让所有 Bean 的 this.config 都指向 child。

抽出共享 helper rebuildToolRegistryOnOverride(override, base),在三个 spawn 站点调用:

  • agent.ts:createApprovalModeOverride
  • subagent-manager.ts:maybeOverrideContentGenerator(inherits 和非 inherits 分支)
  • background-agent-resume.ts resume 路径(通过现在异步的导出版 createApprovalModeOverride;本地的 pre-rebuild 副本已删)

范围说明:MCP / command-discovered 这类 discovered tool 是引用复制过来的,不重新发现 —— 所以 MCP tool 实例的 this.config 还是 parent。这是有意的(避免再次握手 discovery 开销);本 PR 的 bound-tool 隔离专门针对读 FileReadCache / approval mode 的核心 file 工具。

createApprovalModeOverride 变成了 async;现有调用点本就在 async 块里。

避免双重重建 + listener 泄漏

createAgentHeadless 是分层的:agent.ts 包一次(child1),再把 wrapper 传给 subagent-manager.ts:maybeOverrideContentGenerator —— 如果不加判断,这一层会再包一次child2)。background 路径还会再叠一层(bgConfig = Object.create(agentConfig))。下游层重复重建会:

  1. 重复注册 ~10 个 lazy factory、重复复制 discovered tool,做无用功;
  2. 泄漏 listener —— 第二层注册表里 AgentTool / SkillTool 的 factory 一旦被 model 调用,就会在共享的 SubagentManager / SkillManager 上挂 change-listener;
  3. 拆分 cache —— 客户端清 cache 走 child2(空 cache),bound tool 还在 child1 那一层读写。

maybeOverrideContentGenerator 检测到上游已重建就跳过。检测用 Symbol.for('qwen-code:tool-registry-rebuilt') 标记,由 rebuildToolRegistryOnOverride 安装 —— Symbol 属性查找走原型链,所以挂在任何祖先上的标记(哪怕 bgConfigagentConfig 之上一两层)也能正确识别。普通 hasOwnProperty(base, 'getToolRegistry') 检测会漏掉这种 wrapper-on-wrapper 场景,触发冗余重建。

Lifecycle

per-subagent registry 在三条 spawn 路径的 finally 里 stop —— 前台非 fork、后台非 fork、后台 fork —— 让 model 实例化的每个 AgentTool / SkillTool 在共享 manager 上 dispose 它的 change-listener。前台 fork 路径在本 PR 漏了,单独 follow-up #3887 处理。

测试

新增两个测试文件,端到端跑 bound-tool path(真 Config + 真 ToolRegistry + 真工厂,不全局 mock):

  • packages/core/src/tools/agent/agent-override.test.ts
  • packages/core/src/subagents/subagent-manager-override.test.ts

加了 TOOL_REGISTRY_REBUILT marker propagation 子 describe,把 Symbol 标记契约穿过 Object.create 包装层钉死。agent.test.ts / subagent-manager.test.ts / background-agent-resume.test.ts 三处现有 mock config 给 tool-registry mock 加了 createToolRegistry / tools: new Map() / stop 桩。

Test plan

  • npx vitest run packages/core/src — 268 文件,6943 通过,3 skip
  • npm run build — 干净
  • 改动文件 npx eslint — 干净

已知 follow-up

  • fix(core): stop per-subagent ToolRegistry on foreground-fork path #3887:foreground-fork 路径漏了本 PR 的 stop(),单独小 PR 处理。
  • forkedAgent.ts:createYoloConfig / extractionAgentPlanner.ts:scopedConfig / dreamAgentPlanner.ts:scopedConfig 都有同形 Object.create + method override + 直接给 AgentHeadless 的模式但绕过 subagent manager 也就绕过了 rebuild —— 越界,单独 follow-up。

…d tools resolve to the subagent

PR-B (#3774) added per-Config FileReadCache isolation via Object.create
overrides at two subagent spawn sites — agent.ts:createApprovalModeOverride
and subagent-manager.ts:maybeOverrideContentGenerator. The override
shielded code that read FileReadCache directly through the Config
instance, but missed the bound-tool path: Config.createToolRegistry runs
once at parent initialise time, so the parent's EditTool / WriteFileTool
/ ReadFileTool instances are bound with `this.config = parent`. The
subagent's Object.create wrapper inherited getToolRegistry via the
prototype chain, reaching the parent registry whose bound tools then
read FileReadCache and approval mode from the parent.

This change closes that gap by rebuilding the tool registry on the
override at both sites — the same pattern InProcessBackend.createPerAgentConfig
already uses:

  - override.createToolRegistry(undefined, { skipDiscovery: true })
  - registry.copyDiscoveredToolsFrom(base.getToolRegistry())
  - override.getToolRegistry = () => registry

createApprovalModeOverride becomes async; its single call site already
ran inside an async block. maybeOverrideContentGenerator skips the
rebuild when the upstream Config already has its own getToolRegistry
(real-world case: agent.ts wrapper passed through createAgentHeadless),
avoiding wasted work, listener accumulation on shared SubagentManager /
SkillManager, and a cache split where the bound tools' registry layer
diverges from the runtime context's lazy-init cache.

Includes regression tests in agent-override.test.ts and
subagent-manager-override.test.ts that exercise the bound-tool path:
they instantiate the lazy factories on the override registry and
assert that EditTool / WriteFileTool / ReadFileTool resolve
this.config to the override Config (and thus to the override's
FileReadCache / approval mode), not the parent.
@github-actions

github-actions Bot commented May 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 55.8% 55.8% 71.67% 79.12%
Core 76.56% 76.56% 79.08% 82.18%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |    55.8 |    79.12 |   71.67 |    55.8 |                   
 src               |   67.99 |    62.34 |   74.19 |   67.99 |                   
  gemini.tsx       |   59.52 |    58.88 |   66.66 |   59.52 | ...62,770-773,781 
  ...ractiveCli.ts |   69.53 |    57.42 |   72.72 |   69.53 | ...21-768,776-783 
  ...liCommands.ts |   73.92 |     72.5 |     100 |   73.92 | ...40-264,289,389 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |    46.3 |    63.01 |   55.88 |    46.3 |                   
  acpAgent.ts      |   48.12 |    63.38 |   62.06 |   48.12 | ...91-793,807-815 
  authMethods.ts   |   12.19 |      100 |       0 |   12.19 | 11-31,34-38,41-50 
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   68.65 |    83.33 |   66.66 |   68.65 |                   
  filesystem.ts    |   68.65 |    83.33 |   66.66 |   68.65 | ...32,77-94,97-98 
 ...ration/session |   74.86 |    68.57 |    82.6 |   74.86 |                   
  ...ryReplayer.ts |   65.93 |    75.67 |   81.81 |   65.93 | ...40-255,268-269 
  Session.ts       |   73.52 |    66.12 |   82.92 |   73.52 | ...2322,2328-2331 
  ...entTracker.ts |   90.85 |    84.84 |      90 |   90.85 | ...35,199,251-260 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   84.21 |    77.77 |     100 |   84.21 | ...37-153,209-211 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ssion/emitters |   96.01 |    90.75 |    92.3 |   96.01 |                   
  BaseEmitter.ts   |   76.92 |    66.66 |      80 |   76.92 | 23-24,39-40,55-56 
  ...ageEmitter.ts |     100 |    89.47 |     100 |     100 | 109,111           
  PlanEmitter.ts   |     100 |      100 |     100 |     100 |                   
  ...allEmitter.ts |   98.06 |     92.3 |     100 |   98.06 | 227-228,327,335   
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
 ...ession/rewrite |   89.69 |    85.89 |   94.11 |   89.69 |                   
  LlmRewriter.ts   |   80.53 |    79.31 |     100 |   80.53 | ...17-119,170-174 
  ...Middleware.ts |   95.83 |    85.71 |     100 |   95.83 | 119,127-129       
  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      |   62.18 |      100 |    9.52 |   62.18 |                   
  auth.ts          |   46.91 |      100 |       0 |   46.91 | ...,91-98,101-102 
  channel.ts       |   56.66 |      100 |       0 |   56.66 | 15-19,27-34       
  extensions.tsx   |   96.55 |      100 |      50 |   96.55 | 37                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   94.73 |      100 |      50 |   94.73 | 28                
  review.ts        |   51.85 |      100 |       0 |   51.85 | 24-35,38          
 src/commands/auth |   66.16 |    79.82 |   78.94 |   66.16 |                   
  handler.ts       |   47.07 |    74.68 |   35.29 |   47.07 | ...-968,1058-1068 
  ...veSelector.ts |     100 |    96.66 |     100 |     100 | 58                
  ...outerOAuth.ts |   89.02 |    78.99 |   96.87 |   89.02 | ...18-622,716-718 
 ...mmands/channel |    39.2 |    79.45 |      50 |    39.2 |                   
  ...l-registry.ts |    8.57 |      100 |       0 |    8.57 | 6-21,24-42        
  config-utils.ts  |   91.89 |      100 |   66.66 |   91.89 | 20-25             
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  pairing.ts       |   26.31 |      100 |       0 |   26.31 | ...30,40-50,52-65 
  pidfile.ts       |   96.34 |    86.95 |     100 |   96.34 | 49,59,91          
  start.ts         |   31.15 |       52 |   69.23 |   31.15 | ...73-476,485-487 
  status.ts        |   17.54 |      100 |       0 |   17.54 | 15-26,32-77       
  stop.ts          |      20 |      100 |       0 |      20 | 14-48             
 ...nds/extensions |   84.53 |    88.95 |   81.81 |   84.53 |                   
  consent.ts       |   71.65 |    89.28 |   42.85 |   71.65 | ...85-141,156-162 
  disable.ts       |     100 |      100 |     100 |     100 |                   
  enable.ts        |     100 |      100 |     100 |     100 |                   
  install.ts       |    75.6 |    66.66 |   66.66 |    75.6 | ...39-142,145-153 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |      100 |     100 |     100 |                   
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  uninstall.ts     |    37.5 |      100 |   33.33 |    37.5 | 23-45,57-64,67-70 
  update.ts        |   96.32 |      100 |     100 |   96.32 | 101-105           
  utils.ts         |   60.24 |    28.57 |     100 |   60.24 | ...81,83-87,89-93 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 src/commands/mcp  |   92.29 |    86.08 |   88.88 |   92.29 |                   
  add.ts           |     100 |    98.03 |     100 |     100 | 293               
  list.ts          |   91.22 |    80.76 |      80 |   91.22 | ...19-121,146-147 
  reconnect.ts     |   76.72 |    71.42 |   85.71 |   76.72 | 35-48,153-175     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   11.57 |      100 |       0 |   11.57 |                   
  cleanup.ts       |   17.94 |      100 |       0 |   17.94 | ...01-106,108-109 
  deterministic.ts |   13.75 |      100 |       0 |   13.75 | ...22-738,740-741 
  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 
 src/config        |   92.04 |    82.54 |   84.72 |   92.04 |                   
  auth.ts          |   87.87 |    81.35 |     100 |   87.87 | ...20-221,237-238 
  config.ts        |   86.36 |    82.53 |   72.72 |   86.36 | ...1339,1361-1362 
  keyBindings.ts   |   95.95 |       50 |     100 |   95.95 | 160-163           
  ...idersScope.ts |      92 |       90 |     100 |      92 | 11-12             
  sandboxConfig.ts |    58.9 |    61.53 |   66.66 |    58.9 | ...54-68,73,77-89 
  settings.ts      |   83.13 |    82.55 |   85.71 |   83.13 | ...35-936,941-944 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...tedFolders.ts |   96.29 |       94 |     100 |   96.29 | ...88-190,205-206 
 ...nfig/migration |   94.56 |    78.94 |   83.33 |   94.56 |                   
  index.ts         |   93.93 |    88.88 |     100 |   93.93 | 85-86             
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   93.63 |     94.5 |     100 |   93.63 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |    90.19 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
 src/constants     |   11.97 |     87.5 |   16.66 |   11.97 |                   
  ...dardApiKey.ts |     100 |      100 |     100 |     100 |                   
  codingPlan.ts    |    8.75 |     87.5 |   16.66 |    8.75 | ...22-327,335-347 
 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    |   63.09 |    64.51 |   55.55 |   63.09 |                   
  ...tputBridge.ts |   62.94 |    65.51 |   56.25 |   62.94 | ...22-323,331-334 
  ...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          |   48.26 |    76.19 |   38.88 |   48.26 |                   
  index.ts         |   26.92 |    76.92 |   26.66 |   26.92 | ...38-239,249-260 
  languages.ts     |    98.7 |       75 |     100 |    98.7 | 110               
 src/i18n/locales  |       0 |        0 |       0 |       0 |                   
  ca.js            |       0 |        0 |       0 |       0 | 1-2146            
  de.js            |       0 |        0 |       0 |       0 | 1-2069            
  en.js            |       0 |        0 |       0 |       0 | 1-2119            
  fr.js            |       0 |        0 |       0 |       0 | 1-2102            
  ja.js            |       0 |        0 |       0 |       0 | 1-1560            
  pt.js            |       0 |        0 |       0 |       0 | 1-2060            
  ru.js            |       0 |        0 |       0 |       0 | 1-2065            
  zh-TW.js         |       0 |        0 |       0 |       0 | 1-1681            
  zh.js            |       0 |        0 |       0 |       0 | 1-1920            
 ...nonInteractive |   72.67 |    72.14 |   74.07 |   72.67 |                   
  session.ts       |   76.86 |    70.45 |   85.71 |   76.86 | ...78-779,787-797 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...80-581,584-585 
 ...active/control |   77.55 |    88.23 |      80 |   77.55 |                   
  ...rolContext.ts |    7.69 |        0 |       0 |    7.69 | 47-79             
  ...Dispatcher.ts |   91.66 |    91.83 |   88.88 |   91.66 | ...54-372,388,391 
  ...rolService.ts |       8 |        0 |       0 |       8 | 46-179            
 ...ol/controllers |    7.04 |       80 |   13.33 |    7.04 |                   
  ...Controller.ts |   19.32 |      100 |      60 |   19.32 | 81-118,127-210    
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |    3.96 |      100 |   11.11 |    3.96 | ...61-379,389-494 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |    5.21 |      100 |       0 |    5.21 | ...21-433,442-471 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   97.59 |    93.06 |   95.18 |   97.59 |                   
  ...putAdapter.ts |   97.33 |    91.89 |   98.07 |   97.33 | ...1343,1368-1369 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.28 |      100 |      90 |   98.28 | 81-82,122-123     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   86.98 |       75 |   85.71 |   86.98 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.12 |    76.08 |   91.66 |   88.12 | ...21-222,233-236 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/services      |   90.37 |    89.75 |   94.28 |   90.37 |                   
  ...mandLoader.ts |     100 |     92.3 |     100 |     100 | 89                
  ...killLoader.ts |     100 |    96.29 |     100 |     100 | 44                
  ...andService.ts |    93.5 |      100 |      80 |    93.5 | 107,150-153       
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   75.32 |    80.64 |   83.33 |   75.32 | ...05-206,272-273 
  ...mandLoader.ts |     100 |      100 |     100 |     100 |                   
  ...nd-factory.ts |      91 |     90.9 |     100 |      91 | 123,132-139       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  commandUtils.ts  |      96 |       90 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   85.95 |    86.42 |   90.47 |   85.95 |                   
  DataProcessor.ts |   85.68 |    86.46 |   92.85 |   85.68 | ...1110,1114-1121 
  ...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 |   92.38 |    84.12 |     100 |   92.38 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |    78.3 |    71.42 |     100 |    78.3 | ...33-148,151,160 
  tipRegistry.ts   |     100 |    95.23 |     100 |     100 | 33                
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/test-utils    |   93.75 |    83.33 |      80 |   93.75 |                   
  ...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            |   63.21 |    68.42 |   51.28 |   63.21 |                   
  App.tsx          |     100 |      100 |     100 |     100 |                   
  AppContainer.tsx |   65.87 |    62.67 |   66.66 |   65.87 | ...2279,2283-2287 
  ...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        |   52.72 |      100 |   23.52 |   52.72 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   91.83 |       90 |     100 |   91.83 | 25-26,54-55       
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   53.26 |    65.51 |      68 |   53.26 |                   
  AuthDialog.tsx   |   67.75 |    64.95 |    65.9 |   67.75 | ...1271,1273,1275 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  useAuth.ts       |    34.3 |    70.37 |     100 |    34.3 | ...14-920,922-937 
 src/ui/commands   |   59.85 |    77.91 |   60.78 |   59.85 |                   
  aboutCommand.ts  |     100 |    85.71 |     100 |     100 | 36                
  agentsCommand.ts |   72.97 |      100 |      20 |   72.97 | ...32,37-38,42-44 
  ...odeCommand.ts |     100 |      100 |     100 |     100 |                   
  arenaCommand.ts  |   33.13 |    67.64 |    37.5 |   33.13 | ...60-565,644-649 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   95.59 |    71.42 |     100 |   95.59 | 72,154-159        
  bugCommand.ts    |   77.35 |    66.66 |      50 |   77.35 | 21-22,60-69       
  clearCommand.ts  |   90.58 |    73.68 |      50 |   90.58 | ...46,74-75,93-94 
  ...essCommand.ts |   63.39 |       48 |      50 |   63.39 | ...48-149,163-166 
  ...extCommand.ts |    6.17 |      100 |      10 |    6.17 | ...21-522,527-528 
  copyCommand.ts   |     100 |      100 |     100 |     100 |                   
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  ...ryCommand.tsx |   66.11 |    76.74 |   55.55 |   66.11 | ...05-306,315-323 
  docsCommand.ts   |   96.07 |     87.5 |      50 |   96.07 | 20-21             
  doctorCommand.ts |     100 |    93.33 |     100 |     100 | 21                
  dreamCommand.ts  |      75 |    66.66 |   66.66 |      75 | 22-27,44-47       
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   56.93 |    91.66 |   33.33 |   56.93 | ...52-353,361-362 
  ...onsCommand.ts |   45.08 |    85.71 |   27.27 |   45.08 | ...37-238,247-248 
  forgetCommand.ts |   26.82 |      100 |      50 |   26.82 | 18-51             
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   19.04 |       25 |      20 |   19.04 | ...86-187,204-205 
  ideCommand.ts    |   57.33 |    57.69 |   35.29 |   57.33 | ...05-306,310-324 
  initCommand.ts   |   84.33 |    72.72 |     100 |   84.33 | 68,82-87,89-94    
  ...ghtCommand.ts |    72.8 |    66.66 |   83.33 |    72.8 | ...31-245,250-273 
  ...ageCommand.ts |   89.39 |    82.35 |   76.92 |   89.39 | ...22-325,348-349 
  ...elsCommand.ts |     100 |      100 |     100 |     100 |                   
  mcpCommand.ts    |   86.66 |      100 |      50 |   86.66 | 14-15             
  memoryCommand.ts |   86.66 |      100 |      50 |   86.66 | 14-15             
  modelCommand.ts  |   42.19 |       65 |      50 |   42.19 | ...35-168,175-193 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |   93.93 |      100 |      50 |   93.93 | 15-16             
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...berCommand.ts |   32.43 |      100 |      50 |   32.43 | 23-57             
  renameCommand.ts |   85.61 |    78.18 |     100 |   85.61 | ...15-322,329-334 
  ...oreCommand.ts |    92.3 |     87.5 |     100 |    92.3 | ...,83-88,129-130 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |      80 |      100 |      50 |      80 | 19-21             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   81.43 |    65.21 |      80 |   81.43 | ...70-173,176-179 
  skillsCommand.ts |   15.04 |      100 |      25 |   15.04 | ...90-106,109-136 
  statsCommand.ts  |   83.91 |    81.25 |      50 |   83.91 | ...31-132,142-145 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.51 |      100 |      50 |    6.51 | 28-323            
  tasksCommand.ts  |   77.45 |    73.43 |     100 |   77.45 | ...55-159,181-186 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |   95.23 |      100 |      50 |   95.23 | 18-19             
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
 src/ui/components |    59.4 |    73.36 |   61.53 |    59.4 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |   18.91 |      100 |       0 |   18.91 | 30-95             
  AppHeader.tsx    |   86.79 |    42.85 |     100 |   86.79 | 32-38,40          
  ...odeDialog.tsx |     9.7 |      100 |       0 |     9.7 | 35-47,50-182      
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   14.63 |      100 |       0 |   14.63 | 18-56             
  ...TextInput.tsx |   67.83 |    72.09 |      50 |   67.83 | ...30-232,250,259 
  Composer.tsx     |   79.31 |    57.14 |     100 |   79.31 | ...-77,95,133,146 
  ...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 
  ...ification.tsx |   28.57 |      100 |       0 |   28.57 | 16-36             
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |    12.4 |      100 |       0 |    12.4 | 61-457            
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  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       |   79.67 |    58.06 |     100 |   79.67 | ...98-102,104-108 
  ...ngSpinner.tsx |   54.28 |       50 |      50 |   54.28 | 31-48,61          
  Header.tsx       |   98.14 |    85.71 |     100 |   98.14 | 97,99             
  Help.tsx         |   98.74 |    68.75 |     100 |   98.74 | 74,129            
  ...emDisplay.tsx |   62.72 |     37.5 |     100 |   62.72 | ...18-327,330,333 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   81.63 |    76.68 |   83.33 |   81.63 | ...1339,1404,1454 
  ...Shortcuts.tsx |   20.87 |      100 |       0 |   20.87 | ...6,49-51,67-125 
  ...Indicator.tsx |     100 |    91.42 |     100 |     100 | 65,74             
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   57.66 |    54.54 |     100 |   57.66 | ...89-200,209-223 
  ...elsDialog.tsx |   16.07 |    89.18 |      50 |   16.07 | ...58-159,162-648 
  MemoryDialog.tsx |   53.35 |    51.21 |   57.14 |   53.35 | ...55,367,380-382 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   76.59 |    54.54 |     100 |   76.59 | ...60-476,533-537 
  ...tsDisplay.tsx |     100 |    96.96 |     100 |     100 | 234               
  ...fications.tsx |   18.18 |      100 |       0 |   18.18 | 15-58             
  ...onsDialog.tsx |    2.13 |      100 |       0 |    2.13 | 62-133,148-1004   
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   88.14 |    83.87 |     100 |   88.14 | ...01-105,133-138 
  PrepareLabel.tsx |   91.66 |    76.19 |     100 |   91.66 | 73-75,77-79,110   
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |   21.42 |      100 |       0 |   21.42 | 13-39             
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |    4.45 |      100 |       0 |    4.45 | 28-92,100-328     
  ...ionPicker.tsx |   94.76 |    87.17 |     100 |   94.76 | 99,132,253-261    
  ...onPreview.tsx |   91.73 |    78.26 |     100 |   91.73 | ...,70-71,126-128 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...ngsDialog.tsx |   66.88 |    73.52 |     100 |   66.88 | ...11-819,825-826 
  ...ionDialog.tsx |    87.8 |      100 |   33.33 |    87.8 | 36-39,44-51       
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...ionPicker.tsx |   17.59 |      100 |       0 |   17.59 | 55-172            
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...yTodoList.tsx |   94.17 |       80 |     100 |   94.17 | 56-57,131-134     
  ...nsDisplay.tsx |   84.09 |    57.14 |     100 |   84.09 | ...16-118,125-127 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   21.87 |      100 |       0 |   21.87 | 22-40,43-53       
  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 |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
 ...nts/agent-view |    25.2 |       90 |      10 |    25.2 |                   
  ...atContent.tsx |    8.79 |      100 |       0 |    8.79 | 53-265,271-273    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |    9.95 |      100 |       0 |    9.95 | 57-308            
  AgentFooter.tsx  |   17.07 |      100 |       0 |   17.07 | 28-66             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    8.13 |      100 |       0 |    8.13 | 39-59,64-187      
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |   45.72 |    70.53 |   60.86 |   45.72 |                   
  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 |   10.15 |      100 |       0 |   10.15 | 27-161            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...ackground-view |    71.2 |    79.71 |   78.94 |    71.2 |                   
  ...sksDialog.tsx |   71.23 |    78.83 |   73.33 |   71.23 | ...1063,1137-1139 
  ...TasksPill.tsx |   70.83 |    86.95 |     100 |   70.83 | 44,77-89,97-105   
 ...nts/extensions |   45.28 |    33.33 |      60 |   45.28 |                   
  ...gerDialog.tsx |   44.31 |    34.14 |      75 |   44.31 | ...71-480,483-488 
  index.ts         |       0 |        0 |       0 |       0 | 1-9               
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   54.77 |    94.23 |   66.66 |   54.77 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |    6.18 |      100 |       0 |    6.18 | 17-128            
  ...nListStep.tsx |   88.35 |    94.73 |      80 |   88.35 | 51-52,58-71,105   
  ...electStep.tsx |   13.46 |      100 |       0 |   13.46 | 20-70             
  ...nfirmStep.tsx |   19.56 |      100 |       0 |   19.56 | 23-65             
  index.ts         |     100 |      100 |     100 |     100 |                   
 ...mponents/hooks |   72.24 |    70.52 |      80 |   72.24 |                   
  ...etailStep.tsx |   96.52 |       75 |     100 |   96.52 | 33,37,50,59       
  ...etailStep.tsx |   93.27 |    73.68 |     100 |   93.27 | 41-42,99-104,110  
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   36.09 |    47.05 |      50 |   36.09 | ...49,453-466,470 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |    20.2 |    84.61 |   81.81 |    20.2 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |    3.64 |      100 |       0 |    3.64 | 41-717            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-30              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   96.42 |    87.09 |     100 |   96.42 | 21,96-97          
 ...ents/mcp/steps |    6.65 |      100 |       0 |    6.65 |                   
  ...icateStep.tsx |     5.1 |      100 |       0 |     5.1 | 34-95,98-334      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |    5.26 |      100 |       0 |    5.26 | 31-247            
  ...rListStep.tsx |    5.88 |      100 |       0 |    5.88 | 20-176            
  ...etailStep.tsx |   10.41 |      100 |       0 |   10.41 | ...1,67-79,82-139 
  ToolListStep.tsx |    7.14 |      100 |       0 |    7.14 | 16-146            
 ...nents/messages |   79.88 |    78.93 |   69.84 |   79.88 |                   
  ...ionDialog.tsx |   77.35 |    74.54 |    62.5 |   77.35 | ...90,508,526-528 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |   97.67 |    83.33 |     100 |   97.67 | 119,142,150       
  ...onMessage.tsx |   91.93 |    82.35 |     100 |   91.93 | 57-59,61,63       
  ...nMessages.tsx |   77.35 |      100 |      70 |   77.35 | ...31-244,248-260 
  DiffRenderer.tsx |   93.19 |    86.17 |     100 |   93.19 | ...09,237-238,304 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   16.66 |      100 |       0 |   16.66 | 22-38             
  ...sMessages.tsx |   55.67 |       40 |   28.57 |   55.67 | ...20-125,133-145 
  ...ryMessage.tsx |   12.82 |      100 |       0 |   12.82 | 22-59             
  ...onMessage.tsx |   73.55 |    55.81 |   33.33 |   73.55 | ...41-443,450-452 
  ...upMessage.tsx |   76.95 |    82.08 |     100 |   76.95 | ...24-251,273-288 
  ToolMessage.tsx  |   90.68 |    81.35 |   91.66 |   90.68 | ...58-663,690-692 
 ...ponents/shared |    82.5 |    77.29 |   92.64 |    82.5 |                   
  ...ctionList.tsx |   99.03 |    95.65 |     100 |   99.03 | 85                
  ...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  |    6.29 |      100 |       0 |    6.29 | 35-42,45-176      
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  TextInput.tsx    |   74.84 |    57.14 |      75 |   74.84 | ...90-194,206-212 
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  text-buffer.ts   |   83.62 |    75.62 |   97.61 |   83.62 | ...2272,2300,2368 
  ...er-actions.ts |   86.71 |    67.79 |     100 |   86.71 | ...07-608,809-811 
 ...ents/subagents |   32.77 |    33.33 |    12.5 |   32.77 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   13.69 |    33.33 |   16.66 |   13.69 | ...1,56-57,60-102 
 ...bagents/create |    9.13 |      100 |       0 |    9.13 |                   
  ...ionWizard.tsx |    7.28 |      100 |       0 |    7.28 | 34-299            
  ...rSelector.tsx |   14.75 |      100 |       0 |   14.75 | 26-85             
  ...onSummary.tsx |    4.26 |      100 |       0 |    4.26 | 27-331            
  ...tionInput.tsx |    8.63 |      100 |       0 |    8.63 | 23-177            
  ...dSelector.tsx |   33.33 |      100 |       0 |   33.33 | 20-21,26-27,36-63 
  ...nSelector.tsx |    37.5 |      100 |       0 |    37.5 | 20-21,26-27,36-58 
  ...EntryStep.tsx |   12.76 |      100 |       0 |   12.76 | 34-78             
  ToolSelector.tsx |    4.16 |      100 |       0 |    4.16 | 31-253            
 ...bagents/manage |    8.39 |      100 |       0 |    8.39 |                   
  ...ctionStep.tsx |   10.25 |      100 |       0 |   10.25 | 21-103            
  ...eleteStep.tsx |   20.93 |      100 |       0 |   20.93 | 23-62             
  ...tEditStep.tsx |   25.53 |      100 |       0 |   25.53 | ...2,37-38,51-124 
  ...ctionStep.tsx |    2.29 |      100 |       0 |    2.29 | 28-449            
  ...iewerStep.tsx |   13.72 |      100 |       0 |   13.72 | 18-73             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...agents/runtime |   81.76 |    58.24 |   92.85 |   81.76 |                   
  ...onDisplay.tsx |   81.76 |    58.24 |   92.85 |   81.76 | ...14-716,719-722 
 ...mponents/views |   42.16 |    69.23 |   21.42 |   42.16 |                   
  ContextUsage.tsx |     4.7 |      100 |       0 |     4.7 | ...52-167,170-456 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   87.69 |    73.68 |     100 |   87.69 | 65-72             
  McpStatus.tsx    |   89.53 |    60.52 |     100 |   89.53 | ...72,175-177,262 
  SkillsList.tsx   |   27.27 |      100 |       0 |   27.27 | 18-35             
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   76.84 |    78.03 |   84.31 |   76.84 |                   
  ...ewContext.tsx |   65.77 |      100 |      75 |   65.77 | ...22-225,231-241 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.37 |    68.57 |      50 |   93.37 | ...94-195,222-226 
  ...deContext.tsx |     100 |      100 |     100 |     100 |                   
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   81.88 |    82.26 |     100 |   81.88 | ...1153,1159-1161 
  ...owContext.tsx |   89.28 |       80 |   66.66 |   89.28 | 34,47-48,60-62    
  ...onContext.tsx |   43.28 |     62.5 |    62.5 |   43.28 | ...56-259,263-266 
  ...gsContext.tsx |   83.33 |       50 |     100 |   83.33 | 17-18             
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 145-146           
  ...teContext.tsx |   85.71 |       50 |     100 |   85.71 | 175-176           
  ...deContext.tsx |   76.08 |    72.72 |     100 |   76.08 | 47-48,52-59,77-78 
 src/ui/editors    |   93.33 |    85.71 |   66.66 |   93.33 |                   
  ...ngsManager.ts |   93.33 |    85.71 |   66.66 |   93.33 | 49,63-64          
 src/ui/hooks      |    80.8 |    81.38 |   85.56 |    80.8 |                   
  ...dProcessor.ts |   83.12 |    82.56 |     100 |   83.12 | ...88-389,408-435 
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...dProcessor.ts |    94.8 |    70.58 |     100 |    94.8 | ...76-277,282-283 
  ...dProcessor.ts |   72.85 |    57.85 |   61.53 |   72.85 | ...84,808,827-831 
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-158            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...ationFrame.ts |      32 |       60 |     100 |      32 | 42-44,51-90       
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   19.81 |    66.66 |      25 |   19.81 | 57-175            
  ...Completion.ts |   92.77 |    89.09 |     100 |   92.77 | ...86-187,220-223 
  ...ifications.ts |   92.07 |    96.29 |     100 |   92.07 | 116-124           
  ...tIndicator.ts |     100 |    93.75 |     100 |     100 | 63                
  ...waySummary.ts |   96.22 |    69.69 |     100 |   96.22 | 125-127,169       
  ...ndTaskView.ts |   94.11 |    76.92 |     100 |   94.11 | 119-123,216,222   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...lanUpdates.ts |     100 |       92 |     100 |     100 | 59,158            
  ...ompletion.tsx |   91.28 |    79.59 |     100 |   91.28 | ...20-221,259-269 
  ...dMigration.ts |   90.62 |       75 |     100 |   90.62 | 38-40             
  useCompletion.ts |    92.4 |     87.5 |     100 |    92.4 | 68-69,93-94,98-99 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   76.92 |       50 |     100 |   76.92 | 55,68,71-75,88-96 
  ...eteCommand.ts |   33.33 |       50 |     100 |   33.33 | 30,34,41-90       
  ...ialogClose.ts |   18.18 |      100 |     100 |   18.18 | 75-130            
  ...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.45 |     92.3 |     100 |   93.45 | ...83-287,300-306 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |   54.88 |       50 |   33.33 |   54.88 | ...71-173,195-196 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   67.46 |       90 |      50 |   67.46 | ...09-130,149-150 
  ...miniStream.ts |   75.84 |    72.89 |   91.66 |   75.84 | ...2293,2306-2314 
  ...BranchName.ts |    90.9 |     92.3 |     100 |    90.9 | 19-20,55-58       
  ...oryManager.ts |   93.15 |    93.75 |     100 |   93.15 | 44,107-110        
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |      100 |     100 |     100 |                   
  useLogger.ts     |   21.05 |      100 |       0 |   21.05 | 15-37             
  useMCPHealth.ts  |   70.58 |       75 |      50 |   70.58 | 42-47,59-62       
  ...elsCommand.ts |     100 |      100 |     100 |     100 |                   
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...delCommand.ts |     100 |       75 |     100 |     100 | 22                
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   84.52 |    93.33 |     100 |   84.52 | ...27-232,328-338 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   97.24 |    76.92 |     100 |   97.24 | 104-105,145       
  ...ompletion.tsx |   90.59 |    83.33 |     100 |   90.59 | ...01,104,137-140 
  ...ectionList.ts |   96.96 |    95.69 |     100 |   96.96 | ...82-183,237-240 
  ...sionPicker.ts |   90.23 |    71.69 |     100 |   90.23 | ...78-279,283-284 
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   91.74 |    79.41 |     100 |   91.74 | ...74,122-123,133 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-73              
  ...Completion.ts |   78.99 |    81.48 |   94.11 |   78.99 | ...77-579,587-624 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |     100 |    98.79 |     100 |     100 | 257               
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...tification.ts |     100 |    85.71 |     100 |     100 | 47                
  ...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      |   88.09 |    85.71 |     100 |   88.09 | 44-45,51-53       
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |      100 |     100 |     100 |                   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  vim.ts           |   83.77 |    80.31 |     100 |   83.77 | ...55,759-767,776 
 src/ui/layouts    |   89.51 |    86.95 |     100 |   89.51 |                   
  ...AppLayout.tsx |   89.53 |    86.66 |     100 |   89.53 | 50-52,92-97       
  ...AppLayout.tsx |   89.47 |     87.5 |     100 |   89.47 | 58-63             
 ...i/manageModels |   93.61 |       48 |     100 |   93.61 |                   
  manageModels.ts  |   93.61 |       48 |     100 |   93.61 | ...63-166,179,209 
 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 |    7.14 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    7.14 |     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.53 |    70.31 |     100 |   98.53 |                   
  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   |     100 |      100 |     100 |     100 |                   
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.45 |     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 |   87.98 |    82.89 |     100 |   87.98 | ...48-357,362-363 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   77.04 |    86.24 |   85.71 |   77.04 |                   
  ...Colorizer.tsx |   82.78 |    88.23 |     100 |   82.78 | ...10-111,197-223 
  ...nRenderer.tsx |   52.41 |    36.36 |      50 |   52.41 | ...49-151,171-180 
  ...wnDisplay.tsx |   86.79 |    88.88 |     100 |   86.79 | ...06-315,348-373 
  ...eRenderer.tsx |   94.45 |    81.25 |   94.11 |   94.45 | ...65,477,480-483 
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   59.61 |    58.82 |     100 |   59.61 | ...,86-88,107-149 
  commandUtils.ts  |    84.7 |    88.13 |      90 |    84.7 | ...63-164,260-279 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  displayUtils.ts  |   88.37 |    72.22 |     100 |   88.37 | 23,25,29,31,33    
  formatters.ts    |   95.23 |    98.27 |     100 |   95.23 | 117-120           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |   98.63 |       95 |     100 |   98.63 | 93                
  ...oryMapping.ts |     100 |    94.28 |     100 |     100 | 34,56             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |    8.23 |      100 |       0 |    8.23 | ...31-132,135-136 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  ...nUtilities.ts |   69.84 |    85.71 |     100 |   69.84 | 75-91,100-101     
  ...ToolGroups.ts |    98.3 |    95.65 |     100 |    98.3 | 48-49             
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   57.81 |    67.14 |      90 |   57.81 | ...64,412,417-439 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   96.47 |    93.18 |   91.66 |   96.47 | ...46-247,382-383 
  todoSnapshot.ts  |   89.11 |    93.18 |     100 |   89.11 | ...,66-78,180-181 
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 30-42             
 ...i/utils/export |   56.77 |     40.8 |   79.41 |   56.77 |                   
  collect.ts       |   55.92 |    50.58 |   86.36 |   55.92 | ...25-640,642-647 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   57.47 |    20.51 |      80 |   57.47 | ...09-310,324-359 
  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/utils         |   73.76 |    89.53 |   94.55 |   73.76 |                   
  acpModelUtils.ts |     100 |      100 |     100 |     100 |                   
  apiPreconnect.ts |   96.52 |    97.05 |     100 |   96.52 | 166-169           
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |   84.12 |    93.33 |      80 |   84.12 | 75,106-115        
  commands.ts      |     100 |      100 |     100 |     100 |                   
  commentJson.ts   |   85.29 |    89.47 |     100 |   85.29 | 48-57             
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   68.59 |    64.28 |     100 |   68.59 | ...63-269,293-309 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   94.28 |    88.46 |     100 |   94.28 | 28-29,125-126     
  errors.ts        |   98.63 |    96.15 |     100 |   98.63 | 67-68             
  events.ts        |     100 |      100 |     100 |     100 |                   
  gitUtils.ts      |   91.91 |    84.61 |     100 |   91.91 | 78-81,124-127     
  ...AutoUpdate.ts |   90.76 |    93.33 |   88.88 |   90.76 | 103-114           
  ...lationInfo.ts |     100 |      100 |     100 |     100 |                   
  languageUtils.ts |   97.89 |    96.42 |     100 |   97.89 | 132-133           
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...onfigUtils.ts |     100 |      100 |     100 |     100 |                   
  ...iveHelpers.ts |   96.79 |    93.28 |     100 |   96.79 | ...76-477,575,588 
  osc.ts           |    97.5 |      100 |   88.88 |    97.5 | 195-196           
  package.ts       |   88.88 |       80 |     100 |   88.88 | 33-34             
  processUtils.ts  |     100 |      100 |     100 |     100 |                   
  readStdin.ts     |   79.62 |       90 |      80 |   79.62 | 33-40,52-54       
  relaunch.ts      |   98.07 |    76.92 |     100 |   98.07 | 70                
  resolvePath.ts   |   66.66 |       25 |     100 |   66.66 | 12-13,16,18-19    
  sandbox.ts       |       0 |        0 |       0 |       0 | 1-980             
  settingsUtils.ts |   86.32 |    90.59 |   94.44 |   86.32 | ...38,569,632-644 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...upProfiler.ts |     100 |    95.83 |     100 |     100 | 110               
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       60 |     100 |     100 | 23,32             
  systemInfo.ts    |   92.52 |     90.9 |   83.33 |   92.52 | 63-69,184         
  ...InfoFields.ts |   86.91 |    65.78 |     100 |   86.91 | ...16-117,138-139 
  ...iffPreview.ts |   94.11 |    83.33 |     100 |   94.11 | 13                
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   91.17 |    82.35 |     100 |   91.17 | 67-68,73-74,77-78 
  version.ts       |     100 |       50 |     100 |     100 | 11                
  windowTitle.ts   |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |    62.1 |    77.77 |     100 |    62.1 | 93,107,118-157    
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   76.56 |    82.18 |   79.08 |   76.56 |                   
 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        |   84.07 |    76.02 |   90.66 |   84.07 |                   
  ...transcript.ts |   88.76 |    75.43 |     100 |   88.76 | ...82,306-307,434 
  ...ent-resume.ts |   78.67 |    69.51 |   76.66 |   78.67 | ...88-992,995-997 
  ...ound-tasks.ts |   94.19 |    86.17 |     100 |   94.19 | ...15-616,633-634 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/arena  |    76.9 |    66.66 |   78.94 |    76.9 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.84 |     62.9 |   78.57 |   75.84 | ...1889,1895-1896 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    73.46 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |    76.3 |    86.23 |   72.41 |    76.3 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   91.06 |     90.9 |   82.35 |   91.06 | ...51-271,330,430 
  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 |   79.81 |    75.21 |      66 |   79.81 |                   
  agent-core.ts    |   73.97 |    69.03 |   48.48 |   73.97 | ...1299,1326-1372 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   79.09 |    69.76 |   52.38 |   79.09 | ...78-379,382-383 
  ...nteractive.ts |   79.71 |    79.62 |      75 |   79.71 | ...54,456,458,461 
  ...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 |                   
 src/config        |    74.7 |    76.92 |    61.2 |    74.7 |                   
  config.ts        |   72.35 |     74.3 |   55.61 |   72.35 | ...2888,2892-2904 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   95.72 |     93.1 |   91.66 |   95.72 | ...06-207,241-242 
 ...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/constants     |    4.95 |      100 |       0 |    4.95 |                   
  codingPlan.ts    |    4.95 |      100 |       0 |    4.95 | ...79-291,299-309 
 src/core          |   82.72 |    82.31 |   87.91 |   82.72 |                   
  baseLlmClient.ts |   96.77 |    96.42 |      80 |   96.77 | 123-126           
  client.ts        |   77.17 |    77.88 |    86.2 |   77.17 | ...1264,1268-1284 
  ...tGenerator.ts |    72.1 |    61.11 |     100 |    72.1 | ...63,365,372-375 
  ...lScheduler.ts |   77.12 |    81.01 |   92.68 |   77.12 | ...2200,2252-2256 
  geminiChat.ts    |   88.73 |    84.23 |   83.33 |   88.73 | ...1113,1180-1181 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | 34-42,45-49,52-87 
  logger.ts        |   82.25 |    81.81 |     100 |   82.25 | ...57-361,407-421 
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   92.59 |       75 |      50 |   92.59 | 41-42             
  ...on-helpers.ts |   85.71 |    70.58 |     100 |   85.71 | ...90-191,205-214 
  ...issionFlow.ts |   98.59 |    94.73 |     100 |   98.59 | 93                
  prompts.ts       |    88.8 |    88.05 |      75 |    88.8 | ...-898,1101-1102 
  tokenLimits.ts   |     100 |    89.47 |     100 |     100 | 51-52             
  ...okTriggers.ts |   99.31 |    91.02 |     100 |   99.31 | 124,135           
  turn.ts          |   96.42 |    88.88 |     100 |   96.42 | ...00,413-414,462 
 ...ntentGenerator |    94.6 |    79.35 |   92.68 |    94.6 |                   
  ...tGenerator.ts |   96.49 |    79.35 |      90 |   96.49 | ...24,481,637,693 
  converter.ts     |   94.38 |    79.78 |     100 |   94.38 | ...40-541,551,734 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
 ...ntentGenerator |   91.53 |    71.64 |   93.33 |   91.53 |                   
  ...tGenerator.ts |      90 |    70.96 |   92.85 |      90 | ...80-286,304-305 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   91.08 |    76.14 |   85.71 |   91.08 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   91.04 |    76.14 |   85.71 |   91.04 | ...23,533-534,562 
 ...ntentGenerator |   79.48 |    83.73 |   89.47 |   79.48 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   74.92 |    80.85 |   86.95 |   74.92 | ...1410,1431-1437 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   43.85 |    14.28 |      50 |   43.85 | ...,87-91,102-103 
  ...tGenerator.ts |   48.78 |    91.66 |   77.77 |   48.78 | ...10-163,166-167 
  pipeline.ts      |   93.62 |    84.76 |     100 |   93.62 | ...78-479,487,547 
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   90.66 |     88.4 |     100 |   90.66 | ...15-319,349-350 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.67 |    89.74 |   94.87 |   96.67 |                   
  dashscope.ts     |   97.22 |    87.69 |   93.33 |   97.22 | ...10-211,287-288 
  deepseek.ts      |   95.55 |    90.56 |     100 |   95.55 | ...31-132,145-146 
  default.ts       |   94.62 |    86.36 |   85.71 |   94.62 | 85-86,156-158     
  index.ts         |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
 src/extension     |   60.62 |    79.43 |   79.03 |   60.62 |                   
  ...-converter.ts |   62.35 |    47.82 |      90 |   62.35 | ...90-791,800-832 
  ...ionManager.ts |   46.92 |    82.19 |   67.44 |   46.92 | ...1386,1396-1415 
  ...onSettings.ts |   93.46 |    93.05 |     100 |   93.46 | ...17-221,228-232 
  ...-converter.ts |   54.88 |    94.44 |      60 |   54.88 | ...35-146,158-192 
  github.ts        |   44.94 |    88.52 |      60 |   44.94 | ...53-359,398-451 
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   97.29 |    93.75 |     100 |   97.29 | ...64,184-185,274 
  npm.ts           |   48.66 |    76.08 |      75 |   48.66 | ...18-420,427-431 
  override.ts      |   94.11 |    88.88 |     100 |   94.11 | 63-64,81-82       
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-108,143-149    
  storage.ts       |   94.73 |       90 |     100 |   94.73 | 41-42             
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.75 |    83.33 |     100 |   88.75 | ...28-231,234-237 
 src/followup      |   46.35 |     92.3 |   71.87 |   46.35 |                   
  followupState.ts |      96 |    89.74 |     100 |      96 | 159-161,218-219   
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   95.06 |       84 |     100 |   95.06 | 78,108,122,133    
  speculation.ts   |   13.22 |      100 |   16.66 |   13.22 | 88-458,518-568    
  ...onToolGate.ts |     100 |    96.29 |     100 |     100 | 93                
  ...nGenerator.ts |   36.67 |    95.12 |   33.33 |   36.67 | ...24-326,361-391 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/hooks         |    80.6 |    84.37 |   84.16 |    80.6 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.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.37 |    90.54 |     100 |   96.37 | ...89,291-292,365 
  ...entHandler.ts |   95.58 |    84.37 |   92.59 |   95.58 | ...29,682-683,693 
  hookPlanner.ts   |   84.13 |    76.59 |      90 |   84.13 | ...38,144,162-173 
  hookRegistry.ts  |   88.83 |    86.36 |     100 |   88.83 | ...21,326,330,334 
  hookRunner.ts    |   53.63 |    72.22 |   61.11 |   53.63 | ...23-724,733-734 
  hookSystem.ts    |   75.47 |      100 |   56.41 |   75.47 | ...75-576,582-583 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |    96.5 |     91.8 |     100 |    96.5 | ...90,209-210,223 
  ssrfGuard.ts     |   77.22 |    85.36 |     100 |   77.22 | ...57,261-267,273 
  trustedHooks.ts  |       0 |        0 |       0 |       0 | 1-124             
  types.ts         |   90.15 |    91.02 |   85.18 |   90.15 | ...91-392,452-456 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   74.28 |    83.39 |   78.33 |   74.28 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |    64.2 |    81.48 |   66.66 |    64.2 | ...9-970,999-1007 
  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           |   33.92 |    45.16 |   45.76 |   33.92 |                   
  ...nfigLoader.ts |   70.27 |    35.89 |   94.73 |   70.27 | ...20-422,426-432 
  ...ionFactory.ts |    4.29 |      100 |       0 |    4.29 | ...20-371,377-394 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   13.52 |    81.25 |   29.16 |   13.52 | ...75-694,700-730 
  ...eLspClient.ts |   17.89 |      100 |       0 |   17.89 | ...37-244,254-258 
  ...LspService.ts |   45.87 |    62.13 |   66.66 |   45.87 | ...1282,1299-1309 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |   78.69 |    75.34 |   75.92 |   78.69 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   73.82 |    53.92 |     100 |   73.82 | ...88-895,902-904 
  ...en-storage.ts |   98.62 |    97.72 |     100 |   98.62 | 87-88             
  oauth-utils.ts   |   70.58 |    85.29 |    90.9 |   70.58 | ...70-290,315-344 
  ...n-provider.ts |   89.83 |    95.83 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   79.48 |    86.66 |   86.36 |   79.48 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   82.75 |    82.35 |   92.85 |   82.75 | ...62-172,180-181 
  ...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        |   61.59 |    74.87 |   66.44 |   61.59 |                   
  const.ts         |     100 |      100 |     100 |     100 |                   
  dream.ts         |   65.65 |    73.33 |      50 |   65.65 | 50,107-148        
  ...entPlanner.ts |   57.84 |    72.72 |   33.33 |   57.84 | ...35,140-147,152 
  entries.ts       |   59.84 |       70 |      50 |   59.84 | ...72-180,183-189 
  extract.ts       |    95.2 |    79.16 |     100 |    95.2 | 81-86,125         
  ...entPlanner.ts |   63.08 |    65.71 |   41.17 |   63.08 | ...17,222-223,332 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |    8.04 |      100 |       0 |    8.04 | 67-342            
  governance.ts    |       0 |        0 |       0 |       0 | 1-352             
  indexer.ts       |   83.87 |    45.45 |     100 |   83.87 | ...50,56-57,69-70 
  manager.ts       |   73.32 |    78.94 |   74.35 |   73.32 | ...1163,1176-1178 
  memoryAge.ts     |   90.47 |    77.77 |     100 |   90.47 | 50-51             
  paths.ts         |   55.47 |    89.47 |   85.71 |   55.47 | ...,88-89,105-113 
  prompt.ts        |   93.36 |    71.42 |     100 |   93.36 | ...58,161,228-229 
  recall.ts        |   79.56 |    69.38 |   88.88 |   79.56 | ...40-245,269-280 
  ...ceSelector.ts |   91.86 |    77.27 |     100 |   91.86 | ...04,106-107,115 
  scan.ts          |   87.91 |    68.42 |     100 |   87.91 | ...47-48,58,82-87 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   94.44 |    83.33 |     100 |   94.44 | 56-57,92-93       
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   89.49 |    85.58 |   87.14 |   89.49 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   88.67 |     90.9 |     100 |   88.67 | 112,118,121-130   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.63 |    92.53 |     100 |   98.63 | 161,323,329       
  modelRegistry.ts |     100 |    98.21 |     100 |     100 | 182               
  modelsConfig.ts  |   85.37 |    83.54 |   81.57 |   85.37 | ...1210,1239-1240 
  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   |   71.18 |    88.73 |   48.57 |   71.18 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   81.42 |    86.66 |      80 |   81.42 | ...19-820,827-836 
  rule-parser.ts   |   95.99 |    93.18 |     100 |   95.99 | ...-864,1013-1015 
  ...-semantics.ts |   58.28 |    85.27 |    30.2 |   58.28 | ...1604-1614,1643 
  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/qwen          |   86.03 |    79.48 |   97.18 |   86.03 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   85.01 |    74.81 |   93.33 |   85.01 | ...,986-1002,1032 
  ...kenManager.ts |   83.79 |    76.22 |     100 |   83.79 | ...63-768,789-794 
 src/services      |   85.07 |    84.27 |   88.61 |   85.07 |                   
  ...llRegistry.ts |   97.82 |    94.73 |     100 |   97.82 | 172-173           
  ...ionService.ts |   95.42 |       94 |     100 |   95.42 | ...79,336,338-342 
  ...ingService.ts |   79.37 |     82.5 |   78.12 |   79.37 | ...1066,1083-1084 
  cronScheduler.ts |   97.56 |    92.98 |     100 |   97.56 | 62-63,77,155      
  ...eryService.ts |   80.43 |    95.45 |      75 |   80.43 | ...19-134,140-141 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   89.76 |     85.1 |   88.88 |   89.76 | ...89,191,266-273 
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  gitService.ts    |   68.75 |     92.3 |   55.55 |   68.75 | ...12-122,125-129 
  ...reeService.ts |   71.83 |    68.47 |    91.3 |   71.83 | ...89-790,806,822 
  ...ionService.ts |   98.13 |     97.8 |   95.45 |   98.13 | ...32-333,380-381 
  ...orRegistry.ts |   96.76 |    92.15 |     100 |   96.76 | ...95-396,449-450 
  sessionRecap.ts  |   10.71 |      100 |       0 |   10.71 | 48-161            
  ...ionService.ts |   85.48 |    71.62 |      96 |   85.48 | ...73-983,987-988 
  sessionTitle.ts  |   93.95 |    70.37 |     100 |   93.95 | ...36-239,270-271 
  ...ionService.ts |   83.96 |    80.97 |   83.78 |   83.96 | ...1029,1035-1040 
  ...UseSummary.ts |    94.7 |    88.67 |     100 |    94.7 | ...69-171,221-222 
 ...icrocompaction |   98.62 |    86.44 |     100 |   98.62 |                   
  microcompact.ts  |   98.62 |    86.44 |     100 |   98.62 | 138,142           
 src/skills        |    86.7 |    83.88 |   93.61 |    86.7 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |     93.1 |     100 |     100 | 93,112            
  skill-load.ts    |   89.72 |    80.76 |     100 |   89.72 | ...28,248,260-262 
  skill-manager.ts |   82.68 |    79.32 |   90.32 |   82.68 | ...1135,1142-1146 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/subagents     |   82.78 |    80.18 |   91.11 |   82.78 |                   
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   76.75 |    72.09 |   87.09 |   76.75 | ...1176,1198-1199 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 51-56,69-74,78-83 
 src/telemetry     |   70.05 |       83 |   75.11 |   70.05 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...-exporters.ts |   46.37 |      100 |   44.44 |   46.37 | ...85,88-89,92-93 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   91.28 |    83.67 |   92.85 |   91.28 | ...66-171,186-187 
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |    51.9 |       64 |   57.77 |    51.9 | ...1214,1231-1251 
  metrics.ts       |    74.9 |    82.95 |   74.54 |    74.9 | ...58-978,981-992 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  sdk.ts           |   88.97 |    77.77 |     100 |   88.97 | ...80-281,300-304 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |   79.09 |    85.59 |   83.33 |   79.09 | ...1134,1137-1166 
  uiTelemetry.ts   |   92.97 |    96.96 |   81.25 |   92.97 | ...93-194,200-207 
 ...ry/qwen-logger |   68.01 |    80.21 |   64.91 |   68.01 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   68.01 |       80 |   64.28 |   68.01 | ...1042,1080-1081 
 src/test-utils    |   93.07 |    95.55 |   73.52 |   93.07 |                   
  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.02 |    96.77 |   68.96 |   91.02 | ...32,196-197,210 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   76.39 |    80.77 |   81.66 |   76.39 |                   
  ...erQuestion.ts |    88.8 |    76.74 |    90.9 |    88.8 | ...36-337,344-345 
  cron-create.ts   |   97.61 |    88.88 |   83.33 |   97.61 | 30-31             
  cron-delete.ts   |   96.55 |      100 |   83.33 |   96.55 | 26-27             
  cron-list.ts     |   96.36 |      100 |   83.33 |   96.36 | 25-26             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |   77.69 |    84.46 |   73.33 |   77.69 | ...76-677,764-814 
  exitPlanMode.ts  |   84.61 |    85.71 |     100 |   84.61 | ...60-163,177-189 
  glob.ts          |   90.63 |    88.33 |   84.61 |   90.63 | ...28,171,302,305 
  grep.ts          |   79.19 |    85.71 |   78.94 |   79.19 | ...20,560,569-576 
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.69 |    60.09 |   90.32 |   72.69 | ...1208,1210-1211 
  ...nt-manager.ts |   52.09 |     65.9 |   47.36 |   52.09 | ...02-520,523-560 
  mcp-client.ts    |   29.65 |    71.05 |   46.87 |   29.65 | ...1434,1438-1441 
  mcp-tool.ts      |   90.92 |    88.88 |   96.42 |   90.92 | ...89-590,640-641 
  memory-config.ts |       0 |        0 |       0 |       0 | 1-48              
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 102,109           
  monitor.ts       |   92.16 |    83.45 |      92 |   92.16 | ...15,544-547,560 
  ...nforcement.ts |   82.03 |    89.47 |     100 |   82.03 | 137-148,197-210   
  read-file.ts     |   95.09 |     88.6 |      90 |   95.09 | ...99,271-274,277 
  ripGrep.ts       |   94.59 |    85.71 |   93.33 |   94.59 | ...60,463,541-542 
  ...-transport.ts |    6.34 |        0 |       0 |    6.34 | 47-145            
  send-message.ts  |   88.77 |    91.66 |   83.33 |   88.77 | 44-45,68-76       
  shell.ts         |   81.42 |    80.74 |    90.9 |   81.42 | ...1243,1292-1298 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   88.11 |    91.17 |   84.61 |   88.11 | ...95,399,422-444 
  task-stop.ts     |   92.94 |    96.15 |   85.71 |   92.94 | 39-40,54-64       
  todoWrite.ts     |   85.42 |    84.09 |   84.61 |   85.42 | ...05-410,432-433 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   67.94 |    68.42 |   68.57 |   67.94 | ...59-660,668-669 
  tools.ts         |    87.6 |    89.79 |   88.23 |    87.6 | ...31-432,448-454 
  web-fetch.ts     |   88.44 |    76.92 |    92.3 |   88.44 | ...05-306,308-309 
  write-file.ts    |   78.82 |     78.2 |   83.33 |   78.82 | ...13-616,628-663 
 src/tools/agent   |   83.08 |    84.15 |   83.33 |   83.08 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent.ts         |    83.2 |    84.29 |   82.92 |    83.2 | ...1519,1528-1532 
  fork-subagent.ts |   78.26 |    71.42 |      80 |   78.26 | 54-72,104-105     
 src/utils         |    87.3 |    87.32 |    91.7 |    87.3 |                   
  LruCache.ts      |       0 |        0 |       0 |       0 | 1-41              
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   76.08 |    44.44 |     100 |   76.08 | 61-70,72          
  bareMode.ts      |   27.27 |      100 |       0 |   27.27 | 9-15,18-19        
  browser.ts       |    7.69 |      100 |       0 |    7.69 | 17-56             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |   42.85 |    23.07 |     100 |   42.85 | 26-31,33-45,47-54 
  cronParser.ts    |   89.74 |    85.71 |     100 |   89.74 | ...,63-64,183-186 
  debugLogger.ts   |   96.12 |    93.75 |   93.75 |   96.12 | 164-168           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...28-429,463-464 
  editor.ts        |   97.61 |    95.71 |     100 |   97.61 | ...70-271,273-274 
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |     100 |    95.45 |     100 |     100 | 83                
  errorParsing.ts  |    97.7 |    96.87 |     100 |    97.7 | 72-73             
  ...rReporting.ts |   88.46 |       90 |     100 |   88.46 | 69-74             
  errors.ts        |   70.92 |    80.39 |   53.33 |   70.92 | ...03-219,223-229 
  fetch.ts         |   70.18 |    71.42 |   71.42 |   70.18 | ...42,148,161,186 
  fileUtils.ts     |   89.18 |    85.06 |   94.73 |   89.18 | ...91-898,902-908 
  forkedAgent.ts   |   62.98 |    54.54 |      75 |   62.98 | ...23-432,434-447 
  formatters.ts    |   54.54 |       50 |     100 |   54.54 | 12-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        |    12.5 |      100 |       0 |    12.5 | 21-34             
  ...noreParser.ts |    92.3 |    89.36 |     100 |    92.3 | ...15-116,186-187 
  gitUtils.ts      |   38.88 |    84.61 |      50 |   38.88 | ...2,51-74,97-148 
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 26                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   59.57 |    89.74 |   45.45 |   59.57 | ...53-286,292-298 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...yDiscovery.ts |   83.85 |    79.36 |     100 |   83.85 | ...15,318,410-413 
  ...tProcessor.ts |   93.63 |       90 |     100 |   93.63 | ...96-302,384-385 
  ...Inspectors.ts |   61.53 |      100 |      50 |   61.53 | 18-23             
  ...kerChecker.ts |   82.55 |    78.57 |     100 |   82.55 | 68-69,79-84,92-98 
  notebook.ts      |   94.35 |    84.78 |     100 |   94.35 | ...10,122,174-176 
  openaiLogger.ts  |   86.27 |    82.14 |     100 |   86.27 | ...05-107,130-135 
  partUtils.ts     |     100 |      100 |     100 |     100 |                   
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   92.82 |    91.02 |     100 |   92.82 | ...71-372,374-376 
  pdf.ts           |   93.68 |    87.05 |     100 |   93.68 | ...96-297,321-325 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  ...ectSummary.ts |   89.39 |    72.41 |     100 |   89.39 | ...37-142,193-196 
  ...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 |   85.45 |    85.18 |     100 |   85.45 | ...59,65-66,72-73 
  rateLimit.ts     |   91.48 |    94.11 |     100 |   91.48 | 80,93-95          
  readManyFiles.ts |   87.96 |    86.95 |     100 |   87.96 | ...05-207,223-234 
  retry.ts         |   89.81 |    88.05 |     100 |   89.81 | ...29,350,357-358 
  ripgrepUtils.ts  |   46.53 |    84.37 |   66.66 |   46.53 | ...32-233,245-322 
  ...sDiscovery.ts |   97.42 |    92.85 |     100 |   97.42 | ...04,182-183,202 
  ...tchOptions.ts |   63.85 |    64.28 |   83.33 |   63.85 | ...29-130,187-188 
  safeJsonParse.ts |   74.07 |    83.33 |     100 |   74.07 | 40-46             
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   90.78 |    87.87 |     100 |   90.78 | ...41-42,93,95-96 
  ...aValidator.ts |   93.43 |    77.04 |     100 |   93.43 | ...46,155-158,212 
  ...r-launcher.ts |   76.92 |     91.3 |   66.66 |   76.92 | ...34,136,157-195 
  ...orageUtils.ts |   92.41 |    82.82 |     100 |   92.41 | ...39,423-430,441 
  shell-utils.ts   |   82.93 |     89.5 |     100 |   82.93 | ...1522,1529-1533 
  ...lAstParser.ts |   95.58 |    85.79 |     100 |   95.58 | ...1059-1061,1071 
  ...nlyChecker.ts |   95.75 |    92.47 |     100 |   95.75 | ...00-301,313-314 
  sideQuery.ts     |     100 |    92.85 |     100 |     100 | 43                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,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     |      60 |      100 |   66.66 |      60 | 36-55             
  thoughtUtils.ts  |     100 |    92.85 |     100 |     100 | 71                
  ...-converter.ts |   94.59 |    85.71 |     100 |   94.59 | 35-36             
  tool-utils.ts    |    93.6 |     91.3 |     100 |    93.6 | ...58-159,162-163 
  truncation.ts    |     100 |       92 |     100 |     100 | 52,71             
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   93.71 |    88.88 |   93.33 |   93.71 | ...24-225,249-251 
  xml.ts           |     100 |      100 |     100 |     100 |                   
  yaml-parser.ts   |      92 |    84.31 |     100 |      92 | 49-53,65-69       
 ...ils/filesearch |   96.34 |    91.66 |     100 |   96.34 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   96.87 |    94.44 |     100 |   96.87 | 83-84             
  fileSearch.ts    |   93.29 |    86.76 |     100 |   93.29 | ...40-241,243-244 
  ignore.ts        |     100 |      100 |     100 |     100 |                   
  result-cache.ts  |     100 |     92.3 |     100 |     100 | 46                
 ...uest-tokenizer |   56.63 |    74.52 |   74.19 |   56.63 |                   
  ...eTokenizer.ts |   41.86 |    76.47 |   69.23 |   41.86 | ...70-443,453-507 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |      76 |      100 |   33.33 |      76 | 45-48,55-56       
  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.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Downgraded from Request Changes to Comment: self-PR (GitHub rejects REQUEST_CHANGES on own PR).

Critical (unmapped to diff): background-agent-resume.ts:142-150 — 该文件存在一个与 agent.ts 同名的本地 createApprovalModeOverride 函数,此 PR 将 agent.ts 中的导出版本升级为异步 + 注册表重建,但未触及此本地副本。Fork 恢复路径 (createResumedForkSubagent, L877) 将该函数的结果直接传给 AgentHeadless.create,绕过了 SubagentManager.maybeOverrideContentGenerator(注册表重建在此处)。恢复的 fork 子 agent 中的 EditTool/WriteFileTool/ReadFileTool 仍将 this.config 解析为父进程 Config,使用父进程的 FileReadCache

修复建议: 删除本地副本,从 agent.ts 导入已更新的 createApprovalModeOverride,调用点改为 await

— deepseek-v4-pro via Qwen Code /review

Comment thread packages/core/src/subagents/subagent-manager.ts Outdated
Comment thread packages/core/src/subagents/subagent-manager.ts Outdated
Comment thread packages/core/src/tools/agent/agent.ts
Comment thread packages/core/src/subagents/subagent-manager.ts Outdated
Follow-up audit on PR #3873 surfaced a duplicate, pre-rebuild copy of
`createApprovalModeOverride` living in `background-agent-resume.ts`
(L142-150). Resumed fork agents go through `createResumedForkSubagent`
which bypasses `SubagentManager.maybeOverrideContentGenerator` (where
the registry rebuild now lives), so the resumed fork's
`EditTool` / `WriteFileTool` / `ReadFileTool` were still resolving
`this.config` to the parent and reading the parent's `FileReadCache`.

The non-fork resume path went through `subagent-manager` and worked
correctly only because `maybeOverrideContentGenerator` saw no upstream
own-registry on `bgConfig` and rebuilt one — but with that fallback
the fork path could never benefit.

This change deletes the local copy and switches `background-agent-resume.ts`
to import the now-async exported `createApprovalModeOverride` from
`agent.ts`. Drops the previous `?: this.config` short-circuit so the
resumed agent ALWAYS gets a wrapper Config — the same behaviour
`agent.ts` already enforces; reusing the parent directly defeats the
per-Config FileReadCache isolation.

Updates `background-agent-resume.test.ts` mock config with the
`createToolRegistry` / `getToolRegistry` stubs the rebuild path now
exercises.
@wenshao

wenshao commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed in 809c00f3b — thanks for catching background-agent-resume.ts:142-150. The duplicate, pre-rebuild createApprovalModeOverride is gone; the file now imports the exported async version from agent.ts so the registry rebuild applies to:

  • the fork resume path (createResumedForkSubagent, which bypasses SubagentManager.maybeOverrideContentGenerator), and
  • the non-fork resume path (which only worked accidentally before, via maybeOverrideContentGenerator's no-upstream-registry fallback).

Also dropped the ?: this.config short-circuit so the resumed agent always gets a wrapper Config, matching agent.ts's "always wrap even when modes match" behavior — reusing parent directly would have defeated the per-Config FileReadCache isolation regardless of mode.

background-agent-resume.test.ts mocks updated for the new path; full core suite green (268 files / 6938 passed).

中文

809c00f3b 已修。多谢揪出 background-agent-resume.ts:142-150 的本地副本。删了本地版本,改成从 agent.ts 导入异步版的 createApprovalModeOverride,所以注册表重建现在覆盖:

  • fork resume 路径(createResumedForkSubagent,绕过 SubagentManager.maybeOverrideContentGenerator
  • 非 fork resume 路径(之前是靠 maybeOverrideContentGenerator 的 "上游没建过 registry" 兜底分支恰好工作)

同时去掉了 ?: this.config 短路,让 resumed agent 总是套 wrapper,跟 agent.ts "approval mode 一致也照样套" 的行为对齐 —— 直接复用 parent 会破坏 per-Config FileReadCache 隔离,跟 mode 是否一样无关。

background-agent-resume.test.ts mock 跟着补了新路径需要的桩;全套 core 测试绿(268 文件 / 6938 通过)。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

No review findings. Downgraded from Approve to Comment: self-PR reviews cannot be approved by the PR author. — gpt-5.5 via Qwen Code /review

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Test review from deepseek-v4-pro via Qwen Code /review

@wenshao

wenshao commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

Code Review — deepseek-v4-pro via Qwen Code

Critical

FileReadCache 分裂当 baseHasOwnRegistry=truesubagent-manager.ts:735-741

当上游 createApprovalModeOverride 已重建注册表后,maybeOverrideContentGenerator 返回 Object.create(base) 并跳过注册表重建。这导致:

  • isolated.getFileReadCache() 懒创建独立缓存(缓存 B)
  • isolated.getToolRegistry() 代理到 base 的注册表,工具绑定到 base,使用 base 的缓存(缓存 A)
  • Client/GeminiChat 调用 isolated.getFileReadCache().clear() 清空缓存 B,工具使用的缓存 A 不受影响

上下文压缩后缓存清空对工具无效,模型重新读文件时收到 file_unchanged 占位符。同样影响 background-agent-resume.ts:536bgConfig = Object.create(agentConfig)

建议修复:baseHasOwnRegistry=true 时,覆盖 isolated.getFileReadCache = () => base.getFileReadCache() 消除双缓存。


Suggestion

  1. 非 inherit 模型覆盖分支缺少 bound-tool 隔离测试subagent-manager-override.test.ts 的 5 个测试仅覆盖 inherits 分支,model 覆盖分支没有对应覆盖。
  2. 后台恢复测试未断言注册表重建background-agent-resume.test.ts mock 提供了桩但未断言调用。
  3. createYoloConfig 和 planner 仍使用旧 Object.create 模式forkedAgent.ts:264, planner 等 3 处未应用注册表重建。
  4. copyDiscoveredToolsFrom 保留父 Config 引用 — MCP 工具使用父的信任状态而非子代理的。
  5. createApprovalModeOverride 缺少错误处理agent.ts:194getToolRegistry() 返回 undefined 会抛无上下文 TypeError。

Verdict

Request changes (downgraded to Comment — self-PR)

— deepseek-v4-pro via Qwen Code /review

Three independent fixes from PR #3873 review feedback:

1. Switch the upstream-rebuild guard from
   `hasOwnProperty(base, 'getToolRegistry')` to a Symbol-keyed marker
   `TOOL_REGISTRY_REBUILT`. The own-property check missed the case
   where the override is reached via an Object.create wrapper above
   the rebuilt Config (e.g. `bgConfig = Object.create(agentConfig)` in
   the agent.ts background path) — it would falsely report "no
   upstream rebuild" and cause a redundant third rebuild that wastes
   work and doubles the listener-leak surface. Symbol property reads
   walk the prototype chain via normal lookup, so a marker stored on
   any ancestor is correctly observed.

   Extracts the shared rebuild logic into
   `rebuildToolRegistryOnOverride(override, base)` so the three spawn
   sites (agent.ts:createApprovalModeOverride, the inherits branch,
   the non-inherit branch) cannot drift apart.

2. Stop the per-subagent ToolRegistry in the lifecycle finally blocks:
   - agent.ts foreground finally (after the inner try wrapping
     `runFramed`)
   - agent.ts background bgBody finally (after `bgSubagent.execute`
     resolves)
   - background-agent-resume.ts resume body finally (same shape)

   Without this, every AgentTool / SkillTool the model instantiates
   from the per-subagent registry registers a change-listener on
   shared SubagentManager / SkillManager, and repeated subagent runs
   accumulate listeners for the rest of the session. Stop is
   fire-and-forget, matching `InProcessBackend.cleanup` and
   `stopAgent`.

3. Add bound-tool isolation tests for the non-inherit branch
   (explicit-model selector). The original PR only covered the
   inherits branch directly; the non-inherit branch now goes through
   the same helper, but a dedicated test pins
   `tool.config === override` and the FileReadCache binding so a
   regression cannot leave explicit-model subagents reading the
   parent's cache while existing model-override tests still pass.

Tests now exercise:
- Symbol marker propagation via Object.create chain (3 cases)
- Non-inherit rebuild + bound-tool isolation
- Non-inherit skip-rebuild when upstream wrapper has the marker
- Pre-existing inherits / chained-override / approval-mode propagation
- Mock configs in agent.test.ts / subagent-manager.test.ts /
  background-agent-resume.test.ts gain `stop` and `tools: Map` stubs
  to model the registry contract the override path now exercises.

`npx vitest run packages/core/src` — 268 files / 6943 passed.
@tanzhenxin tanzhenxin added the type/bug Something isn't working as expected label May 7, 2026

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

The fix is correct: rebuilding the tool registry on the override Config binds the core file tools to the per-subagent state, and the Symbol.for-keyed rebuilt-marker correctly propagates through the Object.create wrapper chain. Tests exercise the bound-tool path with real Config + real ToolRegistry and assert the load-bearing invariant (bound tool's config === override). One incidental note: the title says "bound tools resolve to the subagent", but copyDiscoveredToolsFrom reference-copies discovered tools so MCP tools still hold this.config = parent. Almost certainly deliberate to avoid re-running discovery, but a one-line note in the description would clarify scope.

Issues

1. Foreground-fork path leaks the per-spawn registry (severity: low · confidence: very high)

The PR adds a per-spawn registry on every override and adds matching cleanup in three of the four spawn paths — foreground non-fork, background non-fork, and background fork. The foreground-fork branch is the odd one out: it fires the fork as a void promise and returns the placeholder result with no try/finally around the fork body, so the per-spawn registry it built is never stopped. AgentTool / SkillTool change-listeners on the shared subagent and skill managers accumulate per foreground-fork for the rest of the session. New regression introduced by this PR — pre-PR the agent config was reused so there was nothing to release. Worth a follow-up commit.

2. PR description is out of sync with the code (severity: low · confidence: very high)

The body still says the override helper has a single call site and that the chained-override skip uses a hasOwnProperty check. Neither matches HEAD: the helper is now called from both the agent tool and the background-agent resume path, and the skip uses a Symbol.for-keyed marker — explicitly chosen so prototype-chain wrappers (the bgConfig = Object.create(agentConfig) pattern) are recognised as already-rebuilt.

3. Adjacent Config-wrapper sites still have the original bug (severity: low · confidence: high)

Out of scope here, but flagging for follow-up. The yolo-config wrapper used by the forked-agent helper, the scoped-permission wrapper used by memory extraction, and the dream-agent planner's wrapper all build an override via Object.create and hand it directly to the headless agent — bypassing the subagent manager and therefore the rebuild. Their bound tools still resolve back to the parent, so the YOLO override and the scoped permission manager are silently ignored on any bound-tool path. Memory extraction is the worst case because it stacks both wrappers.

Verdict

APPROVE — the core fix is correct and well-tested. The three notes above are low-severity follow-ups; none should block merge.

@wenshao wenshao merged commit 7124c6c into main May 7, 2026
13 checks passed
TaimoorSiddiquiOfficial pushed a commit to TaimoorSiddiquiOfficial/HopCode that referenced this pull request May 7, 2026
…d tools resolve to the subagent (QwenLM#3873)

Cherry-picked from QwenLM/qwen-code@7124c6cba.
Resolved: kept HopCode's settings override logic + added upstream's tool
registry rebuild to fix subagent tool resolution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tanzhenxin pushed a commit that referenced this pull request May 7, 2026
…#3887)

Follow-up to #3873 review: the foreground-fork branch in `agent.ts`
fires the fork body via `void runInForkContext(runFramedFork)` and
returns the placeholder result synchronously, with no try/finally
around the fork body. The other three spawn paths (foreground
non-fork, background fork, background non-fork) added in #3873
already stop the per-subagent ToolRegistry in their finally blocks
— this one was missed, so any AgentTool / SkillTool the fork's
model later instantiated leaked its change-listener on the shared
SubagentManager / SkillManager for the rest of the session.

Wraps the inner body in `try { await runSubagentWithHooks(...) }
finally { void agentConfig.getToolRegistry().stop().catch(() => {}) }`
— same shape as the background bgBody finally added in #3873.

Adds a regression test in `agent.test.ts` Fork dispatch describe
that drains the detached fork body and asserts the stop spy was
invoked exactly once.
wenshao added a commit that referenced this pull request May 8, 2026
* fix(core): close bound-tool gap on runForkedAgent's YOLO wrapper

Follow-up to #3873 review (#3 of the three flagged adjacent
Config-wrapper sites). `runForkedAgent`'s AgentHeadless path used to
build its YOLO override via a local `Object.create(parent) +
getApprovalMode = YOLO` helper that did NOT rebuild the tool
registry, so:

1. The YOLO approval mode was silently ignored on the bound-tool
   path — parent's already-bound `EditTool` / `WriteFileTool` /
   `ReadFileTool` resolved `this.config.getApprovalMode()` back to
   the parent.
2. The fork's reads / mutations went through the parent's
   `FileReadCache` instead of a per-fork cache.
3. Memory-extraction and dream-agent paths stack the YOLO wrapper
   over a `getPermissionManager`-overriding scoped wrapper. Since
   the bound tools resolved to the parent, BOTH overrides — the
   YOLO approval mode AND the scoped permission manager — were
   bypassed.

The fix routes through the existing `createApprovalModeOverride`
helper, which:
- rebuilds the tool registry on the wrapper (so bound tools resolve
  `this.config` to the wrapper),
- copies discovered tools from the upstream registry,
- sets the `TOOL_REGISTRY_REBUILT` Symbol marker so any further
  downstream wrapper layer recognises the rebuild and skips
  redundant work.

The memory-extraction / dream-agent composition now resolves
correctly via prototype walk — the YOLO wrapper sits above the
scoped wrapper, so bound tools observe `getApprovalMode() = YOLO`
on the wrapper itself and `getPermissionManager() = scopedPm` one
prototype level up.

Adds a try/finally around the AgentHeadless run so the per-fork
ToolRegistry is stopped after execution — same shape as the spawn
finallys in `agent.ts` and `background-agent-resume.ts`. Without
this, every AgentTool / SkillTool the fork's model later
instantiates leaks its change-listener on shared SubagentManager /
SkillManager.

Adds `forkedAgent.agent.test.ts` covering: marker + YOLO + distinct
registry on the wrapper passed to AgentHeadless.create; bound
EditTool resolves to the wrapper; memory-scoped composition
preserves both YOLO and scopedPm; `stop()` fires after the
AgentHeadless body finishes. Uses `vi.spyOn(AgentHeadless, 'create')`
rather than module mocking so the real `ContextState` /
`AgentEventEmitter` keep working.

`npx vitest run packages/core/src` — 269 files / 6992 passed.

* test(core): cover stop() lifecycle on AgentHeadless.create + execute failure paths

Self-review feedback on #3892: the stop lifecycle test only covered
the success path. A future refactor could move the stop() out of
the `finally` block and onto the success branch, reintroducing
listener leaks when create or execute rejects, while every existing
test still passes.

Two new tests pin the cleanup to the `finally`:

1. `stops the per-fork ToolRegistry even when AgentHeadless.create rejects`
   — make `AgentHeadless.create` return a rejected promise; assert
   the rejection propagates and the stop spy still fires once.
2. `stops the per-fork ToolRegistry even when headless.execute rejects`
   — return a headless object whose `execute` rejects; same shape.

Together with the success-path test these three cases cover every
exit edge of the AgentHeadless body.

`npx vitest run packages/core/src` — 269 files / 6994 passed.
DragonnZhang pushed a commit that referenced this pull request May 8, 2026
…d tools resolve to the subagent (#3873)

* fix(core): rebuild tool registry on subagent Config overrides so bound tools resolve to the subagent

PR-B (#3774) added per-Config FileReadCache isolation via Object.create
overrides at two subagent spawn sites — agent.ts:createApprovalModeOverride
and subagent-manager.ts:maybeOverrideContentGenerator. The override
shielded code that read FileReadCache directly through the Config
instance, but missed the bound-tool path: Config.createToolRegistry runs
once at parent initialise time, so the parent's EditTool / WriteFileTool
/ ReadFileTool instances are bound with `this.config = parent`. The
subagent's Object.create wrapper inherited getToolRegistry via the
prototype chain, reaching the parent registry whose bound tools then
read FileReadCache and approval mode from the parent.

This change closes that gap by rebuilding the tool registry on the
override at both sites — the same pattern InProcessBackend.createPerAgentConfig
already uses:

  - override.createToolRegistry(undefined, { skipDiscovery: true })
  - registry.copyDiscoveredToolsFrom(base.getToolRegistry())
  - override.getToolRegistry = () => registry

createApprovalModeOverride becomes async; its single call site already
ran inside an async block. maybeOverrideContentGenerator skips the
rebuild when the upstream Config already has its own getToolRegistry
(real-world case: agent.ts wrapper passed through createAgentHeadless),
avoiding wasted work, listener accumulation on shared SubagentManager /
SkillManager, and a cache split where the bound tools' registry layer
diverges from the runtime context's lazy-init cache.

Includes regression tests in agent-override.test.ts and
subagent-manager-override.test.ts that exercise the bound-tool path:
they instantiate the lazy factories on the override registry and
assert that EditTool / WriteFileTool / ReadFileTool resolve
this.config to the override Config (and thus to the override's
FileReadCache / approval mode), not the parent.

* fix(core): close bound-tool gap on resumed background agents too

Follow-up audit on PR #3873 surfaced a duplicate, pre-rebuild copy of
`createApprovalModeOverride` living in `background-agent-resume.ts`
(L142-150). Resumed fork agents go through `createResumedForkSubagent`
which bypasses `SubagentManager.maybeOverrideContentGenerator` (where
the registry rebuild now lives), so the resumed fork's
`EditTool` / `WriteFileTool` / `ReadFileTool` were still resolving
`this.config` to the parent and reading the parent's `FileReadCache`.

The non-fork resume path went through `subagent-manager` and worked
correctly only because `maybeOverrideContentGenerator` saw no upstream
own-registry on `bgConfig` and rebuilt one — but with that fallback
the fork path could never benefit.

This change deletes the local copy and switches `background-agent-resume.ts`
to import the now-async exported `createApprovalModeOverride` from
`agent.ts`. Drops the previous `?: this.config` short-circuit so the
resumed agent ALWAYS gets a wrapper Config — the same behaviour
`agent.ts` already enforces; reusing the parent directly defeats the
per-Config FileReadCache isolation.

Updates `background-agent-resume.test.ts` mock config with the
`createToolRegistry` / `getToolRegistry` stubs the rebuild path now
exercises.

* fix(core): address bound-tool isolation review feedback

Three independent fixes from PR #3873 review feedback:

1. Switch the upstream-rebuild guard from
   `hasOwnProperty(base, 'getToolRegistry')` to a Symbol-keyed marker
   `TOOL_REGISTRY_REBUILT`. The own-property check missed the case
   where the override is reached via an Object.create wrapper above
   the rebuilt Config (e.g. `bgConfig = Object.create(agentConfig)` in
   the agent.ts background path) — it would falsely report "no
   upstream rebuild" and cause a redundant third rebuild that wastes
   work and doubles the listener-leak surface. Symbol property reads
   walk the prototype chain via normal lookup, so a marker stored on
   any ancestor is correctly observed.

   Extracts the shared rebuild logic into
   `rebuildToolRegistryOnOverride(override, base)` so the three spawn
   sites (agent.ts:createApprovalModeOverride, the inherits branch,
   the non-inherit branch) cannot drift apart.

2. Stop the per-subagent ToolRegistry in the lifecycle finally blocks:
   - agent.ts foreground finally (after the inner try wrapping
     `runFramed`)
   - agent.ts background bgBody finally (after `bgSubagent.execute`
     resolves)
   - background-agent-resume.ts resume body finally (same shape)

   Without this, every AgentTool / SkillTool the model instantiates
   from the per-subagent registry registers a change-listener on
   shared SubagentManager / SkillManager, and repeated subagent runs
   accumulate listeners for the rest of the session. Stop is
   fire-and-forget, matching `InProcessBackend.cleanup` and
   `stopAgent`.

3. Add bound-tool isolation tests for the non-inherit branch
   (explicit-model selector). The original PR only covered the
   inherits branch directly; the non-inherit branch now goes through
   the same helper, but a dedicated test pins
   `tool.config === override` and the FileReadCache binding so a
   regression cannot leave explicit-model subagents reading the
   parent's cache while existing model-override tests still pass.

Tests now exercise:
- Symbol marker propagation via Object.create chain (3 cases)
- Non-inherit rebuild + bound-tool isolation
- Non-inherit skip-rebuild when upstream wrapper has the marker
- Pre-existing inherits / chained-override / approval-mode propagation
- Mock configs in agent.test.ts / subagent-manager.test.ts /
  background-agent-resume.test.ts gain `stop` and `tools: Map` stubs
  to model the registry contract the override path now exercises.

`npx vitest run packages/core/src` — 268 files / 6943 passed.
DragonnZhang pushed a commit that referenced this pull request May 8, 2026
…#3887)

Follow-up to #3873 review: the foreground-fork branch in `agent.ts`
fires the fork body via `void runInForkContext(runFramedFork)` and
returns the placeholder result synchronously, with no try/finally
around the fork body. The other three spawn paths (foreground
non-fork, background fork, background non-fork) added in #3873
already stop the per-subagent ToolRegistry in their finally blocks
— this one was missed, so any AgentTool / SkillTool the fork's
model later instantiated leaked its change-listener on the shared
SubagentManager / SkillManager for the rest of the session.

Wraps the inner body in `try { await runSubagentWithHooks(...) }
finally { void agentConfig.getToolRegistry().stop().catch(() => {}) }`
— same shape as the background bgBody finally added in #3873.

Adds a regression test in `agent.test.ts` Fork dispatch describe
that drains the detached fork body and asserts the stop spy was
invoked exactly once.
DragonnZhang pushed a commit that referenced this pull request May 8, 2026
* fix(core): close bound-tool gap on runForkedAgent's YOLO wrapper

Follow-up to #3873 review (#3 of the three flagged adjacent
Config-wrapper sites). `runForkedAgent`'s AgentHeadless path used to
build its YOLO override via a local `Object.create(parent) +
getApprovalMode = YOLO` helper that did NOT rebuild the tool
registry, so:

1. The YOLO approval mode was silently ignored on the bound-tool
   path — parent's already-bound `EditTool` / `WriteFileTool` /
   `ReadFileTool` resolved `this.config.getApprovalMode()` back to
   the parent.
2. The fork's reads / mutations went through the parent's
   `FileReadCache` instead of a per-fork cache.
3. Memory-extraction and dream-agent paths stack the YOLO wrapper
   over a `getPermissionManager`-overriding scoped wrapper. Since
   the bound tools resolved to the parent, BOTH overrides — the
   YOLO approval mode AND the scoped permission manager — were
   bypassed.

The fix routes through the existing `createApprovalModeOverride`
helper, which:
- rebuilds the tool registry on the wrapper (so bound tools resolve
  `this.config` to the wrapper),
- copies discovered tools from the upstream registry,
- sets the `TOOL_REGISTRY_REBUILT` Symbol marker so any further
  downstream wrapper layer recognises the rebuild and skips
  redundant work.

The memory-extraction / dream-agent composition now resolves
correctly via prototype walk — the YOLO wrapper sits above the
scoped wrapper, so bound tools observe `getApprovalMode() = YOLO`
on the wrapper itself and `getPermissionManager() = scopedPm` one
prototype level up.

Adds a try/finally around the AgentHeadless run so the per-fork
ToolRegistry is stopped after execution — same shape as the spawn
finallys in `agent.ts` and `background-agent-resume.ts`. Without
this, every AgentTool / SkillTool the fork's model later
instantiates leaks its change-listener on shared SubagentManager /
SkillManager.

Adds `forkedAgent.agent.test.ts` covering: marker + YOLO + distinct
registry on the wrapper passed to AgentHeadless.create; bound
EditTool resolves to the wrapper; memory-scoped composition
preserves both YOLO and scopedPm; `stop()` fires after the
AgentHeadless body finishes. Uses `vi.spyOn(AgentHeadless, 'create')`
rather than module mocking so the real `ContextState` /
`AgentEventEmitter` keep working.

`npx vitest run packages/core/src` — 269 files / 6992 passed.

* test(core): cover stop() lifecycle on AgentHeadless.create + execute failure paths

Self-review feedback on #3892: the stop lifecycle test only covered
the success path. A future refactor could move the stop() out of
the `finally` block and onto the success branch, reintroducing
listener leaks when create or execute rejects, while every existing
test still passes.

Two new tests pin the cleanup to the `finally`:

1. `stops the per-fork ToolRegistry even when AgentHeadless.create rejects`
   — make `AgentHeadless.create` return a rejected promise; assert
   the rejection propagates and the stop spy still fires once.
2. `stops the per-fork ToolRegistry even when headless.execute rejects`
   — return a headless object whose `execute` rejects; same shape.

Together with the success-path test these three cases cover every
exit edge of the AgentHeadless body.

`npx vitest run packages/core/src` — 269 files / 6994 passed.
TaimoorSiddiquiOfficial pushed a commit to TaimoorSiddiquiOfficial/HopCode that referenced this pull request May 8, 2026
…nLM#3892)

* fix(core): close bound-tool gap on runForkedAgent's YOLO wrapper

Follow-up to QwenLM#3873 review (#3 of the three flagged adjacent
Config-wrapper sites). `runForkedAgent`'s AgentHeadless path used to
build its YOLO override via a local `Object.create(parent) +
getApprovalMode = YOLO` helper that did NOT rebuild the tool
registry, so:

1. The YOLO approval mode was silently ignored on the bound-tool
   path — parent's already-bound `EditTool` / `WriteFileTool` /
   `ReadFileTool` resolved `this.config.getApprovalMode()` back to
   the parent.
2. The fork's reads / mutations went through the parent's
   `FileReadCache` instead of a per-fork cache.
3. Memory-extraction and dream-agent paths stack the YOLO wrapper
   over a `getPermissionManager`-overriding scoped wrapper. Since
   the bound tools resolved to the parent, BOTH overrides — the
   YOLO approval mode AND the scoped permission manager — were
   bypassed.

The fix routes through the existing `createApprovalModeOverride`
helper, which:
- rebuilds the tool registry on the wrapper (so bound tools resolve
  `this.config` to the wrapper),
- copies discovered tools from the upstream registry,
- sets the `TOOL_REGISTRY_REBUILT` Symbol marker so any further
  downstream wrapper layer recognises the rebuild and skips
  redundant work.

The memory-extraction / dream-agent composition now resolves
correctly via prototype walk — the YOLO wrapper sits above the
scoped wrapper, so bound tools observe `getApprovalMode() = YOLO`
on the wrapper itself and `getPermissionManager() = scopedPm` one
prototype level up.

Adds a try/finally around the AgentHeadless run so the per-fork
ToolRegistry is stopped after execution — same shape as the spawn
finallys in `agent.ts` and `background-agent-resume.ts`. Without
this, every AgentTool / SkillTool the fork's model later
instantiates leaks its change-listener on shared SubagentManager /
SkillManager.

Adds `forkedAgent.agent.test.ts` covering: marker + YOLO + distinct
registry on the wrapper passed to AgentHeadless.create; bound
EditTool resolves to the wrapper; memory-scoped composition
preserves both YOLO and scopedPm; `stop()` fires after the
AgentHeadless body finishes. Uses `vi.spyOn(AgentHeadless, 'create')`
rather than module mocking so the real `ContextState` /
`AgentEventEmitter` keep working.

`npx vitest run packages/core/src` — 269 files / 6992 passed.

* test(core): cover stop() lifecycle on AgentHeadless.create + execute failure paths

Self-review feedback on QwenLM#3892: the stop lifecycle test only covered
the success path. A future refactor could move the stop() out of
the `finally` block and onto the success branch, reintroducing
listener leaks when create or execute rejects, while every existing
test still passes.

Two new tests pin the cleanup to the `finally`:

1. `stops the per-fork ToolRegistry even when AgentHeadless.create rejects`
   — make `AgentHeadless.create` return a rejected promise; assert
   the rejection propagates and the stop spy still fires once.
2. `stops the per-fork ToolRegistry even when headless.execute rejects`
   — return a headless object whose `execute` rejects; same shape.

Together with the success-path test these three cases cover every
exit edge of the AgentHeadless body.

`npx vitest run packages/core/src` — 269 files / 6994 passed.
B-A-M-N pushed a commit to B-A-M-N/qwen-code that referenced this pull request May 8, 2026
…nLM#3892)

* fix(core): close bound-tool gap on runForkedAgent's YOLO wrapper

Follow-up to QwenLM#3873 review (#3 of the three flagged adjacent
Config-wrapper sites). `runForkedAgent`'s AgentHeadless path used to
build its YOLO override via a local `Object.create(parent) +
getApprovalMode = YOLO` helper that did NOT rebuild the tool
registry, so:

1. The YOLO approval mode was silently ignored on the bound-tool
   path — parent's already-bound `EditTool` / `WriteFileTool` /
   `ReadFileTool` resolved `this.config.getApprovalMode()` back to
   the parent.
2. The fork's reads / mutations went through the parent's
   `FileReadCache` instead of a per-fork cache.
3. Memory-extraction and dream-agent paths stack the YOLO wrapper
   over a `getPermissionManager`-overriding scoped wrapper. Since
   the bound tools resolved to the parent, BOTH overrides — the
   YOLO approval mode AND the scoped permission manager — were
   bypassed.

The fix routes through the existing `createApprovalModeOverride`
helper, which:
- rebuilds the tool registry on the wrapper (so bound tools resolve
  `this.config` to the wrapper),
- copies discovered tools from the upstream registry,
- sets the `TOOL_REGISTRY_REBUILT` Symbol marker so any further
  downstream wrapper layer recognises the rebuild and skips
  redundant work.

The memory-extraction / dream-agent composition now resolves
correctly via prototype walk — the YOLO wrapper sits above the
scoped wrapper, so bound tools observe `getApprovalMode() = YOLO`
on the wrapper itself and `getPermissionManager() = scopedPm` one
prototype level up.

Adds a try/finally around the AgentHeadless run so the per-fork
ToolRegistry is stopped after execution — same shape as the spawn
finallys in `agent.ts` and `background-agent-resume.ts`. Without
this, every AgentTool / SkillTool the fork's model later
instantiates leaks its change-listener on shared SubagentManager /
SkillManager.

Adds `forkedAgent.agent.test.ts` covering: marker + YOLO + distinct
registry on the wrapper passed to AgentHeadless.create; bound
EditTool resolves to the wrapper; memory-scoped composition
preserves both YOLO and scopedPm; `stop()` fires after the
AgentHeadless body finishes. Uses `vi.spyOn(AgentHeadless, 'create')`
rather than module mocking so the real `ContextState` /
`AgentEventEmitter` keep working.

`npx vitest run packages/core/src` — 269 files / 6992 passed.

* test(core): cover stop() lifecycle on AgentHeadless.create + execute failure paths

Self-review feedback on QwenLM#3892: the stop lifecycle test only covered
the success path. A future refactor could move the stop() out of
the `finally` block and onto the success branch, reintroducing
listener leaks when create or execute rejects, while every existing
test still passes.

Two new tests pin the cleanup to the `finally`:

1. `stops the per-fork ToolRegistry even when AgentHeadless.create rejects`
   — make `AgentHeadless.create` return a rejected promise; assert
   the rejection propagates and the stop spy still fires once.
2. `stops the per-fork ToolRegistry even when headless.execute rejects`
   — return a headless object whose `execute` rejects; same shape.

Together with the success-path test these three cases cover every
exit edge of the AgentHeadless body.

`npx vitest run packages/core/src` — 269 files / 6994 passed.
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
…d tools resolve to the subagent (QwenLM#3873)

* fix(core): rebuild tool registry on subagent Config overrides so bound tools resolve to the subagent

PR-B (QwenLM#3774) added per-Config FileReadCache isolation via Object.create
overrides at two subagent spawn sites — agent.ts:createApprovalModeOverride
and subagent-manager.ts:maybeOverrideContentGenerator. The override
shielded code that read FileReadCache directly through the Config
instance, but missed the bound-tool path: Config.createToolRegistry runs
once at parent initialise time, so the parent's EditTool / WriteFileTool
/ ReadFileTool instances are bound with `this.config = parent`. The
subagent's Object.create wrapper inherited getToolRegistry via the
prototype chain, reaching the parent registry whose bound tools then
read FileReadCache and approval mode from the parent.

This change closes that gap by rebuilding the tool registry on the
override at both sites — the same pattern InProcessBackend.createPerAgentConfig
already uses:

  - override.createToolRegistry(undefined, { skipDiscovery: true })
  - registry.copyDiscoveredToolsFrom(base.getToolRegistry())
  - override.getToolRegistry = () => registry

createApprovalModeOverride becomes async; its single call site already
ran inside an async block. maybeOverrideContentGenerator skips the
rebuild when the upstream Config already has its own getToolRegistry
(real-world case: agent.ts wrapper passed through createAgentHeadless),
avoiding wasted work, listener accumulation on shared SubagentManager /
SkillManager, and a cache split where the bound tools' registry layer
diverges from the runtime context's lazy-init cache.

Includes regression tests in agent-override.test.ts and
subagent-manager-override.test.ts that exercise the bound-tool path:
they instantiate the lazy factories on the override registry and
assert that EditTool / WriteFileTool / ReadFileTool resolve
this.config to the override Config (and thus to the override's
FileReadCache / approval mode), not the parent.

* fix(core): close bound-tool gap on resumed background agents too

Follow-up audit on PR QwenLM#3873 surfaced a duplicate, pre-rebuild copy of
`createApprovalModeOverride` living in `background-agent-resume.ts`
(L142-150). Resumed fork agents go through `createResumedForkSubagent`
which bypasses `SubagentManager.maybeOverrideContentGenerator` (where
the registry rebuild now lives), so the resumed fork's
`EditTool` / `WriteFileTool` / `ReadFileTool` were still resolving
`this.config` to the parent and reading the parent's `FileReadCache`.

The non-fork resume path went through `subagent-manager` and worked
correctly only because `maybeOverrideContentGenerator` saw no upstream
own-registry on `bgConfig` and rebuilt one — but with that fallback
the fork path could never benefit.

This change deletes the local copy and switches `background-agent-resume.ts`
to import the now-async exported `createApprovalModeOverride` from
`agent.ts`. Drops the previous `?: this.config` short-circuit so the
resumed agent ALWAYS gets a wrapper Config — the same behaviour
`agent.ts` already enforces; reusing the parent directly defeats the
per-Config FileReadCache isolation.

Updates `background-agent-resume.test.ts` mock config with the
`createToolRegistry` / `getToolRegistry` stubs the rebuild path now
exercises.

* fix(core): address bound-tool isolation review feedback

Three independent fixes from PR QwenLM#3873 review feedback:

1. Switch the upstream-rebuild guard from
   `hasOwnProperty(base, 'getToolRegistry')` to a Symbol-keyed marker
   `TOOL_REGISTRY_REBUILT`. The own-property check missed the case
   where the override is reached via an Object.create wrapper above
   the rebuilt Config (e.g. `bgConfig = Object.create(agentConfig)` in
   the agent.ts background path) — it would falsely report "no
   upstream rebuild" and cause a redundant third rebuild that wastes
   work and doubles the listener-leak surface. Symbol property reads
   walk the prototype chain via normal lookup, so a marker stored on
   any ancestor is correctly observed.

   Extracts the shared rebuild logic into
   `rebuildToolRegistryOnOverride(override, base)` so the three spawn
   sites (agent.ts:createApprovalModeOverride, the inherits branch,
   the non-inherit branch) cannot drift apart.

2. Stop the per-subagent ToolRegistry in the lifecycle finally blocks:
   - agent.ts foreground finally (after the inner try wrapping
     `runFramed`)
   - agent.ts background bgBody finally (after `bgSubagent.execute`
     resolves)
   - background-agent-resume.ts resume body finally (same shape)

   Without this, every AgentTool / SkillTool the model instantiates
   from the per-subagent registry registers a change-listener on
   shared SubagentManager / SkillManager, and repeated subagent runs
   accumulate listeners for the rest of the session. Stop is
   fire-and-forget, matching `InProcessBackend.cleanup` and
   `stopAgent`.

3. Add bound-tool isolation tests for the non-inherit branch
   (explicit-model selector). The original PR only covered the
   inherits branch directly; the non-inherit branch now goes through
   the same helper, but a dedicated test pins
   `tool.config === override` and the FileReadCache binding so a
   regression cannot leave explicit-model subagents reading the
   parent's cache while existing model-override tests still pass.

Tests now exercise:
- Symbol marker propagation via Object.create chain (3 cases)
- Non-inherit rebuild + bound-tool isolation
- Non-inherit skip-rebuild when upstream wrapper has the marker
- Pre-existing inherits / chained-override / approval-mode propagation
- Mock configs in agent.test.ts / subagent-manager.test.ts /
  background-agent-resume.test.ts gain `stop` and `tools: Map` stubs
  to model the registry contract the override path now exercises.

`npx vitest run packages/core/src` — 268 files / 6943 passed.
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
…QwenLM#3887)

Follow-up to QwenLM#3873 review: the foreground-fork branch in `agent.ts`
fires the fork body via `void runInForkContext(runFramedFork)` and
returns the placeholder result synchronously, with no try/finally
around the fork body. The other three spawn paths (foreground
non-fork, background fork, background non-fork) added in QwenLM#3873
already stop the per-subagent ToolRegistry in their finally blocks
— this one was missed, so any AgentTool / SkillTool the fork's
model later instantiated leaked its change-listener on the shared
SubagentManager / SkillManager for the rest of the session.

Wraps the inner body in `try { await runSubagentWithHooks(...) }
finally { void agentConfig.getToolRegistry().stop().catch(() => {}) }`
— same shape as the background bgBody finally added in QwenLM#3873.

Adds a regression test in `agent.test.ts` Fork dispatch describe
that drains the detached fork body and asserts the stop spy was
invoked exactly once.
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
…nLM#3892)

* fix(core): close bound-tool gap on runForkedAgent's YOLO wrapper

Follow-up to QwenLM#3873 review (QwenLM#3 of the three flagged adjacent
Config-wrapper sites). `runForkedAgent`'s AgentHeadless path used to
build its YOLO override via a local `Object.create(parent) +
getApprovalMode = YOLO` helper that did NOT rebuild the tool
registry, so:

1. The YOLO approval mode was silently ignored on the bound-tool
   path — parent's already-bound `EditTool` / `WriteFileTool` /
   `ReadFileTool` resolved `this.config.getApprovalMode()` back to
   the parent.
2. The fork's reads / mutations went through the parent's
   `FileReadCache` instead of a per-fork cache.
3. Memory-extraction and dream-agent paths stack the YOLO wrapper
   over a `getPermissionManager`-overriding scoped wrapper. Since
   the bound tools resolved to the parent, BOTH overrides — the
   YOLO approval mode AND the scoped permission manager — were
   bypassed.

The fix routes through the existing `createApprovalModeOverride`
helper, which:
- rebuilds the tool registry on the wrapper (so bound tools resolve
  `this.config` to the wrapper),
- copies discovered tools from the upstream registry,
- sets the `TOOL_REGISTRY_REBUILT` Symbol marker so any further
  downstream wrapper layer recognises the rebuild and skips
  redundant work.

The memory-extraction / dream-agent composition now resolves
correctly via prototype walk — the YOLO wrapper sits above the
scoped wrapper, so bound tools observe `getApprovalMode() = YOLO`
on the wrapper itself and `getPermissionManager() = scopedPm` one
prototype level up.

Adds a try/finally around the AgentHeadless run so the per-fork
ToolRegistry is stopped after execution — same shape as the spawn
finallys in `agent.ts` and `background-agent-resume.ts`. Without
this, every AgentTool / SkillTool the fork's model later
instantiates leaks its change-listener on shared SubagentManager /
SkillManager.

Adds `forkedAgent.agent.test.ts` covering: marker + YOLO + distinct
registry on the wrapper passed to AgentHeadless.create; bound
EditTool resolves to the wrapper; memory-scoped composition
preserves both YOLO and scopedPm; `stop()` fires after the
AgentHeadless body finishes. Uses `vi.spyOn(AgentHeadless, 'create')`
rather than module mocking so the real `ContextState` /
`AgentEventEmitter` keep working.

`npx vitest run packages/core/src` — 269 files / 6992 passed.

* test(core): cover stop() lifecycle on AgentHeadless.create + execute failure paths

Self-review feedback on QwenLM#3892: the stop lifecycle test only covered
the success path. A future refactor could move the stop() out of
the `finally` block and onto the success branch, reintroducing
listener leaks when create or execute rejects, while every existing
test still passes.

Two new tests pin the cleanup to the `finally`:

1. `stops the per-fork ToolRegistry even when AgentHeadless.create rejects`
   — make `AgentHeadless.create` return a rejected promise; assert
   the rejection propagates and the stop spy still fires once.
2. `stops the per-fork ToolRegistry even when headless.execute rejects`
   — return a headless object whose `execute` rejects; same shape.

Together with the success-path test these three cases cover every
exit edge of the AgentHeadless body.

`npx vitest run packages/core/src` — 269 files / 6994 passed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants