Skip to content

feat(web-shell): add opt-in interactive browser terminal - #9984

Merged
ytahdn merged 22 commits into
mainfrom
worktree-terminal-panel
Aug 28, 2026
Merged

feat(web-shell): add opt-in interactive browser terminal#9984
ytahdn merged 22 commits into
mainfrom
worktree-terminal-panel

Conversation

@ytahdn

@ytahdn ytahdn commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds a manually managed interactive terminal to the Web Shell right panel. The standalone Web Shell opts into the Terminal action, while the client also requires the daemon's web_terminal capability before showing it; this keeps separately released frontend and backend versions compatible, and embedded hosts that do not add the action see no new entry.

Each terminal tab owns an independent workspace-scoped PTY session. Switching tabs, hiding the panel, or reconnecting keeps the session alive and replays bounded scrollback plus exit state; explicitly closing the terminal tab releases and kills that PTY. Resize and release use control frames, while terminal input and output remain binary, preserving raw terminal data.

The daemon resolves every terminal against the live trusted workspace runtime and uses that runtime's cwd and effective environment. The WebSocket route shares the daemon's Host, Origin, authentication, and workspace trust checks. Sessions are capped globally, detached sessions are reclaimed after 15 minutes, workspace drain releases its terminals, and terminal startup removes the inherited npm prefix that otherwise makes nvm print a warning in development launches.

Why it's needed

The Web Shell previously had no manually managed interactive shell tied to the active workspace. Users need to run long-lived commands, interactive CLIs, and development processes without opening an external terminal, while retaining output and process state when they switch panels or briefly disconnect.

Reviewer Test Plan

How to verify

  1. Start the development daemon and open the standalone Web Shell. Open the right panel and confirm that Terminal appears in both the add menu and the empty-state actions.
  2. Open two terminal tabs. Confirm that each starts in the active workspace, accepts interactive input, and has independent content.
  3. Run an interactive CLI in one tab, switch to the other tab, then switch back. Confirm that the first process and screen remain intact.
  4. Resize the panel and browser window. Confirm that the PTY receives the new dimensions and the terminal remains interactive.
  5. Temporarily disconnect and reconnect the page. Confirm that scrollback and an already-exited process state replay once, without duplicated output or an input-eating frozen terminal.
  6. Close a terminal tab and confirm its PTY is released. Open another terminal afterward and confirm a new PTY can still be created.
  7. In an embedded Web Shell configuration, verify that the entry is hidden when either the Terminal action is omitted or the connected daemon lacks the web_terminal capability.

Evidence (Before & After)

Before: Web Shell had no interactive terminal surface. After: the right panel can host multiple independent terminal tabs backed by workspace PTYs.

Web Shell interactive terminal

Tested on

OS Status
🍏 macOS ✅ live daemon/browser and unit coverage
🪟 Windows ⚠️ not tested
🐧 Linux ⚠️ not tested

Environment (optional)

Verified with the development daemon and Vite Web Shell on macOS. Targeted registry, WebSocket route, capability, panel, and client lifecycle tests pass; full workspace type checking and build also pass.

Risk & Scope

  • Main risk or tradeoff: a detached terminal is killed after the 15-minute idle timeout even if its command is still running, preventing abandoned PTYs from living indefinitely.
  • Not validated / out of scope: Windows and Linux shell behavior, non-UTF-8 input from non-browser clients, and changing the resize behavior of third-party TUIs that do not correctly redraw themselves.
  • Breaking changes / migration notes: none. The capability is additive, and embedded hosts only expose the entry when they explicitly include the Terminal action.

Linked Issues

None.

中文说明

本 PR 做什么

在 Web Shell 右侧面板增加一个由用户手动管理的交互式终端。独立运行的 Web Shell 会显式加入 Terminal action,同时客户端还要求 daemon 返回 web_terminal capability 后才展示入口;这样前后端分开发布时仍可保持兼容,未加入该 action 的嵌入式宿主不会出现新入口。

每个终端页签拥有独立、按工作区隔离的 PTY 会话。切换页签、隐藏面板或重新连接时会话继续存活,并重放有界滚动内容及退出状态;用户明确关闭终端页签时则释放并终止对应 PTY。resize 和 release 使用控制帧,终端输入输出保持二进制传输,从而保留原始终端数据。

daemon 会把每个终端解析到当前存活且受信任的工作区运行时,并使用该运行时的 cwd 和生效环境。WebSocket 路由复用 daemon 的 Host、Origin、认证和工作区信任校验。终端会话有全局并发上限,脱离连接 15 分钟后自动回收,工作区排空时释放其全部终端;启动终端时还会移除继承的 npm prefix,避免开发启动链下 nvm 输出冲突警告。

为什么需要

Web Shell 此前没有绑定到当前工作区、由用户手动管理的交互式 Shell。用户需要在不打开外部终端的情况下运行长任务、交互式 CLI 和开发进程,同时在切换面板或短暂断连后保留输出与进程状态。

评审者验证计划

如何验证

  1. 启动开发 daemon 并打开独立运行的 Web Shell。打开右侧面板,确认添加菜单和空状态操作中都出现 Terminal。
  2. 打开两个终端页签,确认它们都从当前工作区启动、可以交互输入,并分别维护独立内容。
  3. 在一个页签运行交互式 CLI,切换到另一个页签后再切回来,确认第一个进程及其屏幕内容仍然完整。
  4. 调整面板和浏览器窗口大小,确认 PTY 收到新尺寸且终端仍可交互。
  5. 临时断开并重新连接页面,确认滚动内容和已退出进程的状态只重放一次,不产生重复输出,也不会出现终端冻结并静默吞输入。
  6. 关闭终端页签并确认对应 PTY 被释放;随后再次打开终端,确认仍可创建新的 PTY。
  7. 在嵌入式 Web Shell 配置中,分别省略 Terminal action 或连接到不含 web_terminal capability 的 daemon,确认两种情况下入口都不会展示。

前后对比证据

改动前:Web Shell 没有交互式终端界面。改动后:右侧面板可承载多个由工作区 PTY 支撑的独立终端页签。截图见上方。

测试环境

OS 状态
🍏 macOS ✅ 真实 daemon/浏览器及单元覆盖
🪟 Windows ⚠️ 未测试
🐧 Linux ⚠️ 未测试

环境(可选)

已在 macOS 上使用开发 daemon 和 Vite Web Shell 验证。针对 registry、WebSocket 路由、capability、面板和客户端生命周期的测试均通过;全仓类型检查和构建也通过。

风险与范围

  • 主要风险/权衡:终端脱离连接超过 15 分钟后,即使命令仍在运行也会被终止,以避免废弃 PTY 无限期存活。
  • 未验证/范围外:Windows 和 Linux Shell 行为、非浏览器客户端的非 UTF-8 输入,以及无法正确自行重绘的第三方 TUI 的 resize 行为。
  • 破坏性变更/迁移说明:无。capability 为增量新增,嵌入式宿主只有显式加入 Terminal action 才会展示入口。

关联 Issue

无。

Adds a browser terminal to the web-shell right panel, backed by shared node-pty sessions exposed through an authenticated /terminal WebSocket route on the serve daemon. The feature is opt-in (QWEN_WEB_TERMINAL=1 plus bearer auth) and gated behind a web_terminal capability so default deployments never expose the entry point.

Terminals are workspace-scoped: the daemon resolves the client workspace selector against the live registry, binds each PTY to that runtime's cwd and effective environment, and releases sessions when the workspace drains. Reconnects claim the same session id and replay bounded scrollback (including exit state) without duplicating output; controls resize/release ride text frames while PTY data stays binary. A session with no listeners is reclaimed after 15 minutes.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@ytahdn
ytahdn requested a review from jifeng August 25, 2026 06:39
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-run over the hardening rounds since the last pass (cc54771amain merge → f41be7be7dca447c), triggered by the author. Template ✓, no new gate concerns.

Problem: feature PR, so no bug reproduction applies. The gap it fills — the Web Shell had no interactive shell tied to the active workspace — is real and long-requested. Still no linked tracking issue; informational only.

Direction: unchanged and still aligned. The shipped gating contract (host right-panel action + web_terminal capability, itself conditional on the ACP HTTP surface + bearer auth + workspace trust) matches the description and the design doc. The one open product question is carried over from @wenshao's Linux verification: finding 3, no operator opt-out toggle for the PTY surface itself (he marked it a design question, not a blocker). That stays on the verdict below.

Size: now roughly 1.39k production-logic lines vs ~1.97k test lines (plus 21 doc lines, 52 NOTICES lines, lockfile churn). The core-path share is the new registry at 438 production lines. As a feat-type PR this is not size-blocked; the 1000+ split advisory applies, and the maintainer-awareness escalation for a core-touching feature of this size remains in force — informational, carried to the verdict.

Approach: every file still serves the feature, and the four new commits are exactly the kind this gate wants to see: focused fixes with named regression tests — release semantics for exited sessions, keyboard-event isolation from app shortcuts, PTY process-tree kill, input-budget accounting. No unrelated changes, no simpler path for the feature itself.

Risk: no elevated revert-risk paths matched. Branch is MERGEABLE.

Moving on to code review of the hardening rounds. 🔍

中文说明

针对上次审查之后的加固轮(cc54771amain 合并 → f41be7be7dca447c)的重新审查,由作者触发。模板 ✓,无新的门禁问题。

问题:功能 PR,不需要 bug 复现。它填补的空白——Web Shell 此前没有绑定当前工作区的交互式终端——真实且长期有需求。仍无关联跟踪 issue,仅供参考。

方向:不变且仍然对齐。实际交付的门控契约(宿主右侧面板 action + web_terminal 能力位(该能力位本身以 ACP HTTP 面启用为前提)+ bearer 认证 + 工作区信任)与描述和设计文档一致。唯一开放的产品问题沿用 @wenshao Linux 实测的问题 3:PTY 面本身缺少运维侧关闭开关(他当时标为设计问题而非阻断项),保留到最终结论。

规模:现约 1.39k 生产逻辑行约 1.97k 测试行(另有 21 行文档、52 行 NOTICES、lockfile 变更)。核心路径份额为新注册表的 438 行生产代码。作为 feat 类型不因规模阻断;1000+ 拆分建议适用,触及核心路径的该规模功能的维护者关注升级仍然有效——仅供参考,带入最终结论。

方案:所有文件仍服务于该功能,四个新提交正是门禁希望看到的形态:带点名回归测试的聚焦修复——已退出会话的释放语义、与应用快捷键隔离的键盘事件处理、PTY 进程树终止、输入预算记账。无无关改动,功能本身没有更简路径。

风险:未命中高回滚风险路径。分支可合并。

进入加固轮的代码审查。🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review — hardening rounds at 7dca447c

This pass reviews everything that landed since the last triage head (fdb8fbe): cc54771a, the main merge, f41be7be, and 7dca447c, plus a full re-read of the two daemon-side files at the reviewed head. Independent proposal first: for the outstanding items (exited-session cleanup, key-event isolation, process-tree kill, input-budget soundness) I would have done exactly what landed — replay-then-release for exits, data-web-terminal guards on the app's global key handlers, a ps-walked descendant kill before the process-group fallback, and byte-proportional credit instead of a full reset. The PR matches that; no simpler shape was missed.

The four round-1 Criticals remain fixed at this head — I re-verified each against the code, and @chiga0's independent cross-check on the same head reached the same conclusion:

  • Output fan-out backpressure: sendOutput checks bufferedAmount (now 8 MiB — raised from 1 MiB so a maximum 4 MiB scrollback replay plus live output fits) before every send; on overflow the listener cleans up and closes with retryable 1013.
  • Error listener window: ws.on('error') is the first statement of onConnection, before any await; there is no window with zero listeners.
  • Input budget: registry.write returns written / backpressure / unavailable; the boundary is exact-cap-inclusive and checked atomically before the PTY write; backpressure closes 1013 without releasing the session, so the client reconnects instead of losing the terminal.
  • Stale detach/reclaim: the detach closure and the reclaim timer both verify session identity before touching anything.

What the new commits add, verified:

  • Exitted sessions replay before release (7dca447c): a live PTY exit no longer releases immediately — the snapshot is preserved, a reconnect replays output + exit frame, and only then releases. This closes the last round-5 item (R3-4) and keeps wenshao's finding-1 fix intact; exited sessions also no longer count against the 8-session cap, with the 15-minute reclaim as the backstop.
  • Proportional input credit (7dca447c): PTY output now reduces the outstanding-input counter by the emitted byte count instead of zeroing it, and reattaching a listener no longer resets it — detach/reconnect cannot bypass the 256 KiB cap. This is the mitigation for chiga0's C3 question; note the residual tradeoff: a foreground program that produces no output at all (e.g. sleep 3600) still disconnects the client after 256 KiB of stdin — retryable, session preserved, but typed input over the budget is not delivered. Design confirmation, not a blocker.
  • Process-tree kill (7dca447c): killPtyTree now enumerates PPID descendants and PTY session members via ps, SIGKILLs children-first, then falls back to the process-group kill. Fixed argv, no shell interpolation. The author reports a real-zsh verification with a background process in its own PGID; that report is the author's claim — the mechanism reads correctly.
  • Transient workspace unavailability preserves the session (f41be7be): a resize/input message that finds the workspace momentarily gone closes 4002 without releasing, so the client can reconnect; a synthetic exit no longer races release during listener notification (listeners are iterated over a copy).
  • Release moved to workspace containment (cc54771a): releaseWebTerminalsForWorkspace now runs in the release/cleanup phase alongside git-state and scheduled-task cleanup instead of at drain start; daemon shutdown is covered by the registry's app-resource dispose. Combined with bypassPrimaryDrain: true this leaves one bounded window — a terminal created after containment runs keeps its PTY until the 15-minute reclaim, with every subsequent message re-validated against the workspace registry (4002 once the runtime is gone). Chiga0 flagged this as "probably acceptable, confirm intent"; carrying it as an open design confirmation.
  • Keyboard isolation completed (cc54771a + f41be7be): all global key handlers (btw shortcut, Ctrl+letter shortcuts, Escape in the composer/drawer/sidebar paths, vaul drawer dismiss) now skip events targeting [data-web-terminal], including Shadow-DOM composed events; covered by the App suite. The client also builds the WS URL from the configured daemon origin/base path, and the hidden terminal pane switched to display:none.

Residual scope disclosure: ArtifactPanel.tsx internals and App.tsx beyond the terminal tab/keyboard lifecycle were not re-reviewed at line depth this pass (they carry tests and were reviewed in earlier rounds); the client TerminalPanel.tsx is pinned by its 326-line suite. The ~60 remaining unresolved threads are all Suggestion-level (mutation-test expansions, contract-pin tests, helper dedup) and were explicitly deferred by the author under the PR convergence policy after five review rounds — recorded in-thread, consistent with the review-round guidance; nothing silently dropped.

sequenceDiagram
    participant P1 as Browser TerminalPanel
    participant P2 as Daemon WS upgrade gates
    participant P3 as Terminal route handler
    participant P4 as WebTerminalRegistry
    participant P5 as PTY shell
    P1->>P2: upgrade, terminalId and cwd selector, bearer subprotocol
    P2->>P2: Host, Origin, credential checks, drain bypass for reconnect
    P2->>P3: hand off upgraded socket
    P3->>P4: resolve selector to a trusted workspace runtime
    P3->>P4: create terminal or read snapshot
    P4->>P5: spawn shell in workspace cwd with runtime env
    P5-->>P1: binary output frames, bounded scrollback replayed on attach
    P1->>P3: text control frames for resize or release
    P3->>P4: release=1 handshake or exit replay releases the session
    P4->>P5: release kills the process tree, descendants first
Loading
Files changed (27 of 27 shown)
File What changed
docs/design/web-terminal-lifecycle.md Design doc on gating, ownership, reconnect, reload and idle reclaim
docs/developers/qwen-serve-protocol.md Lists the web_terminal capability
package-lock.json xterm dependency entries
packages/cli/src/serve/acp-http/index.ts bypassPrimaryDrain on ExtraWsRoute so self-managed routes skip the primary drain gate
packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts Drain-gate exemption and primary-scoped fallback tests
packages/cli/src/serve/capabilities.ts Registers web_terminal, conditional on the ACP HTTP surface
packages/cli/src/serve/routes/terminal.test.ts 25 route-level WebSocket lifecycle test blocks incl. all hardening regressions
packages/cli/src/serve/routes/terminal.ts The /terminal WS route, control framing, release handshake, backpressure guards, heartbeat
packages/cli/src/serve/run-qwen-serve.ts Stops the registry on shutdown, releases terminals in the workspace containment phase
packages/cli/src/serve/server.test.ts Pins web_terminal as advertised only with acpHttpEnabled
packages/cli/src/serve/server.ts Creates the registry, registers the route with a trust-checked workspace resolver
packages/core/src/index.ts Exports the new registry
packages/core/src/services/web-terminal-registry.test.ts Registry lifecycle, race, budget and reclaim tests incl. stale-detach guard
packages/core/src/services/web-terminal-registry.ts PTY session registry with caps, bounded scrollback, proportional input budget, process-tree kill, idle reclaim
packages/vscode-ide-companion/NOTICES.txt Regenerated notices for the two new @XTerm packages
packages/web-shell/client/App.test.tsx Terminal entry gating, release on tab close, keyboard-isolation tests
packages/web-shell/client/App.tsx Opens terminal tabs, releases on close and eviction, data-web-terminal key guards
packages/web-shell/client/components/artifacts/ArtifactPanel.module.css Terminal pane styles incl. display none when hidden
packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx Add-menu and empty-state terminal entries
packages/web-shell/client/components/artifacts/ArtifactPanel.tsx Terminal tab kind, add-menu item, empty-state action, active state
packages/web-shell/client/components/terminal/TerminalPanel.test.tsx Client framing, reconnect, release-retry, origin and focus tests
packages/web-shell/client/components/terminal/TerminalPanel.tsx xterm panel with reconnect backoff, release handshake, localized notices
packages/web-shell/client/customization.tsx Adds terminal to the right-panel item type
packages/web-shell/client/i18n.tsx Terminal strings in EN and ZH
packages/web-shell/client/main.tsx Terminal in the standalone app default right panel
packages/web-shell/package.json Adds @xterm/xterm and @xterm/addon-fit
packages/web-shell/vite.config.ts Dev proxy forwards the /terminal WebSocket to the daemon

Test evidence

Unattended CI run — no PR code was built or executed here; the evidence below is the PR's own CI signal for the reviewed commit, fetched through the GitHub API. All five pull_request-event workflow runs on 7dca447c completed successfully, including the full Test (ubuntu-latest, Node 22.x) suite and Serve A/B. Test (macos-latest) and Test (windows-latest) show skipped — that is routing, not failure: those lanes were taken off PR events by #10059, which this branch already carries. Integration Tests (CLI, No Sandbox) is also skipped on this head — its qwen-serve coverage does not include this route, and the terminal paths are pinned by the 25 route test blocks and 19 registry tests instead; naming it so the gap is explicit.

Check Conclusion
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success
Classify PR ✅ success
Dependency CVE audit ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success
Real daemon E2E / Java 11 ✅ success
Secret scan (TruffleHog) ✅ success
Serve A/B (ubuntu-latest, Node 22.x) ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success
macos-latest / Java 21 ✅ success
ubuntu-latest / Java 11 ✅ success
ubuntu-latest / Java 17 ✅ success
ubuntu-latest / Java 21 ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
windows-latest / Java 21 ✅ success

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

Not verified here (unattended run): the live browser flow at this head — open, type, tab-switch, resize, reconnect replay, release handshake, and the new replay-then-release exit path. Each is unit-pinned at this head; @wenshao's full real-daemon + real-browser verification covered the entire reviewer test plan on Linux but predates all four hardening commits, and the author's self-reported live re-tests since are their claim, not evidence in this thread.

Sandboxed verification would settle this: @qwen-code /tmux — the terminal lifecycle (open → type → switch → resize → reconnect replay → close releases the PTY) is the PR's central behavioural claim and is only unit-pinned at this head; the author has write access, so the lane is available. @qwen-code /verify would add the A/B load-bearing proof for the daemon-side budget and release semantics.

中文说明

代码审查 —— 7dca447c 上的加固轮

本轮审查上次三查头(fdb8fbe)之后落地的全部改动:cc54771amain 合并、f41be7be7dca447c,并在审查头上完整重读了两个守护进程侧文件。独立方案先行:对遗留项(已退出会话清理、键盘事件隔离、进程树终止、输入预算健全性),我会做的正是落地的这些——退出先重放再释放、以 data-web-terminal 守护应用全局按键处理、ps 遍历后代进程后先杀子进程再回退进程组杀、按字节比例抵扣而非全额清零。PR 与之吻合,没有遗漏更简形态。

第一轮 4 个 Critical 在该头上仍然成立——我逐一对代码复核,@chiga0 在同一头上的独立核对结论一致:输出扇出背压(每次发送前检查 bufferedAmount,现为 8 MiB——自 1 MiB 上调,使 4 MiB 满滚动重放与实时输出可共存,超限清理并以可重试 1013 关闭);错误监听窗口(ws.on('error')onConnection 首条语句,先于任何 await);输入预算(三态返回、含上限边界原子检查,背压以 1013 关闭且不释放会话,客户端可重连);过期 detach/回收(detach 闭包与回收定时器均先校验会话身份)。

新提交的内容(已核实):已退出会话先重放再释放(7dca447c——实时 PTY 退出不再立即释放,快照保留,重连重放输出与退出帧后才释放;收口 round-5 的 R3-4,且与问题 1 的修复相容;已退出会话不再占用 8 个名额,15 分钟回收兜底);输入预算按比例抵扣(7dca447c——输出按字节数抵扣未确认输入而非清零,重新挂载监听不再重置预算,断连重连不能绕过 256 KiB 上限;残留权衡:完全无输出的前台程序在 256 KiB stdin 后仍会断开客户端——可重试、会话保留,但超预算输入不会送达;属设计确认而非阻断);进程树终止(7dca447c——先按 PPID 后代与 PTY 会话成员枚举、先子后父 SIGKILL,再回退进程组杀;固定参数无 shell 注入;作者报告的真实 zsh 后台进程验证是其陈述,机制本身读来正确);瞬时工作区不可用保留会话(f41be7be——resize/输入时发现工作区暂不可用以 4002 关闭但不释放;退出通知改为遍历副本,消除通知中释放的竞态);释放移至工作区收容阶段(cc54771a——与 git-state、计划任务清理同阶段执行,守护进程关停由注册表的资源释放兜底;与 bypassPrimaryDrain: true 组合遗留一个有界窗口——收容之后创建的终端在 15 分钟回收前保活,且后续每条消息都重新校验工作区注册表;chiga0 判断"可接受、需确认意图",作为开放设计确认带入结论);键盘隔离补全(cc54771a + f41be7be——全部全局按键处理器对 [data-web-terminal] 目标(含 Shadow DOM composed 事件)放行,App 套件覆盖;客户端按配置的 daemon origin/基础路径构造 WS URL;隐藏面板改为 display:none)。

残留范围披露:本轮未逐行复审 ArtifactPanel.tsx 内部与 App.tsx 的终端页签/键盘生命周期之外的部分(有测试覆盖且早前轮已审);客户端 TerminalPanel.tsx 由其 326 行套件固化。约 60 个未解决线程全部为 Suggestion 级(变异测试扩展、契约固化测试、辅助函数去重),作者已按五轮审查后的 PR 收敛策略明确延期——线程内均有记录,符合审查轮次指引,无静默丢弃。

测试证据

无人值守 CI 运行——此处未构建或执行任何 PR 代码;以上是审查提交上、通过 GitHub API 获取的 PR 自身 CI 信号。7dca447c 上全部 5 个 pull_request 事件工作流运行成功,含完整 Test (ubuntu-latest, Node 22.x) 套件与 Serve A/BTest (macos-latest)Test (windows-latest) 显示 skipped——属路由而非失败:该两通道已由 #10059 移出 PR 事件,本分支已携带该变更。Integration Tests (CLI, No Sandbox) 在该头上亦为 skipped——其 qwen-serve 覆盖不含本路由,终端路径由 25 个路由测试块与 19 个注册表测试固化;如实列出以明确该缺口。此处未验证(无人值守运行):该头上的真实浏览器流程——打开、输入、切换页签、调整尺寸、重连重放、释放握手与新的"重放后释放"退出路径。各项均有单测固化;@wenshao 的完整真实 daemon + 真实浏览器验证(Linux,覆盖全部验证计划)早于四个加固提交,作者此后自报的实测是其陈述,不是本线程的证据。沙箱验证可以定论:@qwen-code /tmux——终端生命周期(打开 → 输入 → 切换 → 调整尺寸 → 重连重放 → 关闭释放 PTY)是本 PR 的核心行为主张且在该头上仅有单测固化;作者有写权限,该通道可用。@qwen-code /verify 可补充守护进程侧预算与释放语义的 A/B 承重证明。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 3/5 — cleanest this PR has ever looked: every Critical from five review rounds is fixed and test-pinned at this head, an independent human cross-check found no blockers, and CI is fully green — but the standing maintainer-awareness escalation for a ~1.4k-production-line feature touching core caps the verdict, and two design confirmations stay open. The cap is policy, not doubt.

Stepping back: since the last defer this PR went strictly in the right direction. The four fix commits are each a named defect closed by a named regression test — replay-then-release for exited sessions, key-event isolation across every global handler including Shadow DOM, a descendants-first process-tree kill, proportional input-budget credit that a detach/reconnect can no longer bypass. @chiga0's cross-check on this exact head refuted all four round-1 Criticals independently of my read, and the two questions he left (the drain-bypass creation window, the silent-stdin-consumer UX at the 256 KiB budget) are design confirmations with bounded worst cases, not defects. The author also held the line on scope: the ~60 surviving threads are Suggestion-level and were deferred under the review-round convergence policy with the rationale recorded in-thread — that is the documented posture after five rounds, not silent drop. If the question were "is this code ready to merge?", the answer is yes.

Three things keep this out of an auto-approve. First, policy: a feat touching packages/core services at ~1.39k production lines carries the standing Stage 0 maintainer-awareness escalation, and escalated PRs defer regardless of how clean the re-run reads. Second, process: the PR's CHANGES_REQUESTED state comes from this bot's own /review rounds; the latest of those (round 5, on f41be7be) predates 7dca447c, which addresses its remaining items per the author's replies — verified above — so that review needs dismissing or re-review before branch protection will allow a merge anyway. Third, product: wenshao's finding 3 (no operator opt-out toggle for a PTY surface that bypasses approval mode and tool permissions by construction) remains a maintainer call, and chiga0's two confirmations want an owner's sentence each.

⏸️ Deferring to @wenshao and @qqqys — three human actions, all small: (1) sign off on (or lift) the standing maintainer-awareness escalation for this core-touching feature; (2) dismiss or re-review the stale round-5 CHANGES_REQUESTED review, whose outstanding items are addressed at this head; (3) one line each on the opt-out-toggle question and chiga0's two confirmations (drain-bypass creation window; silent-stdin budget UX). Branch is MERGEABLE, CI is green on 7dca447c, and @qwen-code /tmux or /verify remain available if live-behavior evidence is wanted before sign-off.

中文说明

置信度:3/5 —— 本 PR 迄今为止最干净的状态:五轮审查中的每个 Critical 均已修复并在该头上以测试固化,独立的人工交叉核对未发现阻断项,CI 全绿——但对触及核心、约 1.4k 生产行功能的既有维护者关注升级给结论封顶,且仍有两项设计确认开放。封顶是政策,不是疑虑。

退一步看:自上次转交以来,本 PR 严格向好。四个修复提交各自以点名的回归测试关闭一个点名的缺陷——已退出会话的重放后释放、覆盖全部全局按键处理器(含 Shadow DOM)的键盘事件隔离、先子后父的进程树终止、断连重连无法再绕过的按比例输入预算抵扣。@chiga0 在同一头上的交叉核对独立于我的阅读推翻了全部 4 个第一轮 Critical,他留下的两个问题(排空旁路下的创建窗口、256 KiB 预算下静默消费 stdin 的交互模型)是坏情形有界的设计确认,不是缺陷。作者也在范围上守住了边界:约 60 个存活线程均为 Suggestion 级,按五轮后的审查收敛策略延期,且线程内记录了理由——这是有文档依据的姿态,不是静默丢弃。若问题是"这份代码可以合并了吗",答案是肯定的。

三件事使其不走自动批准。其一,政策:触及 packages/core services、约 1.39k 生产行的 feat 带有既定的 Stage 0 维护者关注升级,升级的 PR 无论重审多干净都转交。其二,流程:当前 CHANGES_REQUESTED 状态来自本机器人的 /review 轮;最新一轮(第 5 轮,针对 f41be7be)早于 7dca447c,而其遗留项按作者回复已被该提交解决——上文已核实——该审查需要被 dismiss 或重审,分支保护才会放行。其三,产品:wenshao 的问题 3(对按构造绕过审批模式与工具权限的 PTY 面,缺少运维侧关闭开关)仍是维护者判断,chiga0 的两项确认也各需负责人一句话。

⏸️ 转交 @wenshao@qqqys——三项人工动作,都很小:(1)对该触及核心的功能给出(或解除)维护者关注签核;(2)dismiss 或重审过时的第 5 轮 CHANGES_REQUESTED 审查,其遗留项在该头上已解决;(3)对开关问题与 chiga0 的两项确认(排空旁路创建窗口、静默 stdin 预算交互)各给一句结论。分支可合并,7dca447c 上 CI 全绿;如需签核前的实时行为证据,@qwen-code /tmux/verify 仍可用。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

Rendered against a mock daemon (no real backend): the PR base vs this PR head da212e5. Only screenshots that changed are shown (flows below, if any, are head-only) — refreshes on every push.

Screenshots · before / after

⚠️ No preview: one or more scenarios failed to render on this head — see the workflow run. This is not "no visual change" — a scenario that times out or throws produces no image. Fix the failing scenario (or a genuine regression it caught) and the preview returns on the next push.

Full-resolution recordings (.webm) are attached to the workflow run.

Qwen Code · web-shell visuals

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

Built the PR base vs this PR head da212e5, drove a fixed endpoint set against each, and diffed the JSON responses. Only fields that changed are shown.

No response changes against the PR base across 12 scenario(s).

Qwen Code · serve A/B

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 85.63% 85.63% 91.04% 84.56%
Core 88.74% 88.74% 90.51% 87.2%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   85.63 |    84.56 |   91.04 |   85.63 |                   
 src               |   86.45 |    82.24 |   88.23 |   86.45 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  llm.tsx          |   73.22 |    77.73 |   80.76 |   73.22 | ...1345-1349,1476 
  ...ractiveCli.ts |   89.27 |    83.13 |   89.06 |   89.27 | ...3157,3163,3229 
  ...liCommands.ts |   89.71 |    84.17 |   81.81 |   89.71 | ...31-633,650,757 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   74.57 |    77.36 |   93.65 |   74.57 |                   
  acpAgent.ts      |   73.63 |    77.23 |   92.93 |   73.63 | ...02,13080-13081 
  ...k-reporter.ts |     100 |       80 |     100 |     100 | 81,84,119,141     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  ...heap-probe.ts |   97.39 |    96.66 |     100 |   97.39 | 243,264-265       
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |     87.5 |     100 |     100 | 17,28             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...figuration.ts |     100 |    89.65 |     100 |     100 | 79,125,142        
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
  ...ersistence.ts |   94.95 |    92.24 |     100 |   94.95 | ...13-118,227-228 
  ...management.ts |   74.75 |     66.3 |     100 |   74.75 | ...92-496,505-509 
  ...e-download.ts |    64.7 |    62.24 |    87.5 |    64.7 | ...08-609,615-619 
 ...tegration/live |    97.5 |       88 |   92.85 |    97.5 |                   
  ...en-context.ts |   95.74 |    82.35 |     100 |   95.74 | ...0,66-67,99-100 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...ak-to-user.ts |   96.66 |      100 |    87.5 |   96.66 | 37-38             
  ...task-tools.ts |   98.97 |      100 |   88.88 |   98.97 | 201-202           
 ...ration/service |    97.1 |    95.89 |   93.75 |    97.1 |                   
  filesystem.ts    |    97.1 |    95.89 |   93.75 |    97.1 | ...22-123,246-247 
 ...ration/session |    90.9 |    86.48 |   95.67 |    90.9 |                   
  Session.ts       |   90.27 |    85.23 |   95.03 |   90.27 | ...85,13212-13216 
  ...entTracker.ts |   96.88 |    89.36 |      90 |   96.88 | 139-145,224       
  ...projection.ts |   98.85 |    91.59 |     100 |   98.85 | 234,250,262       
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   94.19 |    86.53 |     100 |   94.19 | ...53,357,437,441 
  ...y-replayer.ts |   83.41 |    93.33 |   94.11 |   83.41 | ...30-148,266-268 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.19 |     87.8 |     100 |   89.19 | ...85-304,363-365 
  ...oal-update.ts |   98.61 |    97.29 |     100 |   98.61 | 64                
  ...lure-guard.ts |   98.32 |    97.72 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.65 |    92.34 |   97.14 |   95.65 |                   
  ...ageEmitter.ts |   95.36 |    92.42 |     100 |   95.36 | ...16,129-130,223 
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  base-emitter.ts  |   78.26 |    77.77 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   98.57 |    94.84 |     100 |   98.57 | 75-76,394-395     
 ...ession/rewrite |   96.03 |    89.79 |   94.44 |   96.03 |                   
  LlmRewriter.ts   |   94.01 |    88.23 |     100 |   94.01 | 101-102,179-183   
  ...Middleware.ts |   96.99 |    88.37 |     100 |   96.99 | 145,153-155       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/agent-view    |   86.63 |     80.8 |   94.01 |   86.63 |                   
  attach-lease.ts  |     100 |    97.05 |     100 |     100 | 173               
  ...t-cli-argv.ts |     100 |     92.3 |     100 |     100 | 15                
  ...ged-detach.ts |     100 |     90.9 |     100 |     100 | 40,64             
  presentation.ts  |   94.13 |    88.72 |   94.73 |   94.13 | ...57-358,382-384 
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  pty-host-env.ts  |     100 |      100 |     100 |     100 |                   
  ...st-process.ts |   88.43 |    78.79 |   94.44 |   88.43 | ...1294,1384-1386 
  pty-host.ts      |   85.25 |    87.03 |   90.69 |   85.25 | ...22-524,539-540 
  ...sor-client.ts |   80.38 |    72.81 |   77.41 |   80.38 | ...22-626,652-656 
  ...r-dispatch.ts |      98 |    85.18 |     100 |      98 | 117,173,190       
  ...or-process.ts |    83.5 |     77.3 |   98.72 |    83.5 | ...4479-4482,4485 
  ...sor-runner.ts |   82.43 |    76.82 |   80.95 |   82.43 | ...69,493,496-506 
  ...sor-server.ts |   84.39 |    83.56 |    93.1 |   84.39 | ...67-568,571-588 
  ...isor-store.ts |   94.76 |    84.95 |     100 |   94.76 | ...,966,1008,1023 
  ...nal-bridge.ts |   93.98 |    91.54 |   83.33 |   93.98 | 228-238           
  ...r-sideband.ts |   94.91 |    89.36 |     100 |   94.91 | ...75-276,299-304 
 src/commands      |   90.66 |    78.53 |   65.62 |   90.66 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.85 |      100 |      50 |   98.85 | 98                
  serve.ts         |   89.46 |    76.02 |     100 |   89.46 | ...12-915,927,938 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   89.55 |    88.76 |   90.68 |   89.55 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   94.78 |    94.59 |      90 |   94.78 | ...32-335,380-383 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   96.84 |    96.22 |     100 |   96.84 | ...40-245,303-306 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   94.07 |    85.96 |   94.33 |   94.07 | ...1292,1299-1300 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.53 |    96.66 |     100 |   98.53 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    87.7 |    83.63 |      88 |    87.7 | ...95,601-604,616 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.85 |    87.91 |   87.09 |   88.85 |                   
  consent.ts       |   72.53 |    90.32 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     90.9 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |   75.63 |    57.14 |     100 |   75.63 | ...30-134,136-140 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   91.19 |    88.76 |   85.71 |   91.19 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |    92.9 |    84.84 |      80 |    92.9 | ...79-181,199-200 
  reconnect.ts     |   85.54 |    86.76 |    90.9 |   85.54 | 45-58,337-359     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   91.96 |     90.4 |   93.34 |   91.96 |                   
  agent-prompt.ts  |   94.89 |    92.99 |   97.95 |   94.89 | ...3289,3624-3704 
  base-tree.ts     |   77.02 |    80.76 |   77.77 |   77.02 | ...63-384,386-399 
  capture-local.ts |   94.72 |    97.61 |   94.11 |   94.72 | 271,1336-1374     
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   92.34 |     89.5 |    90.9 |   92.34 | ...1107,1109-1110 
  comment-body.ts  |   67.85 |    87.09 |   66.66 |   67.85 | ...30,157,159-164 
  ...ent-status.ts |   94.22 |    87.32 |    90.9 |   94.22 | ...96,462,738-758 
  ...ose-review.ts |   97.19 |    93.71 |   98.61 |   97.19 | ...6196-6240,6515 
  cost-ledger.ts   |   94.58 |     94.4 |   81.25 |   94.58 | ...53-654,694-704 
  drive.ts         |    94.1 |    92.85 |   92.85 |    94.1 | ...80-782,787-789 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-diff.ts    |   73.75 |      100 |   66.66 |   73.75 | 77-97             
  fetch-pr.ts      |   97.29 |    92.25 |     100 |   97.29 | ...1566,1724-1729 
  findings.ts      |   96.13 |    92.32 |     100 |   96.13 | ...1316,1325-1326 
  issue-context.ts |   88.15 |     93.1 |   85.71 |   88.15 | 249-276           
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.55 |     92.3 |   66.66 |   85.55 | 74-79,144-150     
  meta.ts          |   79.43 |    93.75 |   66.66 |   79.43 | 123-128,147-162   
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.48 |    95.74 |     100 |   99.48 | 664,989,1045,1081 
  plan-diff.ts     |   71.42 |      100 |   66.66 |   71.42 | 162-197           
  pr-context.ts    |   96.43 |    88.62 |     100 |   96.43 | ...2483,2584-2600 
  presubmit.ts     |   94.32 |    90.83 |   94.11 |   94.32 | ...1214,1249-1280 
  ...ish-assets.ts |    81.3 |    82.22 |   85.71 |    81.3 | ...75-479,506-552 
  ...r-findings.ts |   90.74 |    83.75 |     100 |   90.74 | ...17-422,429-430 
  repo-context.ts  |   94.62 |    90.75 |     100 |   94.62 | ...66-467,482-487 
  ...ve-anchors.ts |   78.34 |    89.28 |      75 |   78.34 | ...83-188,200-217 
  run.ts           |   84.47 |    87.58 |   95.45 |   84.47 | ...00,816-870,884 
  save-artifact.ts |    94.2 |    92.46 |   94.11 |    94.2 | ...14-617,710-713 
  scratch-tree.ts  |   95.93 |       86 |     100 |   95.93 | ...91-392,461-464 
  script-lint.ts   |   81.27 |    79.38 |   88.88 |   81.27 | ...69-783,785-807 
  submit.ts        |   94.13 |    89.45 |   94.44 |   94.13 | ...1695,1723-1760 
  test-delta.ts    |   95.75 |     92.3 |      75 |   95.75 | 470-478           
  test-efficacy.ts |   84.03 |    80.48 |   96.07 |   84.03 | ...3249,3257-3277 
  test-plan.ts     |   94.61 |    91.79 |      95 |   94.61 | ...29-832,873-874 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |   97.33 |    94.61 |   98.67 |   97.33 |                   
  agent-briefs.ts  |   99.08 |      100 |      50 |   99.08 | 824-825           
  ...t-identity.ts |     100 |      100 |     100 |     100 |                   
  anchors.ts       |     100 |    97.04 |     100 |     100 | ...39,175,184,231 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  audit-layers.ts  |   98.67 |    96.15 |     100 |   98.67 | 288-290           
  authorization.ts |    96.5 |    95.61 |     100 |    96.5 | ...54-255,629-630 
  budget.ts        |     100 |    97.95 |     100 |     100 | 887,940           
  build-budget.ts  |     100 |      100 |     100 |     100 |                   
  certification.ts |     100 |      100 |     100 |     100 |                   
  convergence.ts   |     100 |    97.94 |    92.3 |     100 | 52,514,619,715    
  coverage.ts      |   98.97 |    95.11 |     100 |   98.97 | ...1103,1648-1649 
  deadline.ts      |   98.03 |    91.66 |     100 |   98.03 | ...20,752,820,837 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 75                
  diff-plan.ts     |   98.81 |    93.65 |     100 |   98.81 | ...78,301,327-328 
  disk.ts          |     100 |      100 |     100 |     100 |                   
  effort.ts        |     100 |      100 |     100 |     100 |                   
  failing-files.ts |     100 |    93.33 |     100 |     100 | 41                
  gh.ts            |   89.53 |    95.52 |   78.94 |   89.53 | ...47,384-385,412 
  git.ts           |   96.92 |    94.11 |     100 |   96.92 | 264-265,302-303   
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  import-graph.ts  |   96.68 |     95.6 |     100 |   96.68 | 180-182,211-212   
  ...ntal-scope.ts |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ...audit-gate.ts |     100 |     97.5 |     100 |     100 | 135               
  ledger.ts        |     100 |    99.42 |     100 |     100 | 788               
  local-anchor.ts  |   93.78 |    88.75 |     100 |   93.78 | ...61,594-595,745 
  local-diff.ts    |   86.77 |    94.28 |     100 |   86.77 | ...54-564,566-574 
  ...ry-context.ts |   96.61 |    95.48 |     100 |   96.61 | ...47-450,496-499 
  md-field.ts      |     100 |      100 |     100 |     100 |                   
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  narrow-diff.ts   |     100 |      100 |     100 |     100 |                   
  npm-toolchain.ts |   98.23 |    95.29 |     100 |   98.23 | ...,822,1203,1220 
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   98.05 |    88.57 |     100 |   98.05 | 33-34             
  prompt-record.ts |   98.03 |    94.23 |     100 |   98.03 | 293-294,300       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   98.03 |    94.73 |     100 |   98.03 | 109-110           
  report.ts        |   92.92 |    86.66 |     100 |   92.92 | 213-214,216-220   
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 187               
  resume.ts        |     100 |      100 |     100 |     100 |                   
  retirement.ts    |     100 |    94.36 |     100 |     100 | ...58-559,760,917 
  review-footer.ts |   99.55 |    98.09 |     100 |   99.55 | 548-549           
  ...w-settings.ts |     100 |    96.42 |     100 |     100 | 99                
  roster.ts        |     100 |    97.14 |     100 |     100 | 177,222           
  round-model.ts   |     100 |      100 |     100 |     100 |                   
  run-ledger.ts    |    98.2 |    93.87 |     100 |    98.2 | ...23,541,647,670 
  same-file.ts     |     100 |       95 |     100 |     100 | 36                
  ...boxed-exec.ts |   94.26 |    89.32 |   95.65 |   94.26 | ...49-550,728-729 
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.18 |    94.04 |     100 |   98.18 | 431,472,512-513   
  test-utils.ts    |   99.04 |    91.66 |     100 |   99.04 | 75                
  toolchain.ts     |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   98.09 |    95.07 |     100 |   98.09 | ...92,438,707-708 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 186               
  workspaces.ts    |     100 |    96.85 |     100 |     100 | 222,452,499,512   
  ...ree-reader.ts |     100 |      100 |     100 |     100 |                   
  worktree.ts      |   89.39 |    81.78 |     100 |   89.39 | ...1813-1814,1827 
 ...w/lib/platform |   94.71 |    87.89 |   97.05 |   94.71 |                   
  aone-client.ts   |   94.94 |     87.3 |     100 |   94.94 | ...92-293,299-302 
  aone.ts          |   93.06 |    89.86 |   94.73 |   93.06 | ...34,598-603,655 
  github.ts        |   99.08 |     75.8 |     100 |   99.08 | 249-250           
  registry.ts      |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...mands/sessions |   94.11 |    89.06 |   89.47 |   94.11 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
  ps.ts            |     100 |    94.44 |     100 |     100 | 58                
 src/config        |   94.26 |    90.56 |   95.02 |   94.26 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.36 |    88.37 |     100 |   93.36 | ...06-307,330-331 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   89.62 |    91.05 |   83.78 |   89.62 | ...2515,2517-2525 
  ...cy-monitor.ts |      90 |    77.27 |     100 |      90 | ...72-73,90-92,98 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  environment.ts   |   94.51 |    92.55 |   95.23 |   94.51 | ...24-625,679-680 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |    97.4 |       50 |     100 |    97.4 | 240-243           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.87 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   78.57 |       92 |   86.66 |   78.57 | ...18-319,324-326 
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.93 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.16 |    93.02 |      90 |   91.16 | ...1026,1028-1029 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  settingsUtils.ts |   80.92 |     89.2 |   85.18 |   80.92 | ...87-605,612-620 
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.54 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    78.94 |   85.71 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |       80 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |   75.08 |    67.64 |   71.42 |   75.08 |                   
  ...tputBridge.ts |   75.33 |    68.18 |   73.68 |   75.33 | ...09-410,418-421 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   89.68 |    88.66 |   93.02 |   89.68 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languageUtils.ts |   98.88 |    97.01 |     100 |   98.88 | 184-185           
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   87.37 |    83.73 |   89.32 |   87.37 |                   
  ...ng-failure.ts |     100 |      100 |     100 |     100 |                   
  ...iveHelpers.ts |   94.95 |    91.05 |     100 |   94.95 | ...30-431,529,542 
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  ...iagnostics.ts |    95.8 |     87.5 |   93.75 |    95.8 | ...03,277-278,289 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...33-634,637-638 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |   57.47 |     66.3 |   73.68 |   57.47 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   70.04 |    62.92 |   91.66 |   70.04 | ...11-620,635-640 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   53.96 |    67.08 |   66.66 |   53.96 | ...78-690,699-728 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.18 |    94.11 |   95.34 |   98.18 |                   
  ...putAdapter.ts |   98.07 |    93.21 |   98.11 |   98.07 | ...1448,1464-1465 
  ...putAdapter.ts |   96.22 |    91.66 |   85.71 |   96.22 | 52-53             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.51 |      100 |   90.47 |   98.51 | 90-91,131-132     
  ...projection.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/peerMessaging |   90.64 |    85.29 |      96 |   90.64 |                   
  ...ngContext.tsx |     100 |      100 |     100 |     100 |                   
  ...-messaging.ts |   90.45 |    85.07 |   95.83 |   90.45 | ...01-306,347-352 
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/runtime       |    99.7 |    96.32 |     100 |    99.7 |                   
  ...livery-ipc.ts |     100 |    91.17 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   87.42 |    84.97 |   90.73 |   87.42 |                   
  ...extra-args.ts |     100 |      100 |     100 |     100 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.99 |     91.5 |     100 |   93.99 | ...29-430,433-435 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.18 |     100 |     100 | 717               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.54 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.98 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   89.61 |    94.37 |   96.55 |   89.61 | ...64-276,528-531 
  ...ebhook-ipc.ts |    98.5 |     87.5 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.32 |    85.33 |     100 |   87.32 | ...14,820-824,842 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...horization.ts |     100 |      100 |     100 |     100 |                   
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   93.24 |    85.42 |    97.4 |   93.24 | ...1765,1819-1823 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |   90.75 |    80.47 |   94.73 |   90.75 | ...1091,1112-1117 
  ...tree-guard.ts |   93.87 |    89.81 |     100 |   93.87 | ...3227,3297-3301 
  daemon-logger.ts |   82.82 |    78.68 |   92.04 |   82.82 | ...1775,1802-1808 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.69 |    91.96 |     100 |   98.69 | ...1590,1592-1593 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    87.09 |     100 |   92.06 | ...72,287-293,316 
  ...h-settings.ts |   94.94 |    90.45 |     100 |   94.94 | ...30,708,724,734 
  fast-path.ts     |   91.38 |       82 |   95.45 |   91.38 | ...46-555,633-634 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-149             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |   91.58 |    86.48 |     100 |   91.58 | ...44-145,156-157 
  ...pp-sandbox.ts |   96.72 |    95.23 |     100 |   96.72 | 41-42             
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...-with-auth.ts |     100 |      100 |     100 |     100 |                   
  ...ate-blocks.ts |   99.03 |    94.73 |     100 |   99.03 | 133               
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  ...nal-ledger.ts |    94.9 |    84.78 |     100 |    94.9 | ...81,302,361-362 
  rate-limit.ts    |   92.68 |    88.29 |     100 |   92.68 | ...89-291,303-305 
  ...qwen-serve.ts |   84.69 |    81.39 |   76.99 |   84.69 | ...9116,9134-9138 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.52 |    59.42 |   76.92 |   45.52 | ...1050,1062-1085 
  ...-keepalive.ts |   94.31 |    88.28 |     100 |   94.31 | ...37,541-542,581 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  ...-lifecycle.ts |   89.16 |    90.29 |   86.95 |   89.16 | ...24-325,330-334 
  serve-token.ts   |     100 |      100 |     100 |     100 |                   
  server.ts        |   89.07 |    91.03 |   70.31 |   89.07 | ...3165,3196-3197 
  ...-admission.ts |   99.13 |    95.94 |     100 |   99.13 | 308-309           
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...-redaction.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.72 |    77.93 |     100 |   93.72 | ...51,854,867-869 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   93.45 |    86.88 |     100 |   93.45 | ...77-280,323-326 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.63 |       80 |     100 |   98.63 | 108,136,186,189   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   94.09 |    90.57 |     100 |   94.09 | ...90-591,598-599 
  ...e-remember.ts |   98.23 |    92.56 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   89.88 |     90.9 |     100 |   89.88 | ...05-206,274-295 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...visibility.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.83 |   96.15 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.09 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |    80.4 |    80.03 |   94.53 |    80.4 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |   93.03 |    84.13 |   98.52 |   93.03 | ...1624,1671-1682 
  dispatch.ts      |   75.71 |    76.82 |   93.44 |   75.71 | ...5649,5706-5712 
  index.ts         |   82.81 |    79.92 |   91.22 |   82.81 | ...2434,2520-2521 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  ...ach-budget.ts |     100 |      100 |     100 |     100 |                   
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   98.26 |    88.75 |     100 |   98.26 | 87-88,117         
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   94.06 |    89.09 |     100 |   94.06 | 50,55,134,138-141 
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 .../conversations |   86.32 |    78.75 |   93.33 |   86.32 |                   
  ...e-activity.ts |     100 |      100 |     100 |     100 |                   
  ...ime-errors.ts |     100 |      100 |     100 |     100 |                   
  ...me-manager.ts |   97.88 |    94.91 |     100 |   97.88 | 64-65,92          
  ...-ownership.ts |   87.33 |    83.75 |   88.46 |   87.33 | ...57-558,601-602 
  ...-workspace.ts |   89.21 |    76.37 |     100 |   89.21 | ...52-554,568-572 
  ...on-journal.ts |   91.69 |    80.86 |     100 |   91.69 | ...46-747,753-755 
  ...on-service.ts |   83.22 |    75.11 |   89.01 |   83.22 | ...3014,3023-3025 
 src/serve/fs      |   87.77 |    82.34 |     100 |   87.77 |                   
  audit.ts         |     100 |    96.29 |     100 |     100 | 211               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |    74.01 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.52 |    89.18 |     100 |   90.52 | 172-180           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   88.02 |    81.85 |     100 |   88.02 | ...3027,3037-3038 
 src/serve/live    |    76.6 |    70.54 |    90.2 |    76.6 |                   
  discovery.ts     |   85.89 |    82.14 |    91.3 |   85.89 | ...73-579,592-593 
  ...oordinator.ts |   82.67 |    76.63 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |    76.7 |    67.47 |   85.71 |    76.7 | ...1885,1976-1977 
  ...controller.ts |   67.82 |    79.66 |      75 |   67.82 | ...66-278,287-295 
  ...sk-service.ts |   82.71 |    66.15 |   93.61 |   82.71 | ...1270,1283,1290 
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.85 |    77.39 |     100 |   94.85 | ...18,327-330,350 
  types.ts         |     100 |      100 |     100 |     100 |                   
 .../local-control |   82.89 |    88.77 |      90 |   82.89 |                   
  credentials.ts   |   96.42 |    95.45 |     100 |   96.42 | 109-110           
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...interfaces.ts |   43.58 |    82.75 |   42.85 |   43.58 | ...09-117,130-142 
  ...r-identity.ts |     100 |    85.71 |     100 |     100 | 61                
  service.ts       |    93.4 |       90 |     100 |    93.4 | ...20-222,313-315 
 src/serve/routes  |   86.39 |    81.71 |   95.73 |   86.39 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |   98.73 |    96.15 |     100 |   98.73 | 82                
  ...nel-notify.ts |   79.16 |    85.18 |     100 |   79.16 | ...03-104,120-126 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.94 |    91.17 |     100 |   98.94 | 143               
  health.ts        |   99.09 |    91.42 |     100 |   99.09 | 147               
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |   84.61 |    76.47 |     100 |   84.61 | ...04,106-111,131 
  permission.ts    |   96.03 |    87.87 |     100 |   96.03 | 81-84             
  ...uled-tasks.ts |   87.95 |    84.38 |   94.59 |   87.95 | ...1730,1775-1776 
  ...r-backfill.ts |   98.53 |    94.51 |     100 |   98.53 | ...48-249,616-617 
  ...on-runtime.ts |   91.42 |       90 |     100 |   91.42 | 56-64             
  session.ts       |   86.69 |    83.06 |    94.3 |   86.69 | ...7149,7151-7152 
  sse-events.ts    |   87.01 |    84.95 |   94.44 |   87.01 | ...40-951,954,961 
  ...e-sessions.ts |    86.9 |    80.57 |     100 |    86.9 | ...81-483,486-491 
  terminal.ts      |   92.81 |    90.35 |     100 |   92.81 | ...10-313,332-335 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.35 |    78.94 |     100 |   90.35 | ...52-553,576-577 
  ...d-contacts.ts |   83.62 |    94.59 |     100 |   83.62 | 123,125-142       
  ...controller.ts |   83.33 |    80.47 |      90 |   83.33 | ...1056,1061,1068 
  ...extensions.ts |    89.9 |    79.35 |   93.93 |    89.9 | ...2348,2393-2394 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   89.72 |    79.35 |     100 |   89.72 | ...05,719-726,807 
  ...t-branches.ts |   75.04 |     66.4 |     100 |   75.04 | ...99-604,613-620 
  ...e-git-diff.ts |   97.19 |    89.58 |     100 |   97.19 | 157-158,185-187   
  ...ce-git-log.ts |     100 |       95 |     100 |     100 | 48,73             
  workspace-git.ts |   74.71 |     87.5 |     100 |   74.71 | 83-104            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...al-control.ts |   74.17 |    69.23 |     100 |   74.17 | ...18,220-226,231 
  ...management.ts |   87.14 |    84.21 |     100 |   87.14 | ...1802,1812-1817 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.67 |       75 |     100 |   75.67 | ...15-726,732-733 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |   76.41 |    86.11 |     100 |   76.41 | ...29-354,360-394 
  ...ace-status.ts |   82.57 |    74.48 |     100 |   82.57 | ...71-473,477-478 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   76.92 |     67.1 |      80 |   76.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    81.02 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   93.06 |    91.22 |   97.39 |   93.06 |                   
  access-log.ts    |   98.73 |    97.26 |     100 |   98.73 | 119,196           
  ...-timestamp.ts |     100 |      100 |     100 |     100 |                   
  ...er-helpers.ts |   63.82 |    78.15 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.87 |       80 |     100 |   97.87 | 27                
  ...r-response.ts |   88.75 |    82.25 |     100 |   88.75 | ...61,878,941-950 
  fs-factory.ts    |     100 |    95.52 |     100 |     100 | 77,144,200        
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...list-cache.ts |   99.01 |    95.52 |     100 |   99.01 | 184-185           
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |       80 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.13 |    95.14 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   95.13 |     87.5 |     100 |   95.13 | 188-194           
  ...on-archive.ts |   91.29 |    89.33 |   97.61 |   91.29 | ...1133,1196-1197 
  ...ion-export.ts |   98.57 |    90.47 |     100 |   98.57 | 85                
  session-list.ts  |   97.27 |    93.89 |     100 |   97.27 | ...1183,1392-1396 
  ...pr-refresh.ts |   98.71 |    98.57 |     100 |   98.71 | 267-270           
  ...ry-context.ts |    87.5 |       50 |     100 |    87.5 | 49-50             
  telemetry.ts     |   99.06 |    97.26 |     100 |   99.06 | ...04,873,952-954 
 src/serve/voice   |    92.7 |    91.53 |   97.72 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.24 |     100 |     100 | 176               
 ...kspace-service |   89.85 |    86.73 |    91.3 |   89.85 |                   
  index.ts         |   89.49 |    86.34 |      90 |   89.49 | ...1393-1397,1400 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |    92.7 |    89.68 |   98.13 |    92.7 |                   
  ...mandLoader.ts |     100 |       95 |     100 |     100 | 107               
  ...killLoader.ts |   97.19 |    85.71 |     100 |   97.19 | 142,153-154       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   87.09 |    83.07 |     100 |   87.09 | ...35-340,345-350 
  ...omptLoader.ts |   79.55 |    88.42 |   85.71 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.77 |    92.45 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   92.14 |    92.42 |     100 |   92.14 | ...91-296,329-330 
  ...low-loader.ts |     100 |    96.29 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...96-898,901-903 
 ...s/housekeeping |      93 |    88.34 |      95 |      93 |                   
  scheduler.ts     |      93 |    88.34 |      95 |      93 | ...57-359,411-415 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.94 |    86.86 |   96.29 |   88.94 |                   
  DataProcessor.ts |   88.31 |    86.84 |      95 |   88.31 | ...1368,1372-1379 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.25 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |       85 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.83 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |    94.6 |    76.66 |      80 |    94.6 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...lot-client.ts |     100 |    66.66 |     100 |     100 | 31,39             
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   71.09 |    78.17 |   70.65 |   71.09 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   76.62 |    73.37 |   71.05 |   76.62 | ...4465,4581-4587 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |   63.63 |      100 |   41.17 |   63.63 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...AutoUpdate.ts |   93.54 |    94.64 |      90 |   93.54 | 126,131,202-213   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...ractiveUI.tsx |   68.33 |    77.27 |   41.66 |   68.33 | ...63-465,495-500 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  systemInfo.ts    |   95.09 |    90.27 |     100 |   95.09 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
 src/ui/auth       |   69.23 |    72.03 |   61.22 |   69.23 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   74.93 |    78.62 |   71.42 |   74.93 | ...92-902,918,921 
  useAuth.ts       |   94.83 |       75 |     100 |   94.83 | ...33-234,253-259 
  ...rSetupFlow.ts |   59.79 |    58.33 |     100 |   59.79 | ...82-403,420-463 
 src/ui/commands   |    84.6 |    84.46 |   91.68 |    84.6 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...or-command.ts |     100 |    95.65 |     100 |     100 | 104,182           
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 28,62             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...28-129,137-146 
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...essCommand.ts |   80.71 |     64.7 |     100 |   80.71 | ...05-206,220-223 
  ...astCommand.ts |   84.75 |    76.47 |     100 |   84.75 | ...96-102,130-135 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   73.75 |    74.02 |   83.33 |   73.75 | ...72-605,616-617 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   90.56 |    87.83 |    90.9 |   90.56 | ...75-280,327-334 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 26                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  doctorCommand.ts |   70.16 |    84.61 |      95 |   70.16 | ...29-679,682-816 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   80.95 |       80 |     100 |   80.95 | 49-54,69-72,93-98 
  effort-utils.ts  |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 95,146            
  goalCommand.ts   |     100 |    96.49 |     100 |     100 | 139,192           
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.25 |    65.71 |   85.71 |   81.25 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |    58.5 |    74.07 |      80 |    58.5 | ...21-331,334-343 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   94.63 |    90.66 |     100 |   94.63 | ...25-226,253-263 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,102-103        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.28 |    86.29 |     100 |   86.28 | ...1112,1146-1151 
  peers-command.ts |     100 |    94.36 |     100 |     100 | 59,70,223,228     
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |    89.6 |       90 |     100 |    89.6 | ...72-176,212-219 
  ...oreCommand.ts |   90.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.33 |    72.13 |     100 |   77.33 | ...46-150,173-178 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |     100 |      100 |     100 |     100 |                   
  voice-command.ts |   93.63 |       88 |     100 |   93.63 | 36,98-103         
  ...owsCommand.ts |   94.38 |    85.29 |     100 |   94.38 | ...78-183,282-287 
 src/ui/components |   73.25 |    80.22 |    77.7 |   73.25 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   89.06 |    90.78 |     100 |   89.06 | ...87-289,303-305 
  Composer.tsx     |   94.54 |    66.66 |     100 |   94.54 | ...-76,88,143,158 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |   11.28 |      100 |       0 |   11.28 | 71-598            
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...gsDisplay.tsx |     100 |    96.87 |   83.33 |     100 | 69                
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   81.27 |    69.23 |      50 |   81.27 | ...06,245,267-272 
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.69 |    67.61 |     100 |   79.69 | ...17,520,523-529 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   86.26 |     83.3 |      80 |   86.26 | ...2231,2252,2348 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.88 |    96.03 |   46.15 |   95.88 | ...20,523-527,530 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   85.22 |    74.17 |     100 |   85.22 | ...1042,1098,1100 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |   16.66 |      100 |       0 |   16.66 | 14-56             
  ...onsDialog.tsx |    2.13 |      100 |       0 |    2.13 | 62-133,148-1004   
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |    8.57 |      100 |       0 |    8.57 | 24-55,58-134      
  ...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           
  ...ngSpinner.tsx |   67.85 |    85.71 |      50 |   67.85 | 33-50,71,78-79    
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.55 |    73.89 |   69.23 |   71.55 | ...1252,1258-1259 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-171             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.9 |    86.88 |     100 |    93.9 | ...20,282,302-304 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   95.62 |    87.09 |     100 |   95.62 | ...24-125,273-275 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |    61.5 |    75.57 |    62.5 |    61.5 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |     100 |    81.81 |     100 |     100 | 82                
  ...tComposer.tsx |   78.35 |     64.7 |   66.66 |   78.35 | ...64,277,303-305 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |   45.51 |    70.53 |   60.86 |   45.51 |                   
  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 |    9.77 |      100 |       0 |    9.77 | 27-166            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...ackground-view |   85.86 |     85.1 |   92.98 |   85.86 |                   
  ...sksDialog.tsx |   82.66 |    83.09 |   85.71 |   82.66 | ...1854,1977-1983 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |    50.7 |    52.38 |   20.83 |    50.7 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.24 |      100 |       0 |    9.24 | 40-67,70-163      
 ...mponents/hooks |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.78 |    87.65 |   86.79 |   90.78 |                   
  ...orMessage.tsx |     100 |      100 |     100 |     100 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   93.24 |       85 |     100 |   93.24 | 73-75,77,79       
  ...nMessages.tsx |   94.11 |    95.91 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.51 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   95.04 |    89.55 |     100 |   95.04 | ...1075,1120-1122 
 ...ponents/shared |    86.4 |    82.05 |    86.6 |    86.4 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.95 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   90.37 |    82.85 |   18.18 |   90.37 | ...60-63,65,73-76 
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  TextInput.tsx    |    80.8 |    67.79 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  text-buffer.ts   |   85.98 |    81.78 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |    3.99 |      100 |       0 |    3.99 |                   
  ...gerDialog.tsx |    3.99 |      100 |       0 |    3.99 | 79-137,140-678    
 ...ents/subagents |   30.87 |        0 |       0 |   30.87 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   10.95 |      100 |       0 |   10.95 | ...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 |    21.6 |    59.52 |   27.27 |    21.6 |                   
  ...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 |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |   13.72 |      100 |       0 |   13.72 | 18-73             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   86.47 |    82.34 |   86.48 |   86.47 |                   
  ...ewContext.tsx |   91.66 |       90 |      75 |   91.66 | ...89-193,279-289 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 237-238           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   89.51 |    76.92 |   95.65 |   89.51 |                   
  ...ui-adapter.ts |   89.51 |    76.92 |   95.65 |   89.51 | ...59,877-878,964 
 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      |    86.1 |    84.16 |   87.81 |    86.1 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.55 |    73.58 |     100 |   94.55 | ...87-288,293-294 
  ...dProcessor.ts |   86.83 |    71.86 |   83.33 |   86.83 | ...1536,1565-1569 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...llm-stream.ts |   87.63 |    84.43 |   78.72 |   87.63 | ...5813-5815,5817 
  ...ng-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.41 |    82.08 |   66.66 |   92.41 | ...12,514-515,670 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      52 |    63.63 |     100 |      52 | ...59,67-70,76-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   96.03 |    88.75 |     100 |   96.03 | ...04-205,362-365 
  ...ompletion.tsx |   97.09 |    87.23 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |   11.62 |      100 |       0 |   11.62 | 44-87             
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.44 |     98.9 |     100 |   98.44 | 157-160           
  ...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    
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |    94.94 |     100 |     100 | ...43,279,349,359 
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |   85.29 |    80.28 |    92.3 |   85.29 | ...36,351-361,441 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.13 |     86.9 |     100 |   89.13 | ...61-463,496-506 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   96.51 |    90.19 |     100 |   96.51 | 279,306-311       
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.19 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.79 |    85.33 |   94.73 |   82.79 | ...86-688,696-732 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.32 |    93.93 |     100 |   97.32 | ...18-422,518-525 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |    79.2 |    35.29 |     100 |    79.2 | ...15-116,120-121 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |   91.25 |    89.47 |     100 |   91.25 |                   
  ...AppLayout.tsx |   90.99 |     87.5 |     100 |   90.99 | 61-63,111-116,152 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/model      |   97.91 |    98.36 |     100 |   97.91 |                   
  ...ggregation.ts |     100 |      100 |     100 |     100 |                   
  ...ming-model.ts |   97.43 |    97.72 |     100 |   97.43 | 261-265           
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   93.56 |    86.19 |     100 |   93.56 |                   
  screen-buffer.ts |   94.73 |    66.66 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   93.81 |     92.1 |     100 |   93.81 | ...1,45-46,99-100 
  ...tion-state.ts |     100 |      100 |     100 |     100 |                   
  ...ction-text.ts |   93.85 |    93.44 |     100 |   93.85 | 30-34,130-131     
  ...selection.tsx |   91.88 |    78.57 |     100 |   91.88 | ...16-417,446-447 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   87.98 |    86.07 |    96.1 |   87.98 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   80.07 |     75.6 |     100 |   80.07 | ...70,274,332-333 
  ...wnDisplay.tsx |   92.87 |     93.5 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   93.63 |    81.77 |   95.23 |   93.63 | ...47-750,803-808 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |    52.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.61 |    93.27 |     100 |   98.61 | 189,217-218,424   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  ...coalescing.ts |     100 |      100 |     100 |     100 |                   
  formatters.ts    |   94.87 |    98.24 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   94.44 |    96.29 |     100 |   94.44 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |    95.65 |     100 |     100 | 45,151            
  historyUtils.ts  |   96.07 |     97.1 |     100 |   96.07 | 104-107           
  ...mage-parts.ts |   97.75 |       95 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   91.33 |    79.03 |     100 |   91.33 | ...73,273,277-278 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   84.37 |    81.09 |     100 |   84.37 | ...03-625,759-760 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   95.19 |      100 |   88.88 |   95.19 | 121-126           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...ize-reflow.ts |     100 |     92.3 |     100 |     100 | 57,62,209,217,347 
  ...wOptimizer.ts |     100 |    94.73 |     100 |     100 | 35,78             
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   98.71 |    95.72 |     100 |   98.71 | 292-293,478-479   
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   95.81 |     92.3 |     100 |   95.81 | ...09-210,243-244 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  windowTitle.ts   |   96.55 |    94.73 |     100 |   96.55 | 56-57             
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |     60.1 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    51.35 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.24 |    79.78 |   81.69 |   81.24 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   92.32 |    89.77 |   96.44 |   92.32 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.09 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  ...y-identity.ts |   89.22 |    85.18 |     100 |   89.22 | ...23-424,431-432 
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.38 |    71.83 |   88.88 |   70.38 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 50-52,58          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.81 |    94.69 |     100 |   97.81 | ...03,420-421,466 
  ...projection.ts |   95.27 |    95.58 |     100 |   95.27 | 140-145           
  jsonc-editor.ts  |   93.18 |    92.66 |     100 |   93.18 | ...80-381,384-385 
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   86.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...-part-list.ts |     100 |      100 |     100 |     100 |                   
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  shell-args.ts    |     100 |      100 |     100 |     100 |                   
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       90 |     100 |     100 | 23                
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   94.35 |    94.11 |     100 |   94.35 |                   
  cleanup.ts       |   92.59 |    93.75 |     100 |   92.59 | ...02-205,209-211 
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  throttledOnce.ts |   95.95 |    93.93 |     100 |   95.95 | 77-78,153-154     
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   88.74 |     87.2 |   90.51 |   88.74 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.26 |    84.51 |   94.55 |   90.26 |                   
  ...transcript.ts |   88.49 |    84.09 |     100 |   88.49 | ...32,640,646-650 
  ...ent-resume.ts |   85.74 |       78 |    85.1 |   85.74 | ...1803-1807,1810 
  ...ound-tasks.ts |   95.19 |    90.75 |   96.42 |   95.19 | ...1889,1897-1898 
  forkedAgent.ts   |   93.21 |    83.47 |   94.44 |   93.21 | ...94,702,707-714 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.27 |    88.23 |   98.33 |   95.27 | ...1478,1492-1494 
  ...w-snapshot.ts |   75.73 |    72.22 |    87.5 |   75.73 | ...21,445,452-454 
  worktree-pin.ts  |     100 |    88.23 |     100 |     100 | 78,99             
 src/agents/arena  |   76.87 |    68.43 |   78.94 |   76.87 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |    75.8 |    65.46 |   78.57 |    75.8 | ...1879,1885-1886 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   77.32 |    86.38 |   75.52 |   77.32 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   91.45 |    90.21 |   96.87 |   91.45 | ...66-467,586-592 
  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 |   93.37 |    87.56 |   92.44 |   93.37 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   90.39 |    80.91 |   81.25 |   90.39 | ...2551,2597-2599 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.57 |    89.41 |   83.33 |   93.57 | ...04-505,508-509 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.38 |      100 |    92.3 |   98.38 | 85-86             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   92.78 |    78.12 |     100 |   92.78 | ...49-150,192-194 
  ...ta-literal.ts |   95.96 |    92.68 |     100 |   95.96 | ...78-379,395-396 
  ...chestrator.ts |   93.85 |    90.47 |     100 |   93.85 | ...2206,2299-2302 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   95.77 |    84.16 |      95 |   95.77 | ...88,356,376-379 
  ...ow-sandbox.ts |   97.29 |    88.84 |     100 |   97.29 | ...1835,1841-1842 
  ...flow-saved.ts |    96.7 |     93.9 |     100 |    96.7 | 153-154,261-264   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 170-171,270       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   84.84 |    85.82 |   91.09 |   84.84 |                   
  TeamManager.ts   |   78.24 |    83.83 |   84.12 |   78.24 | ...1907,1930-1931 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   96.02 |     87.5 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.29 |       83 |     100 |   89.29 | ...1000,1044-1045 
  team-events.ts   |   73.68 |      100 |   66.66 |   73.68 | 140-144,151-155   
  teamHelpers.ts   |    92.5 |    95.45 |      95 |    92.5 | ...29-330,393-403 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   95.28 |    95.34 |   98.24 |   95.28 |                   
  ...on-harness.ts |   96.49 |    85.71 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |     100 |    96.96 |     100 |     100 | 189,198           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   86.21 |    88.39 |   78.34 |   86.21 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.91 |    87.81 |   76.32 |   84.91 | ...9653,9657-9659 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  models.ts        |     100 |      100 |     100 |     100 |                   
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  storage.ts       |   96.05 |    93.43 |   89.47 |   96.05 | ...34-735,738-739 
 ...nfirmation-bus |   98.27 |    97.22 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.14 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.83 |    88.65 |   93.87 |   92.83 |                   
  ...on-restore.ts |   88.23 |    85.41 |     100 |   88.23 | ...60,63-64,67-68 
  baseLlmClient.ts |    88.4 |    83.68 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   92.36 |    88.22 |   91.83 |   92.36 | ...4537,4635-4636 
  ...tGenerator.ts |   87.45 |    88.09 |   88.88 |   87.45 | ...08-509,554-560 
  ...lScheduler.ts |   90.23 |    85.01 |   94.73 |   90.23 | ...6512,6540-6556 
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  geminiChat.ts    |     100 |      100 |     100 |     100 |                   
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  llm-chat.ts      |   95.21 |    90.81 |   96.69 |   95.21 | ...5744,5789-5790 
  llm-request.ts   |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 46-47             
  output-styles.ts |     100 |      100 |     100 |     100 |                   
  ...on-helpers.ts |   95.38 |    84.31 |     100 |   95.38 | ...87,215,217-218 
  ...issionFlow.ts |   98.98 |    96.96 |     100 |   98.98 | 109               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.89 |    91.12 |      85 |   93.89 | ...1272,1475-1476 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    91.89 |     100 |     100 | 87,122-139        
  ...-arguments.ts |     100 |      100 |     100 |     100 |                   
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 83-87             
  ...allIdUtils.ts |   98.81 |    91.22 |     100 |   98.81 | 43,52             
  ...okTriggers.ts |   99.45 |     92.5 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   99.19 |    94.48 |     100 |   99.19 | 765-766,835       
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.58 |    89.11 |   97.43 |   96.58 |                   
  ...tGenerator.ts |   97.66 |    88.91 |   97.43 |   97.66 | ...1494,1523,1534 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1334,1555-1557 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 ...tent-generator |   89.24 |    72.72 |   94.11 |   89.24 |                   
  index.ts         |     100 |    85.71 |     100 |     100 | 51                
  ...-generator.ts |   87.54 |    71.42 |   93.75 |   87.54 | ...93-294,356-362 
 ...ntentGenerator |   95.78 |    90.51 |   96.22 |   95.78 |                   
  ...e-snapshot.ts |   97.39 |    89.65 |     100 |   97.39 | ...,49-50,151-152 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.38 |    90.14 |   95.12 |   95.38 | ...1345-1346,1374 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   92.33 |    90.93 |   96.58 |   92.33 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.25 |    89.66 |   96.87 |   91.25 | ...1946,2115-2130 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   76.19 |    88.88 |      50 |   76.19 | 44-53,90-94       
  ...tGenerator.ts |      70 |    73.33 |     100 |      70 | ...07-112,121-127 
  pipeline.ts      |   95.38 |    91.56 |     100 |   95.38 | ...1461-1462,1569 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.11 |    92.25 |     100 |   92.11 | ...21-522,542-545 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.24 |       92 |   98.64 |   97.24 |                   
  dashscope.ts     |   98.42 |    95.27 |   96.55 |   98.42 | ...51-752,894-895 
  deepseek.ts      |   95.34 |    90.56 |     100 |   95.34 | ...54-155,168-169 
  default.ts       |   98.87 |       96 |     100 |   98.87 | 178,304           
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |      90 |    76.31 |     100 |      90 | ...,72-73,173-175 
 src/extension     |   88.79 |    86.22 |   93.46 |   88.79 |                   
  ...ive-safety.ts |   97.77 |    93.75 |     100 |   97.77 | 100-101           
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...git-client.ts |     100 |      100 |     100 |     100 |                   
  ...redentials.ts |   95.33 |    89.47 |     100 |   95.33 | ...21-122,173-175 
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   92.82 |    89.27 |    98.3 |   92.82 | ...1641-1647,1691 
  ...ionManager.ts |   84.52 |    83.52 |      83 |   84.52 | ...3139,3177-3178 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.71 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   92.43 |    87.52 |     100 |   92.43 | ...1293-1294,1304 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |    90.16 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.54 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.33 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 ...ent-plugins-v1 |   84.94 |    79.51 |     100 |   84.94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  manifest.ts      |   81.87 |    84.48 |     100 |   81.87 | ...55-156,161-174 
  mcp.ts           |   84.98 |    79.56 |     100 |   84.98 | ...88-389,419-420 
  paths.ts         |     100 |    94.44 |     100 |     100 | 59                
  skills.ts        |   82.31 |    63.88 |     100 |   82.31 | ...38-141,150-151 
 src/followup      |   84.78 |    82.27 |   86.84 |   84.78 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   76.53 |    71.96 |   58.33 |   76.53 | ...48-749,756-757 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   86.11 |    87.17 |     100 |   86.11 | ...39-244,356-358 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   93.59 |    90.38 |      95 |   93.59 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   99.45 |    97.05 |     100 |   99.45 | 155               
  ...checkpoint.ts |   86.08 |    85.18 |     100 |   86.08 | ...29-132,142-145 
  ...ion-prompt.ts |     100 |      100 |     100 |     100 |                   
  goal-evidence.ts |    88.7 |     88.2 |   97.67 |    88.7 | ...1219,1242-1245 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...87,190,194-196 
  ...ersistence.ts |   87.36 |    85.96 |    87.5 |   87.36 | ...53-154,185-190 
  goal-protocol.ts |   97.56 |    96.42 |     100 |   97.56 | 322-323           
  goal-reducer.ts  |   95.75 |    93.82 |   97.36 |   95.75 | ...76,666,684-685 
  goal-runtime.ts  |   96.51 |    90.64 |   96.49 |   96.51 | ...1645-1646,1777 
  ...provenance.ts |     100 |      100 |     100 |     100 |                   
  goal-tools.ts    |   98.58 |     95.2 |   96.15 |   98.58 | ...41-242,350-351 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    93.02 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   89.12 |     87.1 |    89.8 |   89.12 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   75.58 |    83.23 |   87.87 |   75.58 | ...25-927,937-940 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   82.47 |    84.21 |      75 |   82.47 | 63-67,169-184     
  ...oksManager.ts |   94.87 |    90.12 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.09 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ipc           |   92.72 |    90.15 |    97.5 |   92.72 |                   
  inbound-gate.ts  |   98.93 |     89.1 |     100 |   98.93 | 522-524           
  peer-envelope.ts |     100 |      100 |     100 |     100 |                   
  peer-frames.ts   |   97.45 |    93.65 |     100 |   97.45 | 235-237           
  socket-path.ts   |   85.71 |    93.33 |     100 |   85.71 | 83-88             
  uds-client.ts    |   85.71 |    94.11 |      80 |   85.71 | 162-175           
  uds-inbox.ts     |   82.42 |    81.81 |     100 |   82.42 | ...33,240-250,282 
 src/lsp           |   58.96 |    70.67 |   66.49 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |    72.22 |   95.65 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |    81.81 |   21.05 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.48 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.71 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   88.82 |    85.24 |    90.9 |   88.82 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 135,145           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   93.82 |    84.09 |     100 |   93.82 | 78-83,122,154-157 
  ...entPlanner.ts |   91.55 |    76.74 |     100 |   91.55 | ...05,118-121,296 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   90.16 |    78.76 |   94.44 |   90.16 | ...06,629,642-648 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |   78.51 |    83.16 |   77.77 |   78.51 | ...1487,1500-1502 
  ...ent-config.ts |   87.64 |    83.62 |      88 |   87.64 | ...08,411-425,437 
  memoryAge.ts     |   90.47 |    83.33 |     100 |   90.47 | 50-51             
  ...yDiscovery.ts |   93.48 |    90.09 |     100 |   93.48 | ...42,401,629-632 
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    86.79 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   86.86 |    86.23 |   92.85 |   86.86 | ...33-538,571-582 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.2 |    85.71 |     100 |    93.2 | ...45-146,148-149 
  remember.ts      |   98.88 |    90.38 |     100 |   98.88 | 50,70             
  scan.ts          |   93.75 |       80 |     100 |   93.75 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   73.92 |       75 |   66.66 |   73.92 | ...78-482,485,491 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |    85.71 |     100 |     100 | 27                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...66-280,294-299 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.82 |    89.39 |   91.35 |   92.82 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   79.43 |    64.51 |   85.71 |   79.43 | ...,89-96,131-142 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,262           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1407,1436-1437 
  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   |   84.45 |    91.47 |    72.4 |   84.45 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.79 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |      89 |    90.99 |   86.84 |      89 | ...1461,1567-1571 
  rule-parser.ts   |   94.89 |    92.83 |     100 |   94.89 | ...1550,1584-1586 
  ...-semantics.ts |   70.44 |    91.09 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.05 |    95.23 |     100 |   99.05 |                   
  system-prompt.ts |   99.05 |    95.23 |     100 |   99.05 | 226               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   85.14 |    80.63 |   82.85 |   85.14 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...-discovery.ts |    95.4 |    94.44 |     100 |    95.4 | 31-32,42-43       
  ...der-config.ts |   75.91 |    73.48 |   78.26 |   75.91 | ...74-475,503-504 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   98.04 |    91.66 |   63.63 |   98.04 |                   
  ...oding-plan.ts |    87.5 |      100 |       0 |    87.5 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  moonshot.ts      |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.36 |    78.82 |   95.94 |   85.36 |                   
  ...tGenerator.ts |    98.6 |    98.14 |     100 |    98.6 | 103-104           
  qwenOAuth2.ts    |   82.79 |    73.91 |    90.9 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |     76.8 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   90.65 |     86.2 |   96.55 |   90.65 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   98.48 |    87.28 |     100 |   98.48 | 81-82,105,474-475 
  branch-points.ts |     100 |    95.23 |     100 |     100 | ...20,211,224,327 
  ...ionService.ts |   97.72 |    96.53 |     100 |   97.72 | ...1081,1224-1232 
  ...ingService.ts |    92.6 |    88.12 |   94.73 |    92.6 | ...2856,2871-2872 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.23 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.34 |    91.96 |     100 |   96.34 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |   74.75 |    70.76 |   96.07 |   74.75 | ...2296,2325-2326 
  ...on-service.ts |   86.58 |    74.39 |     100 |   86.58 | ...56-460,498-499 
  ...references.ts |   98.57 |    91.42 |     100 |   98.57 | 156-157,217-218   
  ...ionService.ts |   98.26 |    97.23 |     100 |   98.26 | ...65-866,889-890 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |   97.22 |    90.99 |     100 |   97.22 | ...55-456,609-610 
  ...ttachments.ts |   97.74 |     90.9 |     100 |   97.74 | 298-308,646       
  ...pi-history.ts |   98.94 |    89.13 |     100 |   98.94 | 43                
  ...ersistence.ts |   91.88 |    81.19 |     100 |   91.88 | ...1073-1074,1119 
  ...tory-state.ts |     100 |    95.23 |     100 |     100 | 31                
  ...on-service.ts |   94.61 |    92.44 |   97.22 |   94.61 | ...11-613,669-677 
  ...pr-service.ts |   96.04 |    89.74 |     100 |   96.04 | 72,98-101,190-191 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...n-registry.ts |   98.74 |    94.92 |     100 |   98.74 | 601,655-656,714   
  ...ken-counts.ts |     100 |       96 |     100 |     100 | 58                
  ...ipt-reader.ts |    93.7 |    91.22 |    97.8 |    93.7 | ...2791-2792,2869 
  ...turn-state.ts |   94.11 |     90.9 |   91.66 |   94.11 | 108-112,129-130   
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   84.57 |    75.18 |   97.72 |   84.57 | ...2567,2589,2603 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.82 |    85.68 |    91.4 |   88.82 | ...4049-4050,4091 
  sessionTitle.ts  |   96.35 |    79.71 |     100 |   96.35 | ...08-311,342-343 
  ...ContextEnv.ts |     100 |    94.73 |     100 |     100 | 76,111            
  ...ionService.ts |   84.43 |    78.45 |   97.18 |   84.43 | ...2496,2502-2507 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...Estimation.ts |     100 |    95.83 |     100 |     100 | 139               
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...ite-origin.ts |     100 |    93.33 |     100 |     100 | 32                
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.77 |    84.92 |     100 |   90.77 | ...43-546,598-599 
  ...l-registry.ts |   92.99 |    83.19 |     100 |   92.99 | ...66-367,377-378 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   88.36 |     87.7 |     100 |   88.36 | ...48-449,465-466 
 ...icrocompaction |   98.91 |    95.08 |     100 |   98.91 |                   
  microcompact.ts  |   98.91 |    95.08 |     100 |   98.91 | ...60,769,778-779 
 ...s/visionBridge |    98.8 |    92.12 |     100 |    98.8 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.78 |    86.08 |   94.73 |   89.78 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |    87.69 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   86.11 |    85.71 |   86.11 |   86.11 | ...1244,1251-1255 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.07 |     100 |   97.91 | 286-287           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   88.58 |    89.46 |    98.3 |   88.58 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   85.54 |    86.59 |   97.43 |   85.54 | ...1588,1665-1666 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   83.23 |    84.98 |   86.51 |   83.23 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  context-usage.ts |   96.85 |    91.07 |     100 |   96.85 | ...26-127,199-200 
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   80.71 |    81.91 |   79.16 |   80.71 | ...92,499-501,517 
  ...attributes.ts |   96.98 |    91.37 |     100 |   96.98 | ...47-348,366-367 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.38 |    83.33 |      50 |   65.38 | ...08-109,112-113 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |    99.02 |     100 |     100 | 106               
  ...ai-request.ts |   87.88 |    92.79 |   83.78 |   87.88 | ...55-561,564-568 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.12 |    96.03 |      95 |   99.12 | 150,379-380       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.83 |    77.77 |   66.66 |   60.83 | ...1523,1540-1560 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   94.13 |    86.66 |      75 |   94.13 | ...45,496-497,513 
  sdk.ts           |    82.7 |     90.9 |   66.66 |    82.7 | ...00-204,242-264 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ion-events.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   91.29 |    88.88 |    97.5 |   91.29 | ...1946,1975-1978 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   83.26 |    88.81 |   86.36 |   83.26 | ...1467,1471-1478 
  uiTelemetry.ts   |   98.87 |     95.1 |   97.05 |   98.87 | ...59,696,786-787 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.38 |    98.64 |   84.09 |   96.38 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |      80 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   87.54 |    86.06 |   90.21 |   87.54 |                   
  ...erQuestion.ts |   89.71 |    81.13 |    92.3 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.72 |    91.48 |   83.33 |   89.72 | ...06-307,318-325 
  cron-create.ts   |   92.26 |    97.72 |      75 |   92.26 | ...,76-77,272-281 
  cron-delete.ts   |   97.56 |      100 |   85.71 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.45 |   88.88 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    85.71 |    90.9 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.88 |   82.35 |   82.76 | ...45-746,865-915 
  ...r-worktree.ts |   83.14 |    68.42 |   88.88 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |       84 |      90 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |     83.8 |   94.73 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.71 |   86.36 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    78.12 |   91.66 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.11 |    83.33 |   85.71 |   94.11 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |     93.1 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.54 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.9 |    90.9 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.07 |    80.15 |   85.71 |   82.07 | ...3243,3245-3246 
  mcp-client.ts    |   86.25 |    87.61 |   93.93 |   86.25 | ...2552,2556-2559 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1342,1350-1351 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |    97.5 |    93.93 |     100 |    97.5 | 178-179           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |    98.1 |       93 |     100 |    98.1 | ...1233,1288-1289 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1411,1418-1422 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.71 |    77.39 |   82.35 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.61 |    87.5 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  readManyFiles.ts |   96.04 |    82.25 |     100 |   96.04 | ...41,594,604-608 
  ...d-artifact.ts |   85.68 |    81.59 |   94.73 |   85.68 | ...1071,1095-1096 
  ...t-findings.ts |   99.08 |    93.75 |    92.3 |   99.08 | 217-219           
  ...t-shutdown.ts |    87.2 |    86.66 |   77.77 |    87.2 | ...,75-79,162-165 
  ripGrep.ts       |    94.6 |    87.34 |   95.45 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |    81.5 |    90.69 |   66.66 |    81.5 | ...80-286,354-361 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.96 |    84.29 |      93 |   78.96 | ...5036,5111-5112 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   93.56 |    90.78 |   91.66 |   93.56 | ...49,653,701-723 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.75 |   83.33 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   80.43 |    86.95 |   85.71 |   80.43 | ...67,121,125-132 
  task-stop.ts     |   93.14 |    96.29 |    87.5 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.87 |     86.5 |   92.85 |   82.87 | ...54-564,588-599 
  team-create.ts   |   97.24 |     87.5 |   85.71 |   97.24 | 48-49,129-130     
  team-delete.ts   |   86.74 |    84.61 |   85.71 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.96 |   81.81 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.73 |    90.47 |   93.75 |   95.73 | ...48-552,565-570 
  ...repeat-key.ts |     100 |      100 |     100 |     100 |                   
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   80.48 |    82.45 |   86.53 |   80.48 | ...1099,1107-1108 
  ...-finalizer.ts |    98.1 |    92.36 |   93.33 |    98.1 | ...34-235,237-241 
  ...iagnostics.ts |   99.06 |    97.69 |   91.66 |   99.06 | 133-134,205       
  ...-retention.ts |     100 |    95.83 |     100 |     100 | 116               
  tool-search.ts   |   96.19 |    89.79 |   93.75 |   96.19 | ...09,259-264,426 
  tool-utils.ts    |   97.46 |    96.55 |     100 |   97.46 | 26-27             
  tools.ts         |   92.93 |    92.18 |      92 |   92.93 | ...64-565,581-587 
  truncation.ts    |   90.61 |    90.35 |     100 |   90.61 | ...53-461,498-504 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   87.29 |    86.15 |   89.47 |   87.29 | ...53-856,893-928 
  zoom-image.ts    |   95.76 |    93.93 |    90.9 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.26 |    88.51 |   89.71 |   87.26 |                   
  agent.ts         |   85.88 |    87.64 |   87.35 |   85.88 | ...4265,4299-4309 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.83 |    92.51 |   88.63 |   95.83 |                   
  artifact-tool.ts |   91.69 |    88.46 |   71.42 |   91.69 | ...20-321,329-332 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...tools/workflow |   89.33 |    87.68 |   82.75 |   89.33 |                   
  workflow.ts      |   89.33 |    87.68 |   82.75 |   89.33 | ...33,878,880-881 
 src/utils         |   92.78 |    89.74 |   96.89 |   92.78 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |      95 |    92.76 |     100 |      95 | ...49-550,657-661 
  auth-type.ts     |     100 |      100 |     100 |     100 |                   
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.79 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.89 |    94.11 |      95 |   95.89 | ...99-500,512-525 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |     100 |    97.18 |     100 |     100 | 79,86             
  ...qwen-model.ts |     100 |      100 |     100 |     100 |                   
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   88.92 |    92.99 |      68 |   88.92 | ...92,394,410-411 
  fetch.ts         |   90.68 |    82.63 |     100 |   90.68 | ...72,483-484,503 
  ...ng-options.ts |     100 |      100 |     100 |     100 |                   
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.79 |    92.16 |   96.29 |   94.79 | ...2076,2084-2085 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  git-ignore.ts    |     100 |      100 |     100 |     100 |                   
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.83 |    82.35 |    87.5 |   78.83 | ...22-123,164-215 
  github-prs.ts    |   96.06 |    84.09 |     100 |   96.06 | 251,350-358       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.08 |    93.47 |     100 |   95.08 | ...62-166,234-238 
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  is-tool.ts       |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   96.15 |    93.51 |     100 |   96.15 | ...86-387,429-432 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...-constants.ts |   94.73 |     92.3 |     100 |   94.73 | 66-67             
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...tProcessor.ts |   94.01 |     90.1 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.18 |     100 |   98.96 | 154               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   90.88 |    90.66 |     100 |   90.88 | ...28-629,631-633 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  ...s-liveness.ts |     100 |    93.47 |     100 |     100 | 62,72,108         
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.36 |     100 |   96.98 | ...87-688,763-764 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...72,563-564,582 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |   97.77 |    91.48 |     100 |   97.77 | 172-173           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.22 |    98.01 |     100 |   98.22 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |       90 |     100 |     100 | 95                
  ...orageUtils.ts |   96.21 |     86.2 |     100 |   96.21 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.37 |    88.59 |     100 |   86.37 | ...2361,2368-2372 
  ...lAstParser.ts |    98.3 |    91.59 |     100 |    98.3 | ...1340-1342,1352 
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |    57.14 |     100 |   77.77 | 44,54-59          
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminal-env.ts  |      50 |      100 |       0 |      50 | 18-19             
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...error-type.ts |     100 |      100 |     100 |     100 |                   
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ultCleanup.ts |   54.62 |    65.38 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.82 |    92.48 |     100 |   96.82 | ...37-342,344-349 
  ...pt-records.ts |   87.61 |    86.23 |     100 |   87.61 | ...80-484,514-529 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...-directory.ts |    83.7 |    80.95 |    87.5 |    83.7 | ...37-238,252-253 
  ...ifact-path.ts |   94.11 |    92.85 |     100 |   94.11 | 32-33             
  ...aceContext.ts |   95.39 |    89.47 |     100 |   95.39 | ...16-317,321-322 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.75 |   94.78 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.86 |      90 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |    92.3 |      100 |   88.88 |    92.3 |                   
  ...ageFormats.ts |   81.81 |      100 |   66.66 |   81.81 | 56-61             
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
-------------------|---------|----------|---------|---------|-------------------

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

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

整体评估 / Overall assessment

在 head c0114c08 上完整审了 29 个文件(+2483/−16):daemon 侧 PTY 注册表 + /terminal WS 路由 + xterm 面板 + 双重门控。静态审查(未运行测试),CI 全绿。整体设计扎实——升级门控复用、帧协议、竞态处理(创建中释放/排空/重放)和测试密度都很好。但有 1 个 🔴:pre-attach 窗口缺 WS error 监听,一个协议违规帧可以击垮整个 daemon。另有 5 个 🟡 值得处理。

先交代 bot 审查(针对更早的 head)的核心关切:描述承诺 QWEN_WEB_TERMINAL=1 环境门控而代码未实现。在当前 head 上,PR 描述与设计文档均已重写、不再承诺环境变量门控(全库无 QWEN_WEB_TERMINAL 引用),实际门控为"宿主配置项 + capability + bearer 认证 + 工作区信任",与代码一致;残留物见下文第 11 条。两处纯格式化 drive-by(geminiChat.ts、config-session-env.test.ts)已逐行核实确无语义变化,建议若再触碰分支顺手去掉。

Reviewed all 29 files (+2483/−16) at head c0114c08: daemon-side PTY registry + /terminal WS route + xterm panel + dual gating. Static review (no tests run); CI fully green. The design is solid — upgrade-gate reuse, framing, race handling (release-during-create / drain / replay) and test density are all good. But there is 1 🔴: the pre-attach window lacks a WS error listener, so a single protocol-violation frame can take down the entire daemon, plus 5 🟡 items worth addressing.

Context on the earlier bot review (against an older head): its main concern was that the description promised a QWEN_WEB_TERMINAL=1 env gate the code never implemented. At the current head both the PR description and the design doc have been rewritten and no longer promise an env gate (zero QWEN_WEB_TERMINAL references repo-wide); the shipped gating is host-config item + capability + bearer auth + workspace trust, matching the code. Residue is covered in item 11 below. The two formatting-only drive-bys (geminiChat.ts, config-session-env.test.ts) were verified line-by-line as purely cosmetic — worth dropping if the branch is re-touched.


🔴 1. pre-attach 窗口没有 WS error 监听——一个坏帧击垮整个 daemon

packages/cli/src/serve/routes/terminal.ts:128-129(pre-attach 只注册 close/message);:258(首个 error 监听在 attach 之后);packages/cli/src/serve/acp-http/index.ts:1858-1868(extra route 拿到的 socket 不带任何 error 监听)

ws.once('close')/ws.on('message') 注册(:128-129)到 attach 段注册 ws.on('error', cleanup)(:258)之间,横着 await registry.create(...)(动态 import PTY + spawn,可达数百毫秒)。这个窗口内的协议违规(未掩码帧、非法 UTF-8 文本帧、超过 maxPayload 的帧)会让 ws(8.21.3)在 WebSocket 实例上 emit error;没有监听器时 EventEmitter 抛 ERR_UNHANDLED_ERROR → daemon 的未捕获异常处理器只豁免良性 PTY 竞态(uncaught-exception-handler.ts:62-73),其余一律 process.exit(1)——所有工作区的所有会话一起陪葬。对比:ACP 分支自己注册 error 监听(acp-http/index.ts:1901),voice 路由在 onConnection 开头同步注册三件套(voice-ws.ts:516-520)——本路由偏离了既有模式。默认定位的 loopback 无 token 姿态下任何本地进程都能升级成功(Origin 检查只在带 Origin 头时生效),触发成本极低。
修复:在 onConnection 开头(:128 附近)就注册 ws.on('error', markClosed)(或触发 cleanup),与 voice-ws 一致;另建议在分发点对 extraRoute.onConnection 的返回 promise 加防御性 catch(目前是悬浮 promise,acp-http/index.ts:1866)。

EN: Between the pre-attach close/message registration (:128-129) and the first error listener (:258) sits await registry.create(...) (dynamic PTY import + spawn, up to hundreds of ms). A protocol violation in that window (unmasked frame, invalid UTF-8 text frame, frame over maxPayload) makes ws 8.21.3 emit error on the WebSocket instance; with no listener, EventEmitter throws and the daemon's uncaught-exception handler — which suppresses only benign PTY races — calls process.exit(1), taking down every session in every workspace. The dispatch site hands extra routes a bare socket (no error listener), while the ACP branch and the voice route both register one immediately. In the default loopback-no-token posture any local process can reach this. Fix: register ws.on('error', markClosed) at the top of onConnection (mirroring voice-ws), ideally plus a defensive catch on the extraRoute.onConnection promise at the dispatch site.

🟡 2. 陈旧 detach 闭包可给被回收的 id 上定时器,误杀后来的新会话

packages/core/src/services/web-terminal-registry.ts:204-208(detach 闭包)与 :314-320(reclaim 回调只查 listener 数量,不查身份)

addOutputListener 返回的闭包捕获 session 对象但按键 terminalId 行事。时序:会话 S1(id=X)挂载中 → 工作区排空触发 release(X)(S1 从 sessions 移除、PTY 被杀,但路由此刻若尚未感知到 ws close,detach1 还没被调用)→ 客户端 ws 随后关闭 → 路由 cleanup 调 detach1() → 陈旧 S1 的 listeners 归零 → scheduleReclaim(X, S1) 给已删除的 S1 上 15 分钟定时器 → 客户端以同一 terminalId 重连(tab 未关、网络恢复——id 来自 URL 查询参数、同 tab 复用)→ 新会话 S2 建在 X 下 → 定时器到期,回调只见 S1.outputListeners.size === 0this.release('X') → 杀掉 S2。release() 清理的是"当前注册者"的 reclaimTimer(:277),清不掉挂在陈旧 S1 上的那个。
修复(一行级):reclaim 回调与 detach 闭包都加身份校验 this.sessions.get(terminalId) === session(并检查 disposed),并补一条"release 后 detach + id 复用"的回归测试。

EN: The detach closure captures the session object but acts by terminalId, and the reclaim callback only re-checks the listener count, not identity. Sequence: S1 attached (id=X) → drain releases X (S1 removed, PTY killed) before the route sees the ws close → ws closes later → route cleanup calls the stale detach → zero listeners → scheduleReclaim(X, S1) arms a 15-minute timer on the removed session → client reconnects with the same terminalId (URL-param id, reused by the same tab) → new session S2 under X → timer fires and release('X') kills S2. release() clears the registered session's timer, not the stale one. Fix: identity-check this.sessions.get(terminalId) === session in both the detach closure and the reclaim callback (plus a disposed check), with a release-then-detach-then-reuse regression test.

🟡 3. 裸 spawned.kill()——正是仓库文档记载不够用的那种 kill

packages/core/src/services/web-terminal-registry.ts:152kill: () => spawned.kill())与 :281;对照 packages/core/src/services/shellExecutionService.ts:525-545(ConPTY 下 pty.kill() 只拆掉伪控制台宿主、不杀 shell 本体,曾导致 Windows 空闲 shell 堆积至 OOM;故用 taskkill 树杀)与 :637-640(POSIX 进程组杀 process.kill(-pid, 'SIGKILL')

Web 终端是这个已知缺陷的最坏租户:长驻交互 shell + 15 分钟回收反复"杀"分离会话。Windows 上被回收的 shell 进程会按既有 issue 的模式堆积;POSIX 上 shell 的后台子进程会作为孤儿存活。另外 onData/onExit 注册(:171/:186)丢弃了 node-pty 返回的 disposable——若 kill 未落地,已释放会话的闭包还会继续缓冲至多 4 MB。
修复:把 shellExecutionService 里现成的平台清理策略(Windows taskkill 树杀 + ConPTY 宿主杀;POSIX 进程组杀)抽出来复用,并在 release 时 dispose onData/onExit

EN: Bare spawned.kill() is exactly the kill the codebase documents as insufficient: under ConPTY it tears down only the pseudo-console host, not the shell itself (the Windows idle-shell OOM pattern), which is why shellExecutionService uses tree taskkill on Windows and process-group SIGKILL on POSIX. The web terminal is the worst-case tenant: long-lived interactive shells plus repeated reclaim kills. Also, the onData/onExit disposables are discarded, so a released session whose kill didn't land keeps buffering up to 4 MB in a detached closure. Fix: extract and reuse the existing platform cleanup strategies; dispose the pty listeners on release.

🟡 4. web_terminal 无条件通告——在端点不存在或 PTY 不可用的环境里也显示入口

packages/cli/src/serve/capabilities.ts:449(基线条目,不在 CONDITIONAL_SERVE_FEATURES);packages/cli/src/serve/acp-http/index.ts:642-643QWEN_SERVE_ACP_HTTP=0 时根本不挂 WS upgrade 监听);packages/core/src/utils/getPty.ts:22-24(Bun 下返回 null)

/terminal 完全依赖 ACP-HTTP 的 upgrade 监听器,QWEN_SERVE_ACP_HTTP=0 姿态下端点不存在,capability 却照常通告,Web Shell 显示入口、每次连接都失败;Bun 运行时下 PTY 恒不可用同样如此。同一传输上的兄弟能力是正确做法:voice_transcribevoiceWsAvailable !== false 为条件、realtime_voiceacpHttpEnabled === true 为条件(capabilities.ts:667-674)。
修复:给 web_terminal 加同类条件谓词(至少 acpHttpEnabled),并按兄弟条目的样式补上契约注释;顺带把 server.test.ts 里"for frontend version compatibility"的测试标题改成与实际断言(无条件通告 → 条件通告)匹配的措辞。

EN: /terminal lives exclusively on the ACP-HTTP upgrade listener, yet web_terminal is a baseline capability: with QWEN_SERVE_ACP_HTTP=0 the endpoint does not exist, and under Bun getPty() is null, but the entry still shows and every connect fails. The siblings on the same transport do it right (voice_transcribe gated on voiceWsAvailable, realtime_voice on acpHttpEnabled). Fix: make web_terminal conditional (at least on acpHttpEnabled), add a contract comment like its siblings, and adjust the test title accordingly.

🟡 5. 初始 resize 竞态:PTY 可能被钉在 80×24 直到下次面板缩放

packages/web-shell/client/components/terminal/TerminalPanel.tsx:107-114(首个 fit() 推迟到 rAF)、:192-201(onopen 立即发 term.cols/term.rows)、:247-269(ResizeObserver 观察的是容器)

首次 fit() 在 rAF 里(约 16ms 后),而 WebSocket 同一 effect 内同步创建;loopback 下 onopen 握手可以先于首帧完成,此时发出的 resize 是 xterm 默认 80×24。之后 rAF 的 fit() 改变的是 canvas 而非容器尺寸,ResizeObserver 不触发,没有补发——结果界面 137×32、PTY 80×24(折行/光标错位),直到用户手动缩放面板或重连才纠正。
修复:把 resize 控制帧改由 term.onResize(({cols, rows}) => ...) 驱动(fit() 引发的尺寸变化也会触发它),observer 只负责触发 fit();或在首次 fit() 后若 ws.readyState === OPEN 补发一帧。

EN: The first fit() is deferred to requestAnimationFrame while the WebSocket is created synchronously in the same effect; on loopback the onopen handshake can complete first, sending the xterm defaults (80×24). The later fit() changes the canvas, not the observed container, so no corrective resize frame is ever sent — the PTY stays 80×24 (wrapped output, misplaced cursor) until the panel is resized or a reconnect happens. Fix: drive the resize control frame from term.onResize (fires for fit() too), or send a resize frame right after the initial fit() when the socket is OPEN.

🟡 6. 信任撤销/运行时替换后,空闲挂载的终端不会被释放

packages/cli/src/serve/run-qwen-serve.ts:5683-5701(释放只接在 beginDrain);packages/cli/src/serve/workspace-trust-reconciler.ts:113,305(信任变更走 beginReplacement);packages/cli/src/serve/routes/terminal.ts:207-232(再验证只发生在客户端发消息时)

releaseWebTerminalsForWorkspace 只在 beginDrain 钩子里被调用,而信任重协调通过 beginReplacement 替换运行时、不走 drain;路由侧的工作区再验证又只在收到 resize/输入时执行。于是一个挂载中但空闲(无按键)的终端,在其运行时被替换或降为不受信后,输出监听会压住 15 分钟空闲回收,PTY 持续流式输出——直到下一次按键才被 4002 关掉。这违背设计文档"每个终端由一个活的、受信任的工作区运行时拥有"的不变量。
修复:推式失效——在替换/撤销时通知注册表或路由,对受影响 cwd 关闭挂载 socket(4002)并释放;至少在设计文档中明确"空闲窗口内信任变更延迟生效"。

EN: Terminal release is wired only into beginDrain, but trust reconciliation replaces runtimes via beginReplacement, and the route re-validates the workspace only when the client sends a message. An attached-but-idle terminal therefore survives a trust revocation / runtime replacement indefinitely (its output listener suppresses idle reclaim), streaming until the next keystroke triggers the 4002 path — violating the design doc's "owned by one active, trusted workspace runtime" invariant. Fix: push-based invalidation on replacement/revocation (close attached sockets with 4002 and release for the affected cwd), or document the delayed-enforcement window explicitly.

🟢 7. release() 漏掉 CLOSING 状态

packages/web-shell/client/components/terminal/TerminalPanel.tsx:224-235

OPEN(发送 release + close)、CONNECTING(onopen 补发)、CLOSED/不存在(新建连接再释放)都有分支,唯独 readyState === CLOSING(例如服务端发起关闭的握手中用户关了页签)两个分支都不命中,release 帧永远发不出去,PTY 要等 15 分钟回收——这是唯一违背"关闭页签即杀 PTY"文档承诺的路径。影响有界;修复:CLOSING 分支走与 CLOSED 相同的 connect-then-release。

EN: release() handles OPEN, CONNECTING and CLOSED/absent, but when the socket is mid-close-handshake (CLOSING) neither branch runs and no release frame is ever sent — the PTY survives until the 15-minute reclaim, the one tab-close path that violates the doc's "closing a terminal tab kills the PTY". Bounded impact; fix by treating CLOSING like CLOSED (connect-then-release).

🟢 8. 已退出会话占满 15 分钟的并发槽与滚动缓冲

packages/core/src/services/web-terminal-registry.ts:186-190(onExit 不(重)排回收)与 :100-105(上限 8 计入一切在册会话)

只有干净关闭页签会发 release;异常断连后 shell 退出的会话会在 sessions 里躺满 15 分钟、各占一个并发槽和至多 4 MB。8 个这样的会话就能让新终端得到"Web terminal limit reached"长达 15 分钟。便宜修法:onExit 时无监听者(或从已退出会话 detach 时)改用短得多的回收 TTL——进程已不在,只剩重放价值。

EN: Only a clean tab close sends release; an exited session left by an abnormal disconnect sits in sessions for the full 15 minutes, holding a concurrency slot (cap 8) and up to 4 MB each — eight of them block new terminals for up to 15 minutes. Cheap fix: when onExit fires with no listeners (or on detach from an already-exited session), schedule a much shorter TTL — the process is gone; only replay value remains.

🟢 9. 单个超 4 MB 输出块会被整块丢弃

packages/core/src/services/web-terminal-registry.ts:171-184(驱逐循环把超大新块自己 shift 掉);web-terminal-registry.test.ts:204-214(测试固化了 4.5 MB 块后 output === ''

一次大粘贴/大输出会抹掉全部滚动缓冲而不是保留末尾 4 MB。建议:当最新块单独超过 MAX_BUFFER_BYTES 时保留其尾部切片。

EN: A single chunk larger than the 4 MB cap is evicted wholesale — one large paste erases all scrollback instead of keeping the trailing 4 MB. Retain the tail slice when the newest chunk alone exceeds MAX_BUFFER_BYTES.

🟢 10. 退出 signal 被丢弃

packages/core/src/services/web-terminal-registry.ts:186-190(只存 exitCode)与 :222-231(快照同样只暴露 exitCode)

node-pty 在信号终止时可能报 exitCode: 0 + 非零 signal(shellExecutionService 有文档记载);被信号杀掉的 shell 会被重放成干净的 exit 0。建议把 signal 记入会话并加入 WebTerminalSnapshot

EN: Only exitCode is stored and snapshotted; node-pty can report exitCode: 0 with a non-zero signal on signal termination (documented in shellExecutionService), so a signal-killed shell replays as a clean exit. Record signal on the session and include it in the snapshot.

🟢 11. 一致性残留:parseControl 注释、文档措辞、4003、术语

  • packages/cli/src/serve/routes/terminal.ts:60-62 catch 注释说非法控制帧"保留为终端输入",实际处理器将其丢弃(:198-199,测试也固化了丢弃)——行为更安全,注释过时。
  • docs/design/web-terminal-lifecycle.md 说文本帧"保留"给控制消息,但服务端实际接受任意非控制文本帧作为终端输入;要么收紧服务端、要么软化文档。
  • 客户端 NON_RETRYABLE_CLOSE_CODES 仍含 4003(TerminalPanel.tsx:24),而服务端从不以 4003 关闭(全库唯一的 4003 发射方是无关的 Live Host 协议)——上一轮设计迭代的残留,删除或加注释。
  • 术语碰撞:docs/developers/daemon-client-adapters/web-ui.md 描述过一个"不是 raw PTY 代理"的 web terminal;本 PR 交付的恰是同名 raw PTY 代理,建议在新设计文档加一行消歧。

EN: Stale comment — parseControl's catch says malformed frames are "preserved as terminal input" but the handler drops them (:198-199, tests pin the drop). Doc overstatement — the design doc says text frames are "reserved" for control messages, but the server accepts any non-control text frame as PTY input; tighten the server or soften the doc. Dead code — the client's non-retryable set still contains 4003 (TerminalPanel.tsx:24) though the server never closes with it (the only 4003 emitter repo-wide is the unrelated Live Host protocol); drop or comment it. Terminology — the adapter docs describe a "not a raw PTY proxy" web terminal; a one-line disambiguation in the new design doc would prevent confusion.

🟢 12. 终端内提示语绕过 i18n + bearer 编码器复制

  • TerminalPanel.tsx:139,145,214[Process exited with code …][Error: …][Connection lost — reconnecting…] 硬编码英文写进终端缓冲;其余新文案都做了中英双语。可经现有 i18n hook 本地化后写入。
  • TerminalPanel.tsx:37-48voice/useVoiceCapture.ts:89-100bearerSubprotocol() 逐字节相同,而 daemon 侧的同步注释(acp-http/index.ts:257-259)只点名 voice 是规范副本——抽共享 helper,或至少更新同步注释。

EN: Hardcoded English notices are written into the terminal buffer (TerminalPanel.tsx:139,145,214) while every other new string is localized EN/ZH — route them through the i18n hook. The bearerSubprotocol() encoder is a byte-for-byte copy of the voice client's, and the daemon's sync comment still names only the voice copy as canonical — extract a shared helper or update the comment.

🟢 13. 客户端小健壮性项

  • TerminalPanel.tsx:110-113:首次 fit() 有 try/catch,catch 里安排的 rAF 重试没有——页签在第二帧前关闭会对已 dispose 的终端抛未捕获异常。补同样的保护或检查 disposed。
  • TerminalPanel.tsx:160-166:cleanup 里 term.dispose() 与 socket 真正关闭之间,缓冲消息仍会到达并调用已 dispose 终端的 write(xterm 只告警不崩);加一行 if (disposed) return; 即闭环。
  • TerminalPanel.tsx:98fontFamily: 'var(--font-mono, ...)' 大概率不作用于 canvas 字形渲染——CanvasRenderingContext2D.font 不解析 CSS 变量,非法值被静默忽略,而 DOM 侧度量却解析该变量,可能字体/度量不匹配。用字面字体栈或 getComputedStyle 解析后传入。

EN: The fit() retry scheduled inside the catch branch is itself unguarded and can throw after unmount. handleMessage lacks a disposed guard, so buffered messages between term.dispose() and socket close still hit the disposed terminal. fontFamily: 'var(--font-mono, ...)' almost certainly never applies to canvas glyph rendering — CanvasRenderingContext2D.font does not resolve CSS variables and silently ignores invalid values, while DOM measurement does resolve it, risking a font/metrics mismatch; pass a literal stack or resolve via getComputedStyle.


💡 建议 / Suggestions

  • 每次按键都重跑工作区解析器(terminal.ts:222),非标 selector 会逐键付出一次同步 realpathSync.native;可缓存已解析运行时、按廉价条件复核。/ The workspace resolver re-runs on every keystroke (terminal.ts:222); a non-canonical selector pays a synchronous realpathSync.native per key. Cache the resolved runtime and re-validate cheaply.
  • 连接从未成功(如 1006 循环)时无限退避重试;可对"从未 OPEN"的连续失败设上限或 N 次后在终端内报错。/ Reconnect retries forever when the connection never opens (e.g. repeated 1006); cap never-opened attempts or surface an error after N failures.
  • vite dev 代理 /terminal 是裸前缀(vite.config.ts:121-123),也匹配 /terminals 等并可能遮蔽未来同名顶层路径——voice 的注释专门警告过这个陷阱;改 '^/terminal/?$'。/ The dev proxy /terminal is a bare prefix (also matches /terminals, may shadow future top-level paths) — exactly the trap the voice comment warns about; use '^/terminal/?$'.
  • 其他小项:挂载后的输入帧在 10 MB maxPayload 下没有更小的单帧上限(terminal.ts:233 直写 PTY);terminalId 由客户端提供,同租户内可抢注(受害者得到不可重试的 4001,影响低);ArtifactPanel 的终端入口只查 onOpenTerminal、未像兄弟入口那样同时查 items.includes('terminal')(App 层门控使其当前不可达,纵深防御可补);注册表测试可补:spawn 失败后槽位释放、getPty reject 分支、FIFO 驱逐顺序、未挂载即回收、dispose 已建立会话。

EN (grouped): no per-message cap below the 10 MB maxPayload on post-attach input (terminal.ts:233 writes straight to the PTY); client-supplied terminalId is squat-able within the shared-tenant daemon (victim gets a non-retryable 4001; low impact); the ArtifactPanel terminal entry checks only onOpenTerminal, not items.includes('terminal') like its siblings (unreachable today via the App-level gate; defense in depth); registry tests worth adding: cap-slot freeing after spawn failure, the getPty-rejection branch, FIFO eviction order, never-attached reclaim, and dispose of established sessions.


🎉 值得点名 / Highlights

  • 共享升级门控(路径白名单、Host/Origin/CSWSH、bearer 哈希比较)在 socket 到达路由前全部执行,/terminal 无法绕过;bearer 子协议从不被回显,客户端只递交非秘密标记(TerminalPanel.tsx:50-53)。
  • 客户端 cwd 确实只是 selector:PTY 的 cwd/env 全部来自解析出的受信活体运行时(server.ts:2946-2961 → terminal.ts:144-148),无注入面;terminalId↔工作区绑定在挂载与释放两侧都防跨工作区劫持。
  • cancelledCreations + 上限计入创建中会话 + finishCreating 覆盖全部退出路径——创建/释放竞态干净无泄漏;排空/停机释放接线完整,bypassPrimaryDrain 做成通用 ExtraWsRoute 属性且双向有测试。
  • 帧协议防碰撞:键盘输入恒为二进制帧、控制恒为 NUL 前缀文本帧,粘贴的 \x00{"type":"release"} 无法释放终端(有测试证明)。
  • 环境归一化作用域正确:copy-then-delete,nvm 的 npm_config_prefix 修复不触碰运行时环境本体(web-terminal-registry.ts:127-131,有测试)。
  • 客户端双门控(宿主项 + capability)合取、capability 晚到时 fail-closed(=== true),重连重放前先 term.reset() 防重复,关闭码集合与服务端契约精确镜像。

EN: Shared upgrade gates (path allowlist, Host/Origin/CSWSH, bearer hash-compare) all run before the socket reaches the route — /terminal cannot bypass them, and the bearer subprotocol is never echoed back. Client cwd is truly only a selector: PTY cwd/env come exclusively from the resolved trusted live runtime, with terminalId↔workspace binding enforced on both attach and release. cancelledCreations + cap counting in-flight creations + finishCreating on every exit path — the create/release race is clean; drain/shutdown release wiring is complete, and bypassPrimaryDrain is a general ExtraWsRoute property tested in both directions. Collision-proof framing (binary input vs NUL-prefixed control; a pasted release frame cannot release — tested). Env normalization is copy-then-delete, so the nvm fix never touches the runtime env. Client dual gating is conjunctive and fail-closed on late capabilities, replay is preceded by term.reset(), and the close-code set mirrors the server contract exactly.

@wenshao

wenshao commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Local verification on Linux — real daemon + real browser

Since the PR table marks 🐧 Linux as untested, I built a full two-arm environment on Linux and ran the reviewer test plan end to end against a real qwen serve daemon and a real Chromium, plus protocol-level probes on /terminal.

Setup — Debian 13 / kernel 6.12, x86_64, Node 22.22.2, PTY backend @lydell/node-pty (linux-x64).

Arm Build Serves
PR daemon worktree at c0114c0 (PR head), node esbuild.config.jsdist/cli.js qwen serve --port 4180 --workspace ws-a --no-web
Base daemon worktree at merge base beb3833, same build qwen serve --port 4181 …
PR client packages/web-shell vite dev server, QWEN_DAEMON_URL=:4180 :5291
Base client merge-base packages/web-shell vite, QWEN_DAEMON_URL=:4180 :5292
Skew client PR packages/web-shell vite, QWEN_DAEMON_URL=:4181 :5293

Everything below is browser → vite proxy → real daemon → real PTY; no mocks, no page.route.

Reviewer test plan — all 7 items pass on Linux

# Test-plan item Result
1 Terminal appears in the add menu and the empty-state actions ✅ both surfaces
2 Two tabs, each in the active workspace, independent content ✅ distinct shell PIDs, both cwd = workspace
3 Interactive CLI survives a tab switch top still rendering and running after switching away and back
4 Resize reaches the PTY, terminal stays interactive stty size 48×74 → 31×56 on viewport resize; out-of-range/zero/non-integer resize frames ignored
5 Disconnect/reconnect replays once, no duplication, no frozen input ✅ for a transport drop (see finding 2 for a full page reload)
6 Closing a tab releases the PTY; a new terminal still works ✅ shell process gone, next terminal spawns a new PID
7 Entry hidden when the action is omitted or the daemon lacks web_terminal ✅ all three arms

entry gating

two terminals

Protocol and lifecycle probes (raw WebSocket client against the live daemon)

Area Result
Auth no token → 401; wrong token → 401; browser qwen-bearer.* subprotocol → accepted
CSRF / rebinding cross-origin Origin403; foreign Host403; same-origin → 101
Workspace binding unregistered selector → 4002; a terminal id created in workspace A re-attached with cwd=B4002 Terminal workspace mismatch, original session untouched
Trust gate DO_NOT_TRUST workspace → 4002; control: trusted secondary workspace accepted and its PTY starts in that workspace's cwd
Concurrency cap 8 concurrent OK, 9th → 4001 + Web terminal limit reached; releasing one frees the slot
Exit replay exit 42{"type":"exit","exitCode":42} + close 4000; reconnect replays scrollback and the exit frame exactly once
Environment TERM=xterm-256color, COLORTERM=truecolor; npm_config_prefix, NO_COLOR, FORCE_COLOR stripped
Workspace drain DELETE /workspaces/:id releases that workspace's terminals; re-attach → 4002
Idle reclaim measured over a real 16-minute detachment: session gone and PTY killed after the 15-minute timeout
Daemon shutdown SIGTERM to the daemon kills every live PTY — no orphaned shells
Scrollback cap 2.95 MB of output → replay capped at 1.92 MB, first byte +7 ms, interactive immediately
Output pressure yes streamed 378 MB in 8 s with flat daemon RSS; after Ctrl-C on a 3 s flood the prompt is back in 8.8 s
Narrow/drawer layout drawer variant works, exactly one terminal instance mounts, and the session survives the drawer → docked switch
Merge-base daemon /terminal is not routed (upgrade destroyed) and web_terminal is absent from /capabilities

Tests and static checks in the PR worktree: web-terminal-registry.test.ts 15 ✓, terminal.test.ts 17 ✓, workspace-qualified-acp.test.ts 50 ✓, server.test.ts 1080 ✓, TerminalPanel + ArtifactPanel 68 ✓, App.test.tsx 544 ✓. ESLint clean on all 24 changed .ts/.tsx files. tsc on packages/core clean; the one packages/web-shell error (App.tsx TS2345 on handleSetMode) reproduces identically on the merge base, and the packages/cli TS6305 is a local audio-capture/dist artifact — neither is from this PR.

Finding 1 (worth fixing before merge) — closing a tab whose shell already exited never releases the session

Reproduced through the real UI on a verified-fresh daemon: open a terminal, type exit, close the tab. Eight of those ordinary cycles exhaust the whole 8-terminal budget, and the next terminal fails for 15 minutes even though the user closed every tab and no PTY process is alive.

limit reached

Proof at the daemon level: after the UI closes an exited tab, re-attaching to that same terminal id still replays {"type":"exit","exitCode":0} — the session is still in the registry. Control: closing a tab whose shell is still running does release it (re-attach finds nothing).

Root cause is the ordering in packages/cli/src/serve/routes/terminal.ts. TerminalPanel.release() sees a socket in CLOSED state (the daemon closed it with 4000 when the shell exited), so it opens a fresh WebSocket and sends release from onopen. On that reconnect onConnection never awaits anything — readSnapshot() returns an existing session, so it runs straight through to finishExited(), whose cleanup() detaches the message handler and closes with 4000 before the client's frame is ever read. releaseRequested is only consulted on the create path, so a release for an exited session is unreachable.

Two shapes of fix that both look small:

  • let the client ask for the release in the handshake (&release=1 on the reconnect URL), which the route can honour before it replays anything; or
  • on the exited-snapshot branch, defer the cleanup()/close() by one macrotask so a release frame that lands right after the upgrade is still processed.

Finding 2 (worth a note in the PR description) — a page reload orphans the PTY

artifactPanelTabs lives in a React ref (artifactPanelStateBySessionRef), so a browser reload drops the terminal tab and its terminal:<timestamp>:<n> id. Measured: after location.reload() there is no terminal tab and no way to reach the still-running PTY, which then holds one of the 8 slots until the 15-minute reclaim kills it — taking whatever was running with it. Test-plan item 5 holds for a WebSocket-level drop (verified: replays once, stays interactive) but not for a full page reload, which is how I'd read "reconnect the page". Either persist the tab ids per session, or say explicitly in the docs that a reload ends the terminal.

Finding 3 (design question, not a blocker) — no operator opt-out

On this default daemon, /capabilities reports session_shell_command: false but web_terminal: true. The narrower "run one shell command in a session" surface is off unless an operator turns it on, while an unrestricted interactive PTY is on for every daemon. The PTY is a raw shell spawn, so it is outside approval mode, tool permissions and any shell guardrails by construction — which is what a terminal should be, but it does mean a token holder on a --host-exposed daemon gets an interactive shell that the operator cannot disable. Worth considering a toggle in the same style as sessionShellCommandEnabled.

Smaller observations

  • The 64 KB pre-create input guard is unit-tested but never engaged live: registry.create() resolves without yielding to the I/O phase once node-pty is cached, so no inbound frame is ever buffered. Harmless, just effectively unreachable.
  • packages/core/src/config/config-session-env.test.ts is a drive-by Prettier reformat unrelated to this feature; the NOTICES.txt growth is the expected regeneration for the two new @xterm packages.

Not covered

Windows, non-UTF-8 input from non-browser clients, and third-party TUIs that do not redraw on SIGWINCH.

Overall the daemon side is in good shape — auth, CSRF, trust, workspace binding, drain, reclaim and shutdown all behave on Linux. I would like finding 1 fixed before merge, since it turns an ordinary usage pattern into a 15-minute dead end.

中文说明

Linux 本地验证 —— 真实 daemon + 真实浏览器

PR 的测试矩阵里 🐧 Linux 标注为未测试,所以我在 Linux 上搭了完整的双臂环境,用真实 qwen serve daemon 和真实 Chromium 跑完了整份评审验证计划,并补充了 /terminal 的协议层探针。

环境:Debian 13 / 内核 6.12,x86_64,Node 22.22.2,PTY 后端 @lydell/node-pty(linux-x64)。

分臂 构建 服务
PR daemon c0114c0(PR HEAD)worktree,node esbuild.config.jsdist/cli.js qwen serve --port 4180 --workspace ws-a --no-web
Base daemon merge base beb3833 worktree,同样构建 qwen serve --port 4181 …
PR 客户端 packages/web-shell vite dev server,QWEN_DAEMON_URL=:4180 :5291
Base 客户端 merge-base 的 packages/web-shell vite,QWEN_DAEMON_URL=:4180 :5292
版本错配客户端 PR 的 packages/web-shell vite,QWEN_DAEMON_URL=:4181 :5293

下面所有结果都是 浏览器 → vite 代理 → 真实 daemon → 真实 PTY 的链路,没有任何 mock,也没有 page.route

评审验证计划 7 项在 Linux 上全部通过

# 验证项 结果
1 添加菜单和空状态操作都出现 Terminal ✅ 两处入口都有
2 两个页签各自在当前工作区、内容独立 ✅ shell PID 不同,两者 cwd 都是工作区
3 交互式 CLI 跨页签切换仍存活 top 切走再切回后画面和进程都完整
4 resize 传到 PTY,终端仍可交互 ✅ 视口缩放后 stty size 由 48×74 变为 31×56;超范围/为 0/非整数的 resize 帧被忽略
5 断连重连只重放一次、不重复、不冻结 ✅ 传输层断连成立(整页刷新的情况见问题 2)
6 关闭页签释放 PTY,之后仍能新建 ✅ shell 进程随即消失,下一个终端是新 PID
7 省略 action 或 daemon 无 web_terminal 时入口隐藏 ✅ 三个分臂都验证

(图见上方英文部分。)

协议与生命周期探针(裸 WebSocket 客户端直连真实 daemon)

方面 结果
认证 无 token → 401;错误 token → 401;浏览器 qwen-bearer.* 子协议 → 通过
CSRF / DNS rebinding 跨域 Origin403;伪造 Host403;同源 → 101
工作区绑定 未注册 selector → 4002;在工作区 A 创建的 terminal id 用 cwd=B 挂载 → 4002 Terminal workspace mismatch,原会话不受影响
信任门 DO_NOT_TRUST 工作区 → 4002;对照组:受信任的次级工作区可接受,PTY 从该工作区 cwd 启动
并发上限 8 个并发正常,第 9 个 → 4001 + Web terminal limit reached;释放一个后名额恢复
退出重放 exit 42{"type":"exit","exitCode":42} + 4000 关闭;重连后滚动内容和 exit 帧恰好各重放一次
环境变量 TERM=xterm-256colorCOLORTERM=truecolornpm_config_prefixNO_COLORFORCE_COLOR 均被清除
工作区排空 DELETE /workspaces/:id 会释放该工作区的终端;再挂载 → 4002
空闲回收 真实等待 16 分钟:15 分钟超时后会话消失、PTY 被杀
daemon 关闭 向 daemon 发 SIGTERM 后所有存活 PTY 都被杀,无游离 shell
滚动内容上限 产生 2.95 MB 输出后,重放被截到 1.92 MB,首字节 +7 ms,随即可交互
输出压力 yes 在 8 秒内推送 378 MB,daemon RSS 无增长;对 3 秒洪泛按 Ctrl-C 后 8.8 秒回到提示符
窄屏/抽屉布局 抽屉形态可用,只挂载一个终端实例,抽屉 → 停靠切换后会话仍在
Merge-base daemon /terminal 未挂载(upgrade 被 destroy),/capabilities 中没有 web_terminal

PR worktree 内的测试与静态检查:web-terminal-registry.test.ts 15 ✓、terminal.test.ts 17 ✓、workspace-qualified-acp.test.ts 50 ✓、server.test.ts 1080 ✓、TerminalPanel + ArtifactPanel 68 ✓、App.test.tsx 544 ✓。24 个改动的 .ts/.tsx 文件 ESLint 全绿。packages/coretsc 干净;packages/web-shell 唯一那条 App.tsx TS2345handleSetMode)在 merge base 上一模一样地复现,packages/cliTS6305 是本地 audio-capture/dist 未构建导致的,两者都与本 PR 无关。

问题 1(建议合并前修复)—— shell 已退出后再关闭页签,会话永远不会被释放

在验证过确实是全新启动的 daemon 上通过真实 UI 复现:打开终端 → 输入 exit → 关闭页签。这样普通的 8 次循环就会耗尽全部 8 个终端名额,尽管用户把每个页签都关掉了、也没有任何 PTY 进程存活,接下来的 15 分钟内都无法再打开终端。

daemon 层的证据:UI 关闭已退出的页签后,用同一个 terminal id 重新挂载,仍然会重放 {"type":"exit","exitCode":0},说明会话还在注册表里。对照组:关闭一个 shell 仍在运行的页签,会话确实被释放(重新挂载什么都没有)。

根因在 packages/cli/src/serve/routes/terminal.ts 的时序。shell 退出时 daemon 已用 4000 关闭了连接,于是 TerminalPanel.release() 看到套接字处于 CLOSED,会新建一个 WebSocket 并在 onopen 里发送 release。而这条重连路径上 onConnection 不会 await 任何东西 —— readSnapshot() 返回已存在的会话,代码直接走到 finishExited(),其中的 cleanup() 先摘掉 message 处理器再以 4000 关闭,客户端那一帧根本读不到。releaseRequested 只在创建路径上被检查,所以对已退出会话的 release 是不可达的。

两种看起来都很小的修法:

  • 让客户端在握手阶段就表达释放意图(重连 URL 上带 &release=1),路由在重放任何内容之前先处理;或
  • 在“已退出快照”分支里把 cleanup()/close() 推迟一个宏任务,使刚握手后到达的 release 帧仍能被处理。

问题 2(建议在 PR 描述里说明)—— 整页刷新会遗留孤儿 PTY

artifactPanelTabs 保存在 React ref(artifactPanelStateBySessionRef)里,因此浏览器刷新会丢掉终端页签及其 terminal:<时间戳>:<序号> id。实测:location.reload() 之后没有终端页签,也没有任何途径回到仍在运行的 PTY;它会一直占用 8 个名额中的一个,直到 15 分钟回收把它连同里面正在跑的东西一起杀掉。验证计划第 5 项在 WebSocket 层断连时成立(已验证:只重放一次、仍可交互),但整页刷新不成立,而“重新连接页面”按字面理解通常就是刷新。要么按会话持久化页签 id,要么在文档里明确刷新即终止终端。

问题 3(设计问题,不阻塞)—— 缺少运维侧关闭开关

在这台默认配置的 daemon 上,/capabilitiessession_shell_commandfalse,而 web_terminaltrue。范围更窄的“在会话里执行一条 shell 命令”默认关闭、需要运维显式开启,而不受限制的交互式 PTY 却对每个 daemon 默认开启。PTY 是直接 spawn 的裸 shell,因此在结构上就绕过了审批模式、工具权限和一切 shell 护栏 —— 终端本该如此,但也意味着在 --host 暴露的 daemon 上,拿到 token 的人就能得到一个运维无法关闭的交互式 shell。建议考虑加一个与 sessionShellCommandEnabled 同风格的开关。

其它小观察

  • 64 KB 的创建前输入上限有单测覆盖,但线上从未触发:node-pty 被缓存后 registry.create() 不会让出到 I/O 阶段,因此不会有任何入站帧被缓冲。无害,只是实际不可达。
  • packages/core/src/config/config-session-env.test.ts 是与本功能无关的顺手 Prettier 格式化;NOTICES.txt 的增量是两个新增 @xterm 包的正常再生成。

未覆盖

Windows、非浏览器客户端的非 UTF-8 输入,以及不响应 SIGWINCH 自行重绘的第三方 TUI。

整体上 daemon 侧状态不错 —— 认证、CSRF、信任、工作区绑定、排空、回收和关闭在 Linux 上都符合预期。我希望问题 1 能在合并前修掉,因为它会把一个很常见的使用方式变成 15 分钟的死路。


🤖 Generated with Claude Code — Claude Opus 5 (1M context)

Comment thread packages/cli/src/serve/routes/terminal.ts Outdated
Comment thread packages/cli/src/serve/routes/terminal.ts
Comment thread packages/cli/src/serve/routes/terminal.ts Outdated
Comment thread packages/core/src/services/web-terminal-registry.ts
Comment thread packages/cli/src/serve/routes/terminal.ts
FitAddon: vi.fn(() => ({ fit: vi.fn() })),
}));
vi.mock('../../themeContext', () => ({ useTheme: () => 'light' }));
vi.mock('../../config/daemon', () => ({ getDaemonToken: () => '' }));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Pattern (5 locations): the client suite leaves the terminal's contract paths unpinned. At this location: the suite stubs the daemon token to '' for every test and never asserts that TerminalPanel offers the ['qwen-ws', 'qwen-bearer.<base64url(token)>'] subprotocols to the WebSocket constructor — the only auth channel a browser WebSocket has to the token-gated daemon (browsers cannot set Authorization on a WS; the daemon's extractUpgradeBearer rejects the upgrade with 401 without it). FakeWebSocket already captures the constructor's protocols argument, and the sibling voice feature pins exactly this (useVoiceCapture.test.tsx asserts the qwen-ws marker and the qwen-bearer. prefix). A refactor of wsProtocols() that drops, empties, or reorders the offered subprotocols ships with all tests green — and on any token-gated daemon (LAN pairing, non-loopback access, Local Control credentials) every /terminal upgrade is rejected 401 → retryable 1006 → the panel loops '[Connection lost — reconnecting…]' forever while REST/SSE/voice keep working. Fix: stub getDaemonToken to a non-empty token and assert FakeWebSocket.instances[0].protocols equals ['qwen-ws', 'qwen-bearer.' + base64url(token)].

中文说明

模式(5 处):客户端套件没有固定终端的契约路径。此处的情况:套件在所有测试中把 daemon token stub 成 '',且从未断言 TerminalPanel 向 WebSocket 构造器提供了 ['qwen-ws', 'qwen-bearer.<base64url(token)>'] 子协议——这是浏览器 WebSocket 对带 token 门禁的 daemon 唯一的认证通道(浏览器无法在 WS 上设置 Authorization;daemon 的 extractUpgradeBearer 在缺少它时以 401 拒绝升级)。FakeWebSocket 已经会捕获构造器的 protocols 参数,而兄弟 voice 功能恰好固定了这一点(useVoiceCapture.test.tsx 断言了 qwen-ws 标记和 qwen-bearer. 前缀)。如果重构 wsProtocols() 时删除、置空或调换了提供的子协议,所有测试仍会绿色出厂——而在任何带 token 门禁的 daemon 上(LAN 配对、非 loopback 访问、Local Control 凭据),每次 /terminal 升级都会被 401 拒绝 → 可重试的 1006 → 面板永远循环“连接丢失——重连中…”,而 REST/SSE/voice 照常工作。修复:把 getDaemonToken stub 成非空 token,并断言 FakeWebSocket.instances[0].protocols 等于 ['qwen-ws', 'qwen-bearer.' + base64url(token)]

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

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.

Deferred as test-only follow-up. Authenticated terminal WebSocket behavior was verified end-to-end through the Vite proxy, while the dedicated subprotocol constructor assertion is not added in this late round.

Comment on lines +106 to +108
function render(): FakeWebSocket {
act(() => {
root.render(<TerminalPanel terminalId="terminal:one" cwd="/workspace" />);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Pattern (5 locations): the client suite leaves the terminal's contract paths unpinned. At this location — the connect contract itself: the workspaceCwdcwd prop → ?cwd= URL chain that gets a /terminal connect past the route's mandatory-workspace check is asserted by no test. Both panel-level mocks capture only terminalId (App.test.tsx and ArtifactPanel.test.tsx), so dropping or misspelling cwd={tab.workspaceCwd ?? workspaceCwd} in ArtifactPanel ships green; and FakeWebSocket records url but no test ever inspects it (zero hits), while the daemon route independently reads the names back (url.searchParams.get('terminalId') / .get('cwd')) and no integration test opens /terminal. A rename at either end ships with the web-shell, cli-route, and integration suites all green — and at runtime every terminal connect fails the route's mandatory-field check → close 4002 (non-retryable) → every Terminal open becomes a permanently dead panel with zero red tests. Fix: capture the cwd prop in the panel mocks and assert the override and fallback; here, assert new URL(ws.url) has pathname === '/terminal', terminalId and cwd=/workspace.

中文说明

模式(5 处):客户端套件没有固定终端的契约路径。此处是连接契约本身:让 /terminal 连接通过路由“必须带工作区”检查的 workspaceCwdcwd prop → ?cwd= URL 链条没有任何测试断言。两个面板级 mock 都只捕获 terminalId(App.test.tsx 和 ArtifactPanel.test.tsx),因此在 ArtifactPanel 中删除或拼错 cwd={tab.workspaceCwd ?? workspaceCwd} 可以绿色出厂;FakeWebSocket 记录了 url 但没有任何测试检查它(零命中),而 daemon 路由独立地把这些参数名读回(url.searchParams.get('terminalId') / .get('cwd')),也没有集成测试打开过 /terminal。任何一端的改名都会在 web-shell、cli 路由、集成三个套件全绿的情况下出厂——运行时每次终端连接都会因路由的必填字段检查失败 → 关闭 4002(不可重试)→ 每次打开终端都变成永久死亡的面板,且没有任何测试变红。修复:在面板 mock 中捕获 cwd prop 并断言覆盖与回退两种取值;在此处断言 new URL(ws.url)pathname === '/terminal'terminalIdcwd=/workspace

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

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.

Partially addressed in 50a15d0: TerminalPanel now pins pathname, terminalId, and cwd in its connection contract test. ArtifactPanel override/fallback prop assertions are deferred.

Comment thread packages/web-shell/client/components/terminal/TerminalPanel.tsx
Comment thread packages/web-shell/client/components/terminal/TerminalPanel.tsx Outdated
@ytahdn

ytahdn commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

@wenshao @ytahdn Thanks for the detailed reviews. Commit 50a15d0a14 addresses the correctness and lifecycle issues from this round:

  • explicit close now completes a bounded release handshake, including exited and CLOSING sockets;
  • WebSocket errors are observed before async setup; PTY output and input now have bounded backpressure;
  • stale detach/reclaim callbacks cannot affect a replacement session;
  • live release removes PTY subscriptions and terminates the process tree;
  • capability advertising is conditional on the ACP HTTP transport, while the UI still requires both the host action and web_terminal;
  • initial resize, tab focus restoration, release retry, large-chunk scrollback, localized notices, disposed-state guards, and literal xterm font configuration are covered;
  • unrelated geminiChat.ts, config-session-env, and lockfile formatting churn has been removed.

Workspace trust replacement already flows through beginDrain, which releases the workspace's terminal sessions, so no second hook was added. Full page reload intentionally detaches sessions for reconnect and the documented idle reclaim; LRU tab eviction and explicit tab close release immediately. We did not reintroduce QWEN_WEB_TERMINAL: the agreed product contract is host action + advertised capability, with authentication and workspace trust at the route.

The Vite proxy remains /terminal intentionally: the anchored regexp form did not proxy WebSocket upgrades under the current Vite setup. The daemon still validates the exact route, so prefixed paths are not accepted by the backend.

Remaining mutation-test expansions, signal metadata, reconnect-policy tuning, and helper deduplication are non-critical suggestions after several review rounds; I replied on those threads and left them open for follow-up instead of widening this PR further.

Verified with the focused registry (18), route (23), and client (13) tests, a full install/build, and a real Vite-to-daemon terminal session (prompt, command I/O, release, reconnect).

@ytahdn

ytahdn commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator Author

E2E verification for 4b1f855:

  • Started the PR worktree daemon and opened the real Web Shell.
  • Opened two terminal tabs, ran distinct commands in each, switched between them, and confirmed each tab preserved its own output.
  • Resized the browser between compact and expanded viewports and confirmed the terminal remained interactive without duplicated sessions.
  • Verified the greater-than-256-KiB real-PTY input/reconnect path, Shadow DOM terminal shortcut handling, and WebSocket heartbeat cleanup with focused regression probes.
  • Local checks passed: build via install/prepare, typecheck, lint, CLI terminal route 26/26, core registry 19/19, selected Web Shell tests 12/12.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed.

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

Not reviewed: reverse audit — stopped after round 4 of 5 without two consecutive dry rounds; every round reported findings.

Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:

  • packages/core/src/services/web-terminal-registry.test.ts:424 — [review] shared single PTY mock leaves multi-session kill attribution unpinned (wrong-session kill mutant ships 19/19 green)
  • packages/cli/src/serve/routes/terminal.test.ts:401 — [review] create-failure releaseRequested precedence branch exercised by no test (probe-confirmed, mutant ships green)
  • packages/cli/src/serve/routes/terminal.test.ts:498 — [review] cleanup() in the write-failure branch unpinned (mutant ships 26/26 green; stale listener stays on live session)
  • packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx:392 — [review] inactive terminal panes' terminalPaneHidden class and aria-hidden are unasserted anywhere in the package
  • packages/cli/src/serve/routes/terminal.test.ts:443 — [review] zero-byte frames accumulate unbounded pending entries during the create-pending window (probe: 5000 empty frames -> 5000 flushes, no cap)
  • packages/cli/src/serve/routes/terminal.test.ts:496 — [review] no test pins that the 64 KiB pending-input cap stops applying post-attach (ws.off(bufferMessage) switch unguarded)

Convergence: round 4 posted 6 inline comment(s), 6 of them reported for the first time; the previous round posted 24 (6 new). Findings keep coming back to the same files: packages/web-shell/client/App.tsx (findings in rounds 1, 3; 2 more now); packages/cli/src/serve/routes/terminal.ts (findings in rounds 2, 3; 1 more now); packages/cli/src/serve/routes/terminal.test.ts (findings in round 2; 1 more now), and 2 more file(s). The rate of new findings is not falling. A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. Batching the remaining fixes and verifying them before the next push, or dropping this PR's reviews to --severity-floor critical, keeps the loop from re-deriving the same set. (Observation only — nothing was withheld from this review because of this observation.)

中文说明

仅完成部分审查,审查缺口已披露。

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

未审查:reverse audit — stopped after round 4 of 5 without two consecutive dry rounds; every round reported findings。

收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 6 条(原文未翻译,列表见上方英文部分)。

收敛情况:第 4 轮发布了 6 条行内评论,其中 6 条是首次提出;上一轮发布了 24 条(其中 6 条首次提出)。发现反复回到同一批文件:packages/web-shell/client/App.tsx(第 1、3 轮已出过发现,本轮又有 2 条);packages/cli/src/serve/routes/terminal.ts(第 2、3 轮已出过发现,本轮又有 1 条);packages/cli/src/serve/routes/terminal.test.ts(第 2 轮已出过发现,本轮又有 1 条),另有 2 个文件。新发现的产出速度没有下降。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。把剩余修复攒成一批、验证后再推送,或将本 PR 的评审降到 --severity-floor critical,可以避免循环反复推导同一组发现。(仅为观察——本轮评审未因此扣留任何内容。)

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

Comment thread packages/cli/src/serve/routes/terminal.ts Outdated
Comment thread packages/core/src/services/web-terminal-registry.ts Outdated
Comment thread packages/web-shell/client/App.tsx
Comment thread packages/web-shell/client/App.tsx
Comment on lines +166 to +168
ws.emit('pong');
await vi.advanceTimersByTimeAsync(15_000);
expect(ws.terminate).not.toHaveBeenCalled();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The heartbeat test feeds exactly one pong, so the route's persistent ws.on('pong', onPong) subscription (terminal.ts:122) is indistinguishable from a one-shot ws.once('pong', onPong) — with one pong the on/once timelines are identical (ping@15, pong rearms, ping@30, terminate@45). A ws.onws.once mutant ships the whole suite green (verified: mutant 26/26 passed), while in production every browser auto-pongs each ping and only the first pong would rearm alive, so every web-terminal socket would be terminated ~45 s after connecting — a mass disconnect on a fixed cycle. Emit a second pong after the next advance and assert terminate is still not called at t=45 s, then called only after a further 15 s without a pong.

Suggested change
ws.emit('pong');
await vi.advanceTimersByTimeAsync(15_000);
expect(ws.terminate).not.toHaveBeenCalled();
ws.emit('pong');
await vi.advanceTimersByTimeAsync(15_000);
expect(ws.terminate).not.toHaveBeenCalled();
ws.emit('pong');
await vi.advanceTimersByTimeAsync(15_000);
expect(ws.terminate).not.toHaveBeenCalled();

Fix witness: the added t=45 s not.toHaveBeenCalled() assertion goes red under the ws.once mutant, which today ships green.

中文说明

[Suggestion] 心跳测试只喂了一个 pong,因此路由里持久的 ws.on('pong', onPong) 订阅(terminal.ts:122)与一次性的 ws.once('pong', onPong) 无法区分——只有一个 pong 时 on/once 的时间线完全相同(ping@15、pong 重置、ping@30、terminate@45)。把 ws.on 突变为 ws.once 后整个测试套件依然全绿(已验证:突变体 26/26 通过),而生产中每个浏览器都会对每个 ping 自动回 pong,只有第一个 pong 会重置 alive,于是每个终端 socket 都会在连接约 45 秒后被终止——按固定周期大面积断连。修复:在下一次推进后再发一个 pong,断言 t=45s 时 terminate 仍未被调用、且只在再无 pong 的下一个 15 秒后才被调用。

修复见证:新增的 t=45s not.toHaveBeenCalled() 断言在 ws.once 突变体下会变红(该突变体目前能全绿通过)。

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

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.

Deferred as a non-blocking test-only Suggestion under the PR convergence policy after repeated review rounds. The persistent pong listener remains covered functionally; a second-pong mutation pin can follow separately.

Comment on lines +262 to +265
expect(registry.write('terminal:io', 'x'.repeat(256 * 1024))).toBe(
'written',
);
expect(registry.write('terminal:io', 'x')).toBe('backpressure');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The input-backpressure test never produces the exact-cap state (unacknowledgedInputBytes === 262144) at check time — it checks at 262145, then at 1, then at 262145 — so a >=> mutant of write()'s cap check (web-terminal-registry.ts:302) ships all 19 tests green (verified: mutant passed; an exact-cap probe fails with expected 'written' to be 'backpressure'). Under the mutant, a write arriving exactly at the cap is accepted, letting one frame of any size pass the 256 KiB steady-state unacknowledged-input cap that the R3-1 fix introduced as counter >= MAX; the exact-cap state is reachable in production (a single 256 KiB write from a zero counter). From a zero counter, assert the boundary exactly: a 256 KiB write returns 'written' and the very next 1-byte write returns 'backpressure'.

Fix witness: the added exact-cap assertion goes red under the >=> mutant, which today ships green.

中文说明

[Suggestion] 输入背压测试在检查时从未产生“恰好等于上限”的状态(unacknowledgedInputBytes === 262144)——它分别在 262145、1、262145 处检查——因此把 write() 的上限判断(web-terminal-registry.ts:302)从 >= 突变为 > 后全部 19 个测试依然全绿(已验证:突变体通过;一个“恰好上限”探针以 expected 'written' to be 'backpressure' 失败)。在该突变体下,恰好在上限时到达的写入会被接受,从而让任意大小的单帧越过 R3-1 修复以 counter >= MAX 引入的 256 KiB 稳态未确认输入上限;该“恰好上限”状态在生产中可达(从零计数器做一次 256 KiB 写入)。修复:从零计数器出发精确断言边界——一次 256 KiB 写入返回 'written',紧随其后的 1 字节写入返回 'backpressure'。

修复见证:新增的“恰好上限”断言在 >=> 突变体下会变红(该突变体目前能全绿通过)。

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

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.

Deferred as a non-blocking boundary-test Suggestion under the PR convergence policy after repeated review rounds. Current backpressure behavior and adjacent boundaries remain covered; the exact-cap assertion can follow separately.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed.

23 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • eviction release loop dead code (App.tsx:3071) — already reported (open thread R1-25, comment 3865555110)
  • release-retry bound unpinned (TerminalPanel.test.tsx:231) — already reported (open thread R2-9, comment 3865555133)
  • release dropped while a CONNECTING socket never opens (TerminalPanel.tsx:283) — already reported (open thread R1-32, comment 3865555119)
  • /terminal resolver closure (trust gate + env fallback) untested (server.ts:3017) — already reported (open thread R1-9, comment 3865555104)
  • drain/shutdown terminal wiring untested (run-qwen-serve.ts:6846) — already reported (open thread R1-8, comment 3865555093)
  • killPtyTree group-kill branch unexercised, pid:1 mocks (registry.test.ts:39) — already reported (open thread R2-15, comment 3865555169)
  • dispose() established-session teardown unpinned (registry.test.ts:335) — already reported (open thread R2-19, comment 3865555201)
  • terminal bearer-subprotocol encoder unpinned (TerminalPanel.test.tsx:35) — already reported (open thread R2-8, comment 3865555126)
  • limit-reached 1013 without error frame (terminal.ts:207) — already reported (open thread R2-10, comment 3865555138)
  • established-session cwd guard in release() untested (registry.test.ts:413) — already reported (open thread R2-20, comment 3865555208)
  • terminal tab titles reuse ordinals (App.tsx:3170) — already recorded in the round-3 review body deferral list
  • reconnect backoff doubling/10 s cap unpinned (TerminalPanel.test.tsx:200) — already recorded in the round-3 review body deferral list
  • 4001 dynamic error frame unpinned (terminal.test.ts:710) — already recorded in the round-3 review body deferral list
  • replay-cap tests pin size only, not recency/bytes (registry.test.ts:202) — already reported (open thread R2-17, comment 3865555183, and comment 3852506632)
  • 'Defaults to all actions' JSDoc falsified by the terminal opt-in (customization.tsx:132) — already recorded in the round-2 review body deferral list
  • release-during-pending × create-failure branch untested (terminal.test.ts:361) — already recorded in the round-4 review body deferral list
  • create-armed reclaim timer unpinned (registry.test.ts:464) — already reported (open thread, comment 3852506621; author deferred) and the round-3 deferral list
  • Unix SHELL passthrough untested (registry.test.ts:94) — already reported (comment 3852506627; author deferred)
  • pane visibility (terminalPaneHidden/aria-hidden) unpinned (ArtifactPanel.test.tsx:392) — already recorded in the round-4 review body deferral list
  • ResizeObserver resize path unexercised (TerminalPanel.test.tsx:103) — already recorded in the round-3 review body deferral list
  • …and 3 more (see the run report)

Not explored to full depth (tool budget reached): chunk 9: could not execute packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx — the shared worktree has no node_modules and a full monorepo instal….

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Deferred under the convergence posture (round 5, not a blocker) — recorded, not requested in this round:

  • packages/cli/src/serve/routes/terminal.ts:180 — [review] client-supplied low-entropy terminal ids enable same-workspace attach by guess/collision
  • packages/web-shell/client/components/terminal/TerminalPanel.test.tsx:180 — [review] cleanup guard keeping a CONNECTING socket alive for the banked release is unpinned
  • packages/web-shell/client/components/terminal/TerminalPanel.test.tsx:168 — [review] 1013 retryability is never asserted — only the non-retryable side is pinned
  • packages/web-shell/client/components/artifacts/ArtifactPanel.tsx:613 — [probe] active/cwd props handed to TerminalPanel are unpinned; inverted-active mutant ships green (input silently dead)
  • packages/web-shell/client/components/terminal/TerminalPanel.test.tsx:249 — [probe] connection-contract test never asserts the release param is absent from the main URL

Convergence: round 5 posted 4 inline comment(s), 4 of them reported for the first time; the previous round posted 6 (6 new). Findings keep coming back to the same files: packages/core/src/services/web-terminal-registry.ts (findings in round 4; 3 more now); packages/cli/src/serve/routes/terminal.ts (findings in round 4; 1 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. (Observation only — nothing was withheld from this review because of this observation.)

中文说明

仅完成部分审查,审查缺口已披露。

本轮确认的 23 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

未探索到全部深度(达到工具调用预算):chunk 9:could not execute packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx — the shared worktree has no node_modules and a full monorepo instal…

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

收敛姿态下延后(第 5 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。

收敛情况:第 5 轮发布了 4 条行内评论,其中 4 条是首次提出;上一轮发布了 6 条(其中 6 条首次提出)。发现反复回到同一批文件:packages/core/src/services/web-terminal-registry.ts(第 4 轮已出过发现,本轮又有 3 条);packages/cli/src/serve/routes/terminal.ts(第 4 轮已出过发现,本轮又有 1 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。(仅为观察——本轮评审未因此扣留任何内容。)

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

Comment thread packages/core/src/services/web-terminal-registry.ts Outdated
Comment thread packages/cli/src/serve/routes/terminal.ts Outdated
Comment thread packages/core/src/services/web-terminal-registry.ts Outdated
Comment thread packages/core/src/services/web-terminal-registry.ts Outdated

@chiga0 chiga0 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Scope: read terminal.ts (348 lines), web-terminal-registry.ts (437 lines), TerminalPanel.tsx (390 lines), server.ts wiring, acp-http/index.ts drain bypass, and all new test files in full. NOT reviewed: ArtifactPanel.tsx refactor depth, App.tsx beyond terminal tab lifecycle, design docs.

CI disclosure: Test (ubuntu-latest, Node 22.x) — in_progress; Test (macos-latest, Node 22.x), Test (windows-latest, Node 22.x), Integration Tests (CLI, No Sandbox) — SKIPPED. The macOS and Windows matrix jobs did not run against this head. PR author explicitly marks Linux/Windows as untested (⚠️).


Cross-check against the bot's four Critical findings

C1 — "no backpressure guard on live output fan-out" → refuted

sendOutput (terminal.ts line 31) already checks ws.bufferedAmount > MAX_SOCKET_BUFFERED_BYTES before every ws.send, and on overflow the attached listener calls cleanup() and closes with 1013 — the same pattern the bot's suggested fix prescribes, implemented at 8 MiB rather than the bot's suggested 1 MiB. The bot's probe result (45 MiB accumulated) appears inconsistent with the current code; my best read is the probe ran against an earlier version.

C2 — "error listener attached only at end of happy path" → refuted

ws.on('error', markClosed) is the first statement in onConnection (terminal.ts line 120), before any await and before all early-return branches. There is no window where the socket has zero error listeners, so Receiver errors (maxPayload exceeded, RSV violations) cannot reach uncaughtException.

C3 — "post-attach input has no byte cap" → partially refuted; one question

registry.write() returns 'backpressure' once unacknowledgedInputBytes + incoming >= 256 KB, and the route handler closes with 1013 on that result. The mechanism works by treating PTY output bytes as implicit acknowledgment of consumed input. That means a foreground program that produces no output (e.g., sleep 3600) will disconnect the client after ~256 KB of stdin — the ack never arrives so the budget never replenishes. Is that the intended UX for programs that silently consume stdin? If not, a wall-clock drain of the unacknowledged counter, or a separate per-message size cap, would be more predictable. Not a crash risk; the question is whether 256 KB is the right interaction model.

C4 — "stale reclaim timer can kill a future session reusing the same terminalId" → refuted

The detach closure returned by addOutputListener opens with if (this.sessions.get(terminalId) !== session) return (web-terminal-registry.ts line 301). After release() removes a session from the map, every subsequent detach call exits at this guard and never reaches scheduleReclaim. The timer-kills-new-session sequence the bot describes requires that guard to be absent; it is present.


One open question — drain window

createTerminalWsHandler registers with bypassPrimaryDrain: true, which lets new WebSocket upgrades through even while the primary workspace is draining. releaseWebTerminalsForWorkspace(cwd) is called once at drain time and releases only sessions that exist at that moment. A terminal created after that call (new reconnect or new tab opened concurrently) is not covered. The PTY keeps running in the workspace cwd/env; the next client message re-validates trust via resolveWorkspace(selector), so once the workspace is fully gone the connection closes with 4002. The 15-minute idle reclaim is the final backstop. This is probably acceptable for the reconnect use case the bypass was designed for, but it is worth confirming that "bypass = reconnect only, never new creation" is the intent and that the intent matches the implementation.


No confirmed blockers. Withholding approval pending CI green on the major test jobs (ubuntu in-progress, macOS/Windows/Integration SKIPPED).

Reviewed with AI assistance.

function sendOutput(ws: WebSocket, text: string): boolean {
if (
ws.readyState !== ws.OPEN ||
ws.bufferedAmount > MAX_SOCKET_BUFFERED_BYTES

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.

C1 refutation: backpressure guard is present here. sendOutput returns false when ws.bufferedAmount > MAX_SOCKET_BUFFERED_BYTES (8 MiB); the attached output listener calls cleanup() and closes with 1013 on that result. The bot's finding and probe appear to target an earlier version of the code.

closed = true;
stopHeartbeat();
};
ws.on('error', markClosed);

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.

C2 refutation: this is the first statement in onConnection, before any await and before all early-return paths. The socket has an error listener from the start; Receiver errors cannot reach uncaughtException.

session.outputListeners.add(listener);
this.clearReclaim(session);
return () => {
if (this.sessions.get(terminalId) !== session) return;

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.

C4 refutation: the identity check this.sessions.get(terminalId) !== session is already here. After release() removes the session from the map, any detach call exits at this guard and never reaches scheduleReclaim — the stale-timer-kills-new-session sequence the bot describes cannot occur.

@ytahdn

ytahdn commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Sandboxed verification: ❌ not passed — findings reported (agent verdict) - workflow run

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

Scripted assertions: 72 passed · 3 failed · 75 total

Flakiness gate: ✅ 7 changed test file(s) x 5 identical rounds, no divergence

中文 — 判定:❌ 不通过 · 报告了发现(agent 判定)

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

脚本断言:72 通过 · 3 失败 · 75 总计

抖动门:✅ 7 changed test file(s) x 5 identical rounds, no divergence

Verification report

PR #9984 — feat(web-shell): add opt-in interactive browser terminal

Verdict: findings — 75 scripted assertions executed (72 passed, 3 failed); all three failures are the carried-over finding F-2, re-measured at the new head (bootstrap /capabilities still under-reports web_terminal; no fix for it landed in this round's commits). Verified head: 7dca447c5bf9f5a32878ccb8e2d1dc1d8f14613f (merge-ref HEAD^2; base tip 7357136dd168f1c4abd3a97f4252fa7971047d0e = HEAD^1). Follow-up round — previous round verified head fdb8fbe7e3c330056c95d0decfb844f6585c9f97; the previous-finding status table leads this report. (Snapshot baseRefOid 3ca906ba… drifted from the merge-ref base as main advanced; the merge-ref checkout is canonical.)

中文 — 判定:❌ 不通过 · 报告了发现(agent 判定)

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

脚本断言:72 通过 · 3 失败 · 75 总计(3 条失败均为沿用发现 F-2,详见下表与 Findings)

  • 结论:findings。核心主张(/terminal WS 路由 + WebTerminalRegistry 提供工作区作用域、可重连重放的真实 PTY 会话)在新 head 上经 A/B 与真实 daemon E2E 再次证明成立;上一轮 F-1(release 孤儿后台进程)已被本轮新增的进程树查杀修复并实测通过(表 1 行 F-1)。
  • A/B 结论:见「A/B 表」——功能负载成立(01-ab-head-vs-base.png):base 无 capability、/terminal 拒绝;head 广播、可交互、release 杀进程;QWEN_SERVE_ACP_HTTP=0 时两者同时消失。
  • 发现:F-2 仍存在(启动后约 1.2 s 的 bootstrap 窗口 /capabilities 漏报 web_terminal,根因未变;已实测一条修复并验证,见 Findings);新增一条轻微发现(跨工作区 ?release=1 握手在拒绝释放时仍回报 4004 "Terminal released")。M4/M8 覆盖缺口仍在(非合并条件;M4 的守卫已用双工作区真实 daemon 实测行为正确)。
  • 未覆盖:逐 commit 归因、真实浏览器渲染、Windows/macOS、15 分钟回收常量实时观测、非信任工作区负路径实测、5 轮抖动门(由工作流单独执行)。

Previous-finding status table (round 1 → new head)

# Round-1 finding Severity Status at new head (7dca447c5b)
F-1 POSIX release killed only the shell's process group; background jobs survived as orphans Suggestion fixedkillPtyTree() now walks ps -axo pid=,ppid=,sess= (descendant ppids + same-session) and SIGKILLs each pid deepest-first. Re-measured live: own-pgid background child and a nested grandchild both dead after release (cells F4–F6, 02-e2e-terminal-lifecycle.png); unit test added ("kills every process in the PTY session"); mutation N1 deleting the walk is killed 21/21→20/21. Residual boundary (by design, matches real terminal close): a process that leaves the session (setsid) survives — cells K8/K9.
F-2 Bootstrap /capabilities under-reports web_terminal for ~1.4 s after "listening" Suggestion (low) stands — bootstrap path still omits acpHttpEnabled; re-measured 3 runs: 36/38/37 responses without the capability (+6…+1165 ms), first present at +1178/+1184/+1196 ms. Measured one-line fix validated (see Findings).
F-3 (M4) Coverage gap: release() cross-workspace ownership guard unpinned Completeness stands — mutant still survives (21/21 green); a new test pins the in-flight branch only. The guard itself is behaviorally correct on a live two-workspace daemon (probe 5/5, 04-m4-cross-workspace.png): cross-workspace attach → 4002 mismatch; cross-workspace release → PTY survives; same-workspace release → kills. Test to write: release(tid, otherCwd) on an established session returns false and the session survives.
F-3 (M8) Coverage gap: resize ≤1000 dimension cap unpinned Completeness stands — mutant survives (26/26 green). The route test still feeds cols:1001 but only asserts the frame is not written as input, never that the resize is rejected. Behavior exercised live (cell I1: cols:99999, cols:-5, bogus type all dropped, session alive, size unchanged); only the unit-level pin is missing.
Corr. Commit 1 message claims a QWEN_WEB_TERMINAL=1 gate that doesn't exist stands — first commit body still says "opt-in (QWEN_WEB_TERMINAL=1 plus bearer auth)"; 0 references to QWEN_WEB_TERMINAL in packages/ + docs/ at head. The actual gate is capability (acpHttpEnabled) + client action opt-in + bearer/Host/Origin checks. Correction to the description, not a code change request.

Scope selection

  • Central claim: the daemon's authenticated /terminal WS route, backed by WebTerminalRegistry, delivers workspace-scoped interactive PTY sessions with reconnect scrollback/exit replay, resize/release control frames, and kill-on-release semantics — including the round-2 hardening commits (heartbeat, session preservation, cleanup-path drain, process-tree kill).
  • Secondary 1: web_terminal capability gating — advertised iff the ACP HTTP surface is on; withdrawn with QWEN_SERVE_ACP_HTTP=0.
  • Secondary 2: lifecycle guards — live-session cap of 8 (exited sessions exempt), workspace-mismatch rejection, input/output backpressure, workspace-drain release, 15 s socket heartbeat.
  • Delta since round 1 (diffed directly against fdb8fbe7, which is present in the object store): kill-tree walk, write tri-state (written|backpressure|unavailable) with no release on error paths, live-only cap counting, exit-replay release, route heartbeat (15 s), 8 MB socket buffer, decrement-based unack accounting, drain hook moved into the runtime-cleanup path, client buildWsUrl now derives from the workspace baseUrl + inactive-tab key gating.

A/B load-bearing proof (11/11, 01-ab-head-vs-base.png)

Base control = tmp/base-tree worktree at HEAD^1 (7357136dd1), all daemon-closure packages built from base source (tsc --build --noCheck — base code is CI-verified; type-check skipped only for environment reasons; generated git-commit.ts + web-templates assets + asset copy reproduced), wired to the already-installed root deps via symlinks. Purity: realpath of node_modules/@qwen-code/qwen-code-core from the base tree asserts into the base tree (this check caught and fixed a broken-link fallback that would have silently loaded head code before any base cell ran); nested package-level node_modules contain no @qwen-code entries (verified); base dist greps 0 references to web_terminal/WebTerminalRegistry. The PR's lockfile delta adds only browser-side @xterm/* deps to web-shell, so the daemon dependency closure is identical on both arms.

Cell Build Oracle Result
BASE-TERM-CTRL base WS upgrade /acp opens (upgrade stack alive)
BASE-CAP base GET /capabilities no web_terminal (121 features), as predicted
BASE-CAP-CTRL base same envelope sane (session_create present)
BASE-TERM base WS upgrade /terminal rejected (unknown path), as predicted
HEAD-TERM / -IO / -REL / -KILL head open + PTY echo + release opens; real PTY echoes (echo $$ oracle); close 4004; shell pid dead
HEAD-CAP head GET /capabilities web_terminal present (122 features = base 121 + 1)
OFF-CAP head + QWEN_SERVE_ACP_HTTP=0 GET /capabilities no web_terminal (116 features)
OFF-TERM head + off WS /terminal not upgraded (HTTP 404 — no upgrade listener mounted)

Note: an early HEAD-CAP probe fired inside the bootstrap window and observed the feature absent (116 features) while /terminal already upgraded seconds later — a live capture of finding F-2; the cells above gate capability queries on the deferred runtime being mounted (WS-upgrade readiness / envelope stabilization), and the bootstrap window is measured by its own probe below.

E2E on the real daemon (head dist; 34/34 + 10/10 + 9/9 + 5/5)

One real qwen serve (head dist, SHELL=/bin/bash) + real ws/raw-socket clients + real node-pty sessions; plus an in-process real-registry cell set and a two-workspace daemon probe. Raw logs in logs/.

Lifecycle (02-e2e-terminal-lifecycle.png, 34/34):

Cells Asserted behavior Result
A1–A5 no token → 401; wrong token → 401; cross-Origin → 403; forged Host → 403; good raw upgrade → 101 PASS
B1–B2 missing terminalId / unregistered cwd → error control + close 4002 PASS
C1–C4 open; PTY cwd = registered workspace; TERM=xterm-256color set, NO_COLOR/npm_config_prefix stripped; resize control reaches PTY (stty size 24 80 → 40 132) PASS
D1–D3 abrupt disconnect keeps PTY; reconnect replays scrollback exactly once (replay count == original count); still interactive; same shell pid across reconnect PASS
E1–E4 exit 3 → exit control {exitCode:3} + close 4000; reconnect to exited session replays exit state and releases it (new round-2 behavior); id reusable afterwards PASS
F1–F6 F-1 re-measure: bg child in its own pgid + nested grandchild spawned; release → 4004; shell, bg child, grandchild all dead PASS
G1–G4 detached session keeps PTY; ?release=1 releases (4004, pid dead); id reusable PASS
H1–H3 8 concurrent terminals; 9th → close 1013 retryable; slot reusable after release PASS
I1 malformed + out-of-range controls dropped silently; session alive; size unchanged PASS
J1–J2 release frame buffered during creation → 4004; id reusable PASS

Round-2 new semantics (03-e2e-new-behavior.png, 10/10):

Cells Asserted behavior Result
K1–K3 >256 KB unacknowledged input → error control + close 1013; session not released (shell pid alive — changed from round 1); ?release=1 then cleans it up (4004 + pid dead) PASS
M1–M3 8 sessions exit 0 (close 4000, retained) → 8 new sessions open simultaneously (exited sessions don't count against the cap); a retained exited session still replays its exit state PASS
K6–K7 live heartbeat: server ping within 17 s; session interactive afterwards PASS
K8–K9 boundary: setsid escape (new session, reparented) survives release — same semantics as closing a real terminal; documented, not a defect PASS (as encoded)

Observation (not a finding): after a backpressure close the session sits exactly at the 256 KB unacknowledged cap, so reconnect input is rejected with 1013 until the shell's own output (e.g. processing the buffered backlog) drains the counter. Self-healing; requires a >256 KB paste with no output to reach.

Workspace drain / dispose, real registry in-process (9/9): releaseWorkspace is cwd-scoped, removes only that workspace's session, exit listeners get {exitCode:143, signal:15}, drained PTY dead / survivor alive; dispose() kills the remainder; post-dispose create refused.

Cross-workspace live probe (04-m4-cross-workspace.png, 5/5): daemon booted with two registered workspaces (A primary, B secondary). Terminal created in A: attach from B → 4002 Terminal workspace mismatch; ?release=1 from B → PTY survives (guard holds); same-workspace reattach interactive; same-workspace release kills (4004 + pid dead). See finding 2 below for the close-code honesty wrinkle observed here.

Reviewer Test Plan walk

  1. Entry visibility — protocol/unit level: web_terminal in /capabilities (HEAD-CAP), client gating covered by App/ArtifactPanel/TerminalPanel suites (630 tests). Real-browser rendering not exercised (Not covered).
  2. Two independent tabs — H1–H3 (8 concurrent, independent sessions).
  3. Tab-switch survival — D1–D3 (detach/reattach keeps process and screen; same pid).
  4. Resize — C4 (stty size oracle).
  5. Reconnect replay once — D3 (count-equal oracle) + E3 (exit state replayed exactly once).
  6. Close releases PTY, new PTY afterwards — F3–F6, G2–G4, E4, J2.
  7. Embedded/hidden entry — OFF-CAP (capability absent when ACP HTTP off) + gating unit tests; action-omission path via customization type + App tests.

Findings

1. (Suggestion, low — carried over, stands) F-2: bootstrap /capabilities under-reports web_terminal for ~1.2 s after "listening"

Re-measured at the new head (05-f2-bootstrap-window.png, 3 runs): 36/38/37 bootstrap responses lack web_terminal (from +6…+1165 ms after "listening", 116 features); first present at +1178/+1184/+1196 ms (122 features). Root cause unchanged: currentServeFeaturesForRunQwenServe() passes clientMcpOverWsEnabled/cdpTunnelOverWsEnabled/browserAutomationMcpAvailable but still omits acpHttpEnabled, while the runtime path (server/serve-features.ts) passes acpHttpEnabled: currentAcpHttpEnabled — despite the bootstrap function's own comment promising parity "so the bootstrap window doesn't briefly under-report them". A Web Shell fetching capabilities in that window hides the Terminal entry until its next fetch. The function was even extended since round 1 (for currentSessionSchedulingAvailable, via the base merge) without closing this gap.

Minimal suggested fix (measured against the same probe)

In currentServeFeaturesForRunQwenServe (packages/cli/src/serve/run-qwen-serve.ts), add to the toggles object:

acpHttpEnabled: resolveAcpHttpEnabled(env),

(resolveAcpHttpEnabled is already imported; env is the function's existing parameter.)

Measured, applied in a scratch copy + rebuilt dist, three results:

  1. Hostile fixture clean: f2-probe 3 runs → 0 under-reporting responses on every run; capability present from the first response (+8/+10/+33 ms; bootstrap envelope 117 features).
  2. Benign fixture identical: with QWEN_SERVE_ACP_HTTP=0 the bootstrap envelope still never advertises web_terminal (7 samples over ~1.3 s, 116→120 features, absent throughout) — the toggle-off semantics are preserved.
  3. Affected suite unchanged: run-qwen-serve.test.ts 329/329 both with and without the patch (typecheck also passes with it). Note the suite is green on both sides — it pins nothing along the bootstrap-feature axis — so the fix should land together with a fixture asserting the bootstrap envelope contains web_terminal whenever ACP HTTP is on.

2. (Suggestion, nit — new) ?release=1 reports 4004 Terminal released even when the release is refused

The release handshake ignores registry.release()'s boolean: with the terminal owned by workspace A, a ?terminalId=…&cwd=B&release=1 request from workspace B closes 4004 Terminal released while the PTY (correctly) survives — measured live in probe cell P3 (close=4004, pid alive afterwards). The protective outcome is right (the ownership guard holds; P3/P5), and only the close code misreports to a client that is either buggy or probing another workspace's terminals on a multi-workspace daemon; the in-connection release branch has the same shape. Repro: m4-probe.mjs cells P1–P5. No test pins the refused-release close code (unpinned axis); suggested direction: honor the boolean and close a distinct code (e.g. 4002) when release() returns false — not applied; a fixture asserting the refused-release code would pin it.

3. (Completeness — carried over, not merge conditions) M4 and M8 survivors

Mutation matrix below: M4 (established-session cross-workspace release guard) and M8 (resize ≤1000 cap) still survive their suites. Both behaviors are empirically correct (M4 proven live above; M8 exercised in cell I1) — these are tests to write, recorded so they are not silently dropped:

  • M4 test: release('t', otherWorkspaceCwd) on an established session → false, session survives.
  • M8 test: resize control with cols:1001registry.resize not called (and size unchanged).

Mutation matrix (06-mutation-matrix.png, logs/mutation-matrix.txt)

Baselines green: registry 21/21, route 26/26. Positive controls killed in the same file as each mutant set (C1: exit-code 143→144 killed 21/21→20/21; C2: close 4004→4005 killed 26/26→23/26).

Mutation Guard Suite Result Classification
M4 (carried) release() cross-workspace check, established session registry 21 SURVIVED 21/21 coverage gap — guard proven correct live (probe P1–P5); test to write
N1 killPtyTree ps descendant/session walk (F-1 fix) registry KILLED (1 red) pinned
N2 cap counts only LIVE sessions registry KILLED pinned
N3 exit listeners notified from a snapshot copy registry KILLED pinned
N4 unack-input decrement by output bytes registry KILLED pinned
C1 CONTROL: drain exit code 143→144 registry KILLED control
M8 (carried) resize ≤1000 dimension cap route 26 SURVIVED 26/26 coverage gap — behavior live-exercised (I1); unit pin missing
N5 release after exit-state replay route KILLED (2 red) pinned
N6 15 s WS heartbeat route KILLED pinned
N7 input-path workspace re-check route KILLED pinned
C2 CONTROL: close 4004→4005 route KILLED (3 red) control

Every guard the round-2 commits introduced is pinned by a test; the two survivors are both carried-over completeness items, and neither survivor's behavior is defective.

Targeted gates (project's own tests, all green)

Suite Result
packages/core web-terminal-registry.test.ts 21/21
packages/cli routes/terminal.test.ts 26/26
packages/cli server.test.ts 1102/1102
packages/cli acp-http/workspace-qualified-acp.test.ts 50/50 (incl. the 2 drain-bypass tests)
packages/web-shell App.test.tsx 555/555
packages/web-shell ArtifactPanel.test.tsx 60/60
packages/web-shell TerminalPanel.test.tsx 15/15

Total 1829/1829 across the 7 test files touched by the PR's effective diff. Additionally run-qwen-serve.test.ts 329/329 (not in the PR diff — it arrived via the base merge — but run as the affected suite for the measured F-2 fix, with and without the patch). Flakiness (5 identical rounds) is run by the workflow's own lane; each file above ran once in this gate.

Not covered

  • Per-commit attribution: depth-2 checkout; metadata lists 17 commits, git rev-list HEAD^1..HEAD^2 returns 1 across the shallow graft. The previous head fdb8fbe7 is present in the object store, so the aggregate delta since round 1 was diffed (and the round-2 semantics were each exercised), but commits 13/14/16/17 cannot be separated individually. Verified aggregate HEAD^1..HEAD.
  • Real-browser client: xterm rendering, FitAddon refit-on-activate, inactive-tab key gating, and the new buildWsUrl(baseUrl) derivation were not exercised in a browser; client behavior is covered by the 630 unit tests and by protocol-level E2E of the exact wire contract the client implements. (Shape note, untested topology: a baseUrl carrying a path prefix would produce a WS path the upgrade matcher — exact raw /terminal — rejects; standalone origin-only deployments are unaffected.)
  • Windows/macOS: Linux container only; the Windows taskkill /f /t branch of killPtyTree remains untested here (relevant to F-1's platform contrast).
  • 15-minute idle reclaim constant: not observed live; scheduling logic pinned by registry unit tests (fake timers).
  • Untrusted-workspace negative path: trust check verified by reading (runtime.primary ? isPrimaryWorkspaceTrusted() : runtime.trusted); both live workspaces in the M4 probe were trusted, so the untrusted rejection was not driven live.
  • Repo-wide gates: not run; targeted gates only.
  • Capture 06-mutation-matrix.png is rendered from the run's saved log (logs/mutation-matrix.txt, same artifact dir) rather than a re-execution; all other captures are live re-runs of their harnesses.

Methodology

Environment: CI verify container (node:22-bookworm), merge-ref checkout (HEAD = merge, HEAD^1 = base tip 7357136dd1, HEAD^2 = verified head 7dca447c5b). Harnesses live in this artifact dir (lib.mjs, ab-harness.mjs, terminal-e2e.mjs, e2e2.mjs, registry-proc.mjs, m4-probe.mjs, f2-probe.mjs, mutation-matrix.mjs) and boot the real built daemon (packages/cli/dist/index.js serve --port 0 --token … --require-auth --workspace <scratch> [--workspace B] [--no-web], SHELL=/bin/bash) driving it over loopback with the ws client and raw sockets (Host/Origin forgery); PTY liveness asserted via kill(pid, 0) on pids the shells themselves report (echo $$, echo $!, inner-bash $$). Base control: HEAD^1 worktree, packages built from base source with generated files reproduced, @qwen-code links realpath-asserted into the base tree (the assertion caught a broken-link fallback to head code before any base cell ran), base dist grep-verified free of the feature; daemon dep closure identical because the PR's lockfile delta is browser-only @xterm/*. The measured F-2 fix was applied to the working tree, validated (probe ×3, toggle-off probe, run-qwen-serve.test.ts both ways), then reverted (git checkout + rebuild); the tree was confirmed clean and the pristine A/B re-run green afterwards. Mutations were applied to source, run against the file's own vitest suite, and restored per-mutation via git checkout (final git status clean). Raw per-harness logs in logs/; captures in evidence/. Assertion accounting: fail counts only unexpected outcomes — the 3 fails are the standing finding F-2 (its probe asserts the reviewer-natural property "advertised from listening"); base-arm predicted absences/rejections and the setsid-boundary survival are encoded expectations and count as passes.

Flakiness gate log

rounds=5 files=7 skipped=0
file packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: (cd packages/cli) npx --no-install vitest run ./src/serve/acp-http/workspace-qualified-acp.test.ts
file packages/cli/src/serve/routes/terminal.test.ts: (cd packages/cli) npx --no-install vitest run ./src/serve/routes/terminal.test.ts
file packages/cli/src/serve/server.test.ts: (cd packages/cli) npx --no-install vitest run ./src/serve/server.test.ts
file packages/core/src/services/web-terminal-registry.test.ts: (cd packages/core) npx --no-install vitest run ./src/services/web-terminal-registry.test.ts
file packages/web-shell/client/App.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/App.test.tsx
file packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/artifacts/ArtifactPanel.test.tsx
file packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/terminal/TerminalPanel.test.tsx


per-file results (P=pass F=fail I=infra-exit, one letter per run):
  packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: PPPPP
  packages/cli/src/serve/routes/terminal.test.ts: PPPPP
  packages/cli/src/serve/server.test.ts: PPPPP
  packages/core/src/services/web-terminal-registry.test.ts: PPPPP
  packages/web-shell/client/App.test.tsx: PPPPP
  packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: PPPPP
  packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: PPPPP

verdict: pass
summary: 7 changed test file(s) x 5 identical rounds, no divergence

--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: P (exit 0)
round 1 · packages/cli/src/serve/routes/terminal.test.ts: P (exit 0)
round 1 · packages/cli/src/serve/server.test.ts: P (exit 0)
round 1 · packages/core/src/services/web-terminal-registry.test.ts: P (exit 0)
round 1 · packages/web-shell/client/App.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: P (exit 0)
round 2 · packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: P (exit 0)
round 2 · packages/cli/src/serve/routes/terminal.test.ts: P (exit 0)
round 2 · packages/cli/src/serve/server.test.ts: P (exit 0)
round 2 · packages/core/src/services/web-terminal-registry.test.ts: P (exit 0)
round 2 · packages/web-shell/client/App.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: P (exit 0)
round 3 · packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: P (exit 0)
round 3 · packages/cli/src/serve/routes/terminal.test.ts: P (exit 0)
round 3 · packages/cli/src/serve/server.test.ts: P (exit 0)
round 3 · packages/core/src/services/web-terminal-registry.test.ts: P (exit 0)
round 3 · packages/web-shell/client/App.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: P (exit 0)
round 4 · packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: P (exit 0)
round 4 · packages/cli/src/serve/routes/terminal.test.ts: P (exit 0)
round 4 · packages/cli/src/serve/server.test.ts: P (exit 0)
round 4 · packages/core/src/services/web-terminal-registry.test.ts: P (exit 0)
round 4 · packages/web-shell/client/App.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: P (exit 0)
round 5 · packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts: P (exit 0)
round 5 · packages/cli/src/serve/routes/terminal.test.ts: P (exit 0)
round 5 · packages/cli/src/serve/server.test.ts: P (exit 0)
round 5 · packages/core/src/services/web-terminal-registry.test.ts: P (exit 0)
round 5 · packages/web-shell/client/App.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/artifacts/ArtifactPanel.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/terminal/TerminalPanel.test.tsx: P (exit 0)

Evidence images

01-ab-head-vs-base

02-e2e-terminal-lifecycle

03-e2e-new-behavior

04-m4-cross-workspace

05-f2-bootstrap-window

06-mutation-matrix

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot has neither a verdict nor a deferral on 7dca447c5bf9f5a32878ccb8e2d1dc1d8f14613f — no APPROVED, CHANGES_REQUESTED, or COMMENTED review of its own. A DISMISSED one does not count: dismiss_stale_reviews voids the bot's approval on every push, which is exactly when a fresh one is needed. If this re-run was meant to review or approve, it did not, and an approval left by another account is a separate vote that does not count as the bot's own.

⚠️ 机器人在 7dca447c5bf9f5a32878ccb8e2d1dc1d8f14613f既没有裁决也没有 defer —— 没有属于它自己的 APPROVEDCHANGES_REQUESTEDCOMMENTED 评审。DISMISSED 不算:dismiss_stale_reviews 会在每次推送时作废机器人的批准,而那恰恰是需要一次新批准的时刻。如果这次重跑本应评审或批准,那么它没有做到;而其他账号留下的批准是另一张票,不能算作机器人自己的。

The stage comments above were updated with the latest result. View workflow run.

上方各阶段评论已更新为最新结果。查看工作流运行

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed.

1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • create-pending input overflow (>64 KiB) kills the connection and the just-created session for a single large paste racing the create window (packages/cli/src/serve/routes/terminal.ts:166) — already reported (open thread R2-13,…

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

Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:

  • packages/core/src/services/web-terminal-registry.test.ts:293 — [probe] killPtyTree session-membership branch unpinned by the kill-tree test fixture (D6-1)
  • packages/core/src/services/web-terminal-registry.ts:208 — [probe] output credit bounds the accounting, not the bytes actually queued in the PTY (D6-2)
  • packages/core/src/services/web-terminal-registry.test.ts:308 — [probe] kill fallback chain and if (killed) return; gate unpinned by any test (D6-3)
  • packages/cli/src/serve/run-qwen-serve.ts:2162 — [review] bootstrap /capabilities omits acpHttpEnabled, under-reporting web_terminal for ~1.4 s after boot (D6-4)

Convergence: round 6 posted 4 inline comment(s), 4 of them reported for the first time; the previous round posted 4 (4 new). Findings keep coming back to the same files: packages/core/src/services/web-terminal-registry.ts (findings in round 5; 4 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. (Observation only — nothing was withheld from this review because of this observation.)

中文说明

仅完成部分审查,审查缺口已披露。

本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

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

收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 4 条(原文未翻译,列表见上方英文部分)。

收敛情况:第 6 轮发布了 4 条行内评论,其中 4 条是首次提出;上一轮发布了 4 条(其中 4 条首次提出)。发现反复回到同一批文件:packages/core/src/services/web-terminal-registry.ts(第 5 轮已出过发现,本轮又有 4 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。(仅为观察——本轮评审未因此扣留任何内容。)

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

Comment thread packages/core/src/services/web-terminal-registry.ts
Comment thread packages/core/src/services/web-terminal-registry.ts Outdated
Comment thread packages/core/src/services/web-terminal-registry.ts
Comment thread packages/core/src/services/web-terminal-registry.ts Outdated

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

Independent pass at 7dca447, focused on new ground (not repeating the ~55 open bot threads). Local verification on this head: registry suite 21 pass, terminal route suite 26 pass, tsc --noEmit clean in core and cli. The WS auth surface looks solid — Host allowlist, Origin rejection, and bearer/loopback auth all run before the route handoff, and cross-workspace attach/release is blocked by the workspaceCwd checks. Four new findings inline, two of them worth addressing before merge: (1) the unacknowledged-input budget can wedge a healthy session into a permanent 1013 close/reconnect loop; (2) /terminal bypasses the workspace-drain gate, so new PTYs can be spawned into a draining workspace after the one-shot release has already run.

Comment thread packages/core/src/services/web-terminal-registry.ts Outdated
Comment thread packages/cli/src/serve/routes/terminal.ts
Comment thread packages/web-shell/client/App.tsx Outdated
Comment thread packages/cli/src/serve/routes/terminal.ts

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

Re-reviewed at 4960873. All four of my earlier findings are closed out, verified in source and by local test runs on this head:

  • Input-budget wedges (c36212e): zero-debt first-frame admission + recovery-control pass-through — both lockout shapes are gone; the bounded-admission accounting is the right call given node-pty has no write-completion callback.
  • Drain-bypass concern: withdrawn — activeRuntime (workspace-registry.ts:318) only resolves active entries, and beginDrain flips the state to draining, so the terminal resolver returns undefined from drain start; bypassPrimaryDrain cannot create a PTY in a draining runtime.
  • Terminal id collisions (34a5b0a): crypto.randomUUID() now, counter ref removed.
  • Post-revocation output (34a5b0a): the shared ensureWorkspaceAvailable guard covers input, resize, live output, and snapshot replay.

Local verification: registry suite 23/23, terminal route suite 27/27, tsc --noEmit clean in packages/cli. My pass is clear; the open bot-round threads are outside this approval.

@chiga0 chiga0 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed at new commits c36212ef and 34a5b0a1. Prior findings from round 1 (7dca447c) resolved:

Prior findings — status at new head:

  • C1 (bot: no buffered-amount check): Still refuted — sendOutput gate on ws.bufferedAmount > 8 MB is unchanged.
  • C2 (bot: no error handler): Still refuted — ws.on('error', markClosed) remains the first statement in the connection handler.
  • C3 (bot: write drops input under backpressure) + UX question: Fixed by c36212ef\x03\x04\x1a\x1c now bypass the budget unconditionally and don't accrue bytes; and unacknowledgedInputBytes !== 0 guard allows a first oversized frame through on an idle session (test: accepts one complete oversized input frame on idle). Both lockout shapes gone.
  • C4 (bot: reclaim timer race): Still refuted — identity check at registry line 301 is unchanged.
  • Drain window question: Resolved — activeRuntime (workspace-registry.ts:318) only resolves active entries; beginDrain flips the workspace state to draining before any new PTY can be created, so resolveWorkspace returns undefined at that point. The bypassPrimaryDrain path cannot race a draining workspace into existence.

New code checked (c36212ef, 34a5b0a1):

  • killPtyTree portability (web-terminal-registry.ts:78): Linux sid=, macOS tdev=, fallback to pid=,ppid= only (plus unconditional SIGKILL(-pty.pid)) on other platforms and on ps error. maxBuffer: 8 MB and timeout: 2_000 guard the spawnSync call. rootScope guards (undefined/'0'/'??') are correct — prevents over-broad scope-based kills when the PTY process has no controlling terminal or is in kernel session 0. New test covers both the scope-based kill path (process 45, same session, orphaned from parent chain) and the ps-failure fallback (ENOBUFS → -SIGKILL only). ✅
  • ensureWorkspaceAvailable() in output listener (terminal.ts:300): closes the post-revocation output leak — data from workspace A's PTY can no longer reach a WebSocket that has since become bound to a different workspace. The cleanup() + Set-delete path from within the iterator is safe per ES6 Set iteration semantics. ✅
  • ensureWorkspaceAvailable() at connection setup (terminal.ts:329): closes the TOCTOU window between ws.on('error', cleanup) being registered and the snapshot being sent. ✅
  • crypto.randomUUID() for terminal IDs (App.tsx): removes the Date.now():counter sequential ID, making terminal IDs unpredictable. crypto.randomUUID() is available in all current browser targets. ✅

CI (head 72d611b5): ubuntu unit tests in-progress at time of review · Desktop Shell ubuntu + windows ✅ · macOS unit tests SKIPPED · Windows unit tests SKIPPED · Integration Tests (CLI) SKIPPED.

No blocking findings in round 2.

Reviewed with AI assistance.

@ytahdn
ytahdn added this pull request to the merge queue Aug 28, 2026
Merged via the queue into main with commit d853f09 Aug 28, 2026
34 of 36 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.22.3.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants