Skip to content

fix(cli): wrap tool call descriptions instead of truncating#4

Closed
Alex-ai-future wants to merge 610 commits into
mainfrom
fix/shell-preview
Closed

fix(cli): wrap tool call descriptions instead of truncating#4
Alex-ai-future wants to merge 610 commits into
mainfrom
fix/shell-preview

Conversation

@Alex-ai-future

Copy link
Copy Markdown
Owner

What this PR does

Changes the tool call description text wrapping behavior from truncate-end to wrap, allowing long descriptions (shell commands, file paths, etc.) to wrap onto multiple lines instead of being cut off.

Why it's needed

Tool call descriptions were truncated at the line width, making it impossible to see the full command or file path once the output scrolled out of view. The ANSI echo shows the command during execution but disappears from the viewport afterward, hindering session review and debugging. Wrapping keeps the full description visible in the message header for later reference.

Reviewer Test Plan

How to verify

Run a tool with a long description (e.g. a long shell command chain or a deep file path) and confirm the full text wraps to multiple lines instead of being truncated with no way to see the rest.

Evidence (Before & After)

Before: Long commands are truncated at line width, tail hidden (truncate-end).
After: Long commands wrap to the next line, fully visible (wrap).

Tested on

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

Environment (optional)

npm run dev

Risk & Scope

  • Main risk or trade-off: Very long descriptions will consume multiple terminal rows, slightly reducing visible message count per screen.
  • Not validated / out of scope: N/A
  • Breaking changes / migration notes: N/A

Linked Issues

N/A

中文说明

此 PR 做了什么

将工具调用描述的文本换行行为从 truncate-end(截断)改为 wrap(换行),使长描述(shell 命令、文件路径等)可以换行显示完整内容,而不是被截断。

为什么需要

工具调用描述在行宽处被截断,输出滚出视口后无法看到完整命令或路径。ANSI 回显在执行期间显示命令,但滚动后消失,不利于会话回顾和调试。换行显示使完整描述保留在消息头部,方便后期复盘。

评审测试计划

如何验证

运行一个带有长描述的工具(如长 shell 命令链或深层文件路径),确认完整文本换行到多行显示,而不是被截断且无法查看剩余部分。

证据(前后对比)

之前:长命令在行宽处截断,尾部不可见(truncate-end)。
之后:长命令换行到下一行,完整可见(wrap)。

测试平台

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

环境(可选)

npm run dev

风险与范围

  • 主要风险或权衡:超长描述将占用多行终端空间,略微减少每屏可见的消息数量。
  • 未验证 / 超出范围:N/A
  • 破坏性变更 / 迁移说明:N/A

关联 Issue

N/A

wenshao and others added 30 commits June 19, 2026 19:41
* feat(cli): serve the Web Shell UI from `qwen serve`

`qwen serve` now serves the built Web Shell SPA at its root on the same
origin as the API, so a released binary exposes the browser terminal
without the dev-only Vite server (the `npm run dev:daemon` two-process
setup is unchanged for development).

- New `webShellStatic.ts` mounts `/`, `/assets/*` and an SPA deep-link
  fallback. The fallback uses the same document-navigation discriminator
  as the Vite dev proxy so it never shadows API JSON 404s.
- The static shell is registered BEFORE bearerAuth (a browser can't attach
  a token to a `<script>` subresource or an address-bar navigation; the
  shell carries no secrets and every API route stays token-gated). HTML
  responses set CSP + X-Frame-Options + Referrer-Policy + no-cache.
- `--open` launches the browser at the daemon URL (with `?token=` when set)
  once the listener is up, guarded by `shouldLaunchBrowser()`.
- `--no-web` opts out for an API-only daemon.
- Bundle / npm publish / standalone packaging now ship `dist/web-shell/`.
  Missing assets degrade to API-only with a breadcrumb, never a hard fail.

Tests: +6 cases in server.test.ts (root shell, assets, SPA fallback,
non-navigation 404 passthrough, security headers, --no-web off).

* fix(cli): address review on Web Shell serving

Review fixes for QwenLM#5392 (qwen-code-ci-bot):

- [Critical] SPA fallback no longer shadows /health or /demo on non-loopback
  binds — those paths fall through to their own routes / bearerAuth instead
  of receiving index.html.
- [Critical] --open trims the bearer token before putting it in the browser
  URL, matching runQwenServe's own trimming, so a trailing newline from
  `$(cat token.txt)` no longer makes every API call 401.
- --open is wrapped in its own try/catch so a failed browser launch can't
  take down the already-listening daemon; it normalizes wildcard binds
  (0.0.0.0 / ::) to loopback, and only fires when the UI is actually mounted
  (new RunHandle.webShellMounted).
- resolveWebShellDir() now requires BOTH index.html and assets/, so a partial
  build degrades to API-only instead of serving a shell whose chunks 404.
- runQwenServe logs a positive "Web Shell UI served from <dir>" breadcrumb,
  and warns that on a non-loopback bind without --allow-origin the shell is
  read-only (same-origin POSTs are blocked by the CORS wall).
- Document the --open token-in-process-list exposure in help text + a stderr
  note when a token is forwarded.
- Tests: POST method guard, sec-fetch navigation signal, /health not shadowed,
  sendFile 500 path, plus isDocumentNavigation and resolveWebShellDir units.

* fix(cli): harden Web Shell asset resolution and send-error logging

Second-round review (claude /qreview on the initial commit):

- resolveWebShellDir() now walks up from this module to find a sibling
  packages/web-shell/dist, covering the transpiled layouts the previous
  fixed `..` depth missed — per-package `tsc` output and the integration
  daemon harness (packages/cli/dist/index.js), which would otherwise resolve
  to nonexistent paths and silently run API-only.
- sendFile failures are no longer silent: log the error (matching the /demo
  handler — previously the only 5xx path that emitted nothing) and res.end()
  a half-streamed response instead of leaving the client on a 200 with a
  partial body.

The remaining comment (open-browser inside the boot try) was already fixed
in 2487c90, where the --open block gained its own try/catch.

* fix(cli): pass --open token via URL fragment + add auth-contract tests

Third-round review (qwen3.7-max /review):

- --open now puts the token in the URL fragment (#token=) instead of a query
  param, and the Web Shell reads it from the fragment first (falling back to
  ?token= for the dev launcher / hand-built URLs). A fragment is never sent to
  the server, so the token stays out of access logs and Referer headers. It is
  still visible in the browser-launcher's argv, so the stderr note stays and a
  one-time-code exchange remains the real fix for multi-user hosts (follow-up).
- Add a server test pinning the "shell served before bearerAuth, API still
  token-gated" contract (GET / → 200 without auth, /capabilities → 401 with a
  token set), plus front-end getDaemonToken fragment/query precedence tests.

The token-trim comment in this pass was already addressed in 2487c90.

* fix(cli): read --open token from RunHandle.resolvedToken; doc + test polish

Fourth-round review (qwen3.7-max /review), all suggestions:

- --open now reads the server's resolved (trimmed) token from
  RunHandle.resolvedToken instead of re-deriving it from argv/env. Removes the
  duplicated QWEN_SERVER_TOKEN literal + trim logic and any drift risk; the
  browser token is by construction what the daemon authenticates against.
- Simplify webShellMounted to !!webShellDir (serveWebShell===false already
  forces webShellDir to undefined, so the extra conjunct was dead).
- Docs: the --open row now documents the #token= fragment transport (was
  ?token=) and why a fragment is used.
- Tests: add removeDaemonTokenFromUrl coverage (strip from fragment / query /
  both, preserve non-token hash params, no-op when absent) and the missing
  afterEach import.

* fix(cli): register Web Shell SPA fallback after API routes

Fifth-round review (claude /qreview):

- The SPA fallback no longer sits before bearerAuth. It now runs after every
  API route (just before the error handler), so authed routes — and their
  401s — always win, and only genuine 404 misses fall through to the shell.
  A navigation with an attacker-controlled `Accept: text/html` to
  /capabilities (or /health on a non-loopback bind) no longer coaxes the 200
  shell out of a gated endpoint, and the fragile exact-match /health,/demo
  denylist (which trailing-slash variants slipped past) is gone.
  registerWebShell is split into mountWebShellAssets (/, /assets — still
  pre-auth so a browser can load the shell + subresources without a header)
  and mountWebShellSpaFallback (post-auth). The contract test now sends
  Accept: text/html to /capabilities and asserts 401 — it would have been 200
  before this change (the test was passing only because it omitted Accept).
- verifyBundleArtifacts (the publish gate) now requires dist/web-shell, so a
  build that skipped the web-shell workspace (e.g. npm ci --ignore-scripts
  bypassing the root prepare) fails packaging loudly instead of silently
  shipping an API-only CLI whose GET / 404s.

* fix(cli): return a clean 404 for missing Web Shell assets

Sixth-round review (qwen3.7-max /review):

A missing /assets/* (e.g. a stale hashed chunk after a redeploy renamed it)
now returns 404 instead of falling through to the SPA fallback and answering a
browser navigation with a 200 index.html. Implemented with an explicit /assets
404 handler after express.static rather than serve-static's `fallthrough:
false` — the latter forwards a 404 error to the catch-all error handler, which
would turn it into a 500. Test added.

* test(cli): cover --open + Web Shell signals; add shell security headers

Seventh-round review (qwen-code-ci-bot):

- [Critical] Extract the --open browser-launch logic into the exported
  maybeOpenWebShellBrowser() and unit-test it: --open / webShellMounted /
  shouldLaunchBrowser gating, wildcard-host -> loopback rewrite, token in the
  URL fragment (not query), and the never-throws error catch.
- [Critical] Assert RunHandle.webShellMounted (false under --no-web) and
  resolvedToken (trimmed / undefined) in runQwenServe.test.ts; also cover
  --web/--no-web and --open arg parsing.
- Drop dead code: target.hostname === '::' is unreachable (Node's URL returns
  the IPv6 wildcard as '[::]', which is already handled).
- Add defense-in-depth headers to the shell response: base-uri 'none' in the
  CSP (does not fall back to default-src), X-Content-Type-Options: nosniff,
  and a restrictive Permissions-Policy.
- Add serve-debug-gated logging for /assets 404s and SPA-fallback hits so a
  white-screen shell / routing misconfig has a diagnostic trail.

* fix(test): satisfy the Web Shell release gate in package-assets fixture

Eighth-round review (claude /qreview) — this is the actual CI failure.

The verifyBundleArtifacts Web Shell gate (requiring dist/web-shell, added in
this PR) broke scripts/tests/package-assets.test.js, which merge-main pulled
in: its createBundleArtifacts fixture only created cli.js / vendor / bundled,
so preparePackage exited 1 at the new gate before the test's assertions ran —
red on all three Test jobs. Add the web-shell artifacts (index.html +
assets/) to the fixture. The gate itself is intentional (it stops an API-only
package from shipping).
…M#5022) (QwenLM#5230)

The TUI startup path called enableDurable() fire-and-forget and then
start() synchronously. Because start() installs onFire before
enableDurable() finishes loading tasks from disk, overdue durable fires
were delivered instantly into the notification queue and reached a chat
client whose startChat() had not completed — producing "Chat not
initialized" on fresh launches with pending durable work.

Gate the cron effect on isConfigInitialized and await enableDurable()
before start(), matching the ordering the ACP (Session.ts) and headless
(nonInteractiveCli.ts) paths already use. A `stopped` flag prevents a
stale start() if the component unmounts during the async gap.

On enableDurable() failure the catch falls through (does not return) so
start() still runs: a failed durable init must not silently disable
session-only cron tasks (created via cron_create during the session) —
only durable/persistent tasks are lost.

Tests: gate ordering (with a real async gap so the assertion has teeth),
gate-stays-closed, unmount-during-gap, and enableDurable-rejection-
still-starts. The last two lock in the unmount guard and the fall-through
fix (both verified by mutation).

Co-authored-by: Shaojin Wen <[email protected]>
* fix(auth): preserve custom provider models on install

* fix(auth): scope ACP custom key reuse by endpoint
…ame field (QwenLM#5002)

* perf(core): F2 cleanup PR A — R9/W11/W12/R10 (post-merge follow-ups) (#4411)

* refactor(core): F2 PR A R9 — McpClientManager options-object ctor

R9 (filed as F2 follow-up from #4336 review): 7 positional ctor args
collapse to (config, toolRegistry, options?: McpClientManagerOptions).
The trailing 5 (eventEmitter, sendSdkMcpMessage, healthConfig,
budgetConfig, pool) become named fields on `McpClientManagerOptions`.
Test factory `mkManager(overrides?)` introduced at the top of
`mcp-client-manager.test.ts` so each of the prior 80 inline
constructions becomes a single line naming only the field(s) the test
overrides; the 4 `undefined` sentinels each test threaded through to
reach the trailing `pool` arg are gone.

Net: 113 LOC removed (test) + 35 LOC added (src exposes interface +
mkManager factory + tool-registry call site update). Behavior
unchanged — same field assignments, same downgrade-enforce-without-
budget breadcrumb, same budget event wiring.

Filed bucket: F2 perf / cleanup PR A (R9 + W11 + W12 + R10/R23 T7),
see issue #4175 item 7 "F2 post-merge cleanup PRs". This is the first
of the 4 fixes in PR A; W11/W12/R10 follow as separate commits.

Test sweep: 84/84 mcp-client-manager.test.ts pass; typecheck clean.

* refactor(core): F2 PR A W11 — extract attachPooledSession + rollbackReservationOnSpawnFailure

W11 (filed as F2 follow-up from #4336 review): two private helpers
on `McpTransportPool` to eliminate inline duplication in `acquire()`:

  - `attachPooledSession(entry, id, serverName, cfg, sessionId,
    toolReg, promptReg)`: builds `SessionMcpView` + `entry.attach`
    with the standard pool release callback. Used by both the
    fast-path attach (existing entry) and the post-spawn attach
    (after `await inFlight`). NOT used by `createUnpooledConnection`
    — its release callback runs `entry.forceShutdown('manual')` +
    `indexDetach` directly (no pool refcount accounting since
    unpooled entries are per-session).

  - `rollbackReservationOnSpawnFailure(reservationResult, serverName)`:
    R24 T17 contract — only release the budget slot if THIS acquire
    actually reserved a new slot (`'reserved'`); `'already_held'`
    skips because the sibling owns it. Used by both the unpooled
    catch and the pooled spawn-in-flight catch.

Race-window invariants (W10 / W77 / W90 / W111 / W125 / R24 T17)
stay at the call sites because they describe the SURROUNDING
ordering, not the helpers themselves. Helpers are documented to
defer those decisions back to callers.

Behavior unchanged. Filed bucket: F2 perf cleanup PR A (R9 done /
W11 this commit / W12 + R10 to follow).

Test sweep: 28/28 mcp-transport-pool.test.ts pass; typecheck clean.

* refactor(core): F2 PR A W12 — SessionMcpView precompute filter Sets

W12 (filed as F2 follow-up from #4336 review): `applyTools` /
`applyPrompts` precompute `excludeSet` + `includeSet` once per pass
instead of scanning `cfg.includeTools` / `cfg.excludeTools` arrays
inside every per-tool iteration.

Pre-fix the per-tool predicate (`passesSessionFilter`) walked both
arrays for every snapshot entry → O(M × N) per `applyTools` call.
With M tools × N filter entries, typical M=5-20 / N=2-5 case
finishes in microseconds either way; the win is data-structure
correctness and code clarity, not perceived perf.

`passesSessionFilter` / `passesSessionPromptFilter` (the array-
based predicates) stay exported and unchanged for unit tests + any
caller wanting to test a single name without paying Set construction.
The bulk path uses two new private helpers `compileNameFilter` +
`compiledFilterAccepts` whose Sets live on the `applyTools` /
`applyPrompts` stack frame.

Same semantics: `excludeTools` is direct-equality match (no parens
strip — pre-F2 behavior preserved); `includeTools` strips the first
`(...)` suffix so `toolName(args)` matches `toolName`.

Filed bucket: F2 perf cleanup PR A (R9 + W11 done / W12 this commit
/ R10 to follow).

Test sweep: 13/13 session-mcp-view.test.ts pass; typecheck clean.

* perf(core): F2 PR A R10 / R23 T7 — pid-descendants ps snapshot + pgrep fallback

R10 / R23 T7 (filed as F2 follow-up from #4336 review): the Linux
/ macOS pid-descendant enumeration moves from per-pid `pgrep -P
<pid>` BFS (one subprocess fork per node visited) to a single
`ps -A -o pid=,ppid=` snapshot followed by an in-memory tree walk
over `Map<ppid, pid[]>`. Windows analog: single `Get-CimInstance
Win32_Process | ConvertTo-Csv` snapshot of all `(ProcessId,
ParentProcessId)` rows replaces per-pid
`Get-CimInstance -Filter "ParentProcessId=$p"` BFS.

Two motivations:
  1. **Fork count**: typical `npx → tool` / `uvx → tool` wrapper
     trees are 2-3 levels deep with B=1-3 children per node →
     pre-fix BFS forked ~5-10 subprocesses per pool-shutdown call.
     Post-fix: exactly 1 fork regardless of tree depth.
  2. **Snapshot consistency**: pre-fix BFS walked the table level
     by level; a child that forked between two adjacent BFS levels
     could be missed (we'd see the child but query its
     descendants AFTER the new fork). The snapshot path captures
     the table at one instant; new descendants forked after the
     snapshot are tolerated by the existing ESRCH-tolerant
     SIGTERM loop.

Caveats:
  - `ps -A -o pid=,ppid=` is POSIX standard (macOS / Linux /
    *BSD), but BusyBox `ps` <v1.28 (2018) doesn't support `-o`.
    Distroless containers may not have `ps` at all. To preserve
    behavior on those edge platforms, the legacy per-pid `pgrep`
    BFS is retained as a fallback (`listDescendantPidsUnixPgrepFallback`).
    Same retention on Windows for the per-pid filter path.
  - Snapshot path uses `maxBuffer: 8MB` to cover ~250k-process
    pathological hosts. Default 1MB would clip at ~30k processes.
  - `MAX_DESCENDANTS = 256` / `MAX_DEPTH = 8` caps preserved on
    both snapshot + fallback paths.
  - Snapshot scans the entire host process table (not just the
    target subtree). On the typical 200-500 process developer
    machine this parses in <10ms; the win over BFS is real but
    not order-of-magnitude — ~2x improvement, not 100x. PR A's
    motivation framing is "fork hygiene + consistency", not raw
    perf.

Empty-result detection: snapshot path tracks `parsedRows`. If the
ps/CIM tool runs successfully but produces 0 parseable rows
(BusyBox without `-o` echoing usage, AppLocker truncating CIM
output, etc.), we throw — the outer catch falls back to the
per-pid path. A genuine "root has no children" case parses many
rows and just returns empty from the walk. So the
"no-children-found" semantics are preserved across both paths.

Test gate update: pre-fix `integration: spawn-and-enumerate` test
skipped on `CI === '1'` because pgrep wasn't available on
minimal CI runners. Post-fix `ps -A` is universally available on
non-distroless Linux/macOS — only the Windows skip remains.
6/6 pid-descendants tests pass including the now-active
integration spawn test.

Design doc (`docs/design/f2-mcp-transport-pool.md` §6.4 + the F2
follow-up table at lines 82-85) updated to reflect the snapshot
+ fallback shape, and to mark W11 / W12 / R9 / R10 as ✅ Done in
PR A with the per-fix commit refs.

This commit completes F2 cleanup PR A. Filed bucket order:
R9 (commit 0cb1eaa27) → W11 (commit 2d546efca) → W12 (commit
a4a855ab3) → R10 (this commit). Issue #4175 item 7 "F2 post-
merge cleanup PRs": PR A done; PR B (W93 + W133-a + W134) and
PR C (W133-c SDK breaking) to follow as separate clusters.

Test sweep: 287/287 F2 + cli pass; ESLint clean; typecheck clean
(core + cli). Integration test on macOS local runs the new
snapshot path successfully.

* refactor(core): F2 PR A R2 — wenshao followup (visited set + dedup predicate)

Two Suggestions from wenshao's first PR #4411 review pass (07:15Z),
both small and worth folding before merge:

PR-A-R2 #1 (pid-descendants.ts:309 — walkDescendants visited set):
  `walkDescendants`'s BFS lacked a `visited` set. If the snapshot
  captures a PID-reuse cycle — rare but possible on busy hosts with
  rapid pid churn between `ps -A`'s start and parse, where Linux
  wraparound can show a freed pid in a different parent's children
  list creating an A→B / B→A cycle — pre-fix BFS would revisit nodes
  and fill the MAX_DESCENDANTS=256 quota with duplicate entries,
  starving legitimate descendants. Pre-PR-A the per-pid `pgrep` BFS
  had the same theoretical issue but was less exposed (each
  `pgrep -P pid` call returns only DIRECT children; snapshot captures
  the whole tree at once, making cycles instantly visible).

  Fix: 3-LOC `Set<number>` add. `root` seeded into `visited` so a
  malformed snapshot listing root as a descendant of its own child
  doesn't re-enqueue root either.

PR-A-R2 #2 (session-mcp-view.ts:117 — predicate dedup):
  After W12, the exported `passesSessionFilter` /
  `passesSessionPromptFilter` still called `passesNameFilter` (the
  pre-W12 array-based implementation), while `applyTools` /
  `applyPrompts` used `compiledFilterAccepts(compileNameFilter(...))`.
  Two parallel implementations of the same predicate — future change
  to one without the other would silently diverge:
    - the exported function's tests (passesSessionFilter unit tests)
      would still pass
    - the production filter path in applyTools/applyPrompts would
      behave differently

  Reviewer also noted `passesSessionPromptFilter` had zero callers
  in production code or tests after W12 — `applyPrompts` no longer
  references it. Kept the export rather than deleting it (matches
  the `passesSessionFilter` shape for symmetry + the F3 audit-path
  comment block earmarks both as the replay predicates), but routed
  both through `compiledFilterAccepts(compileNameFilter(...))` so
  there is a single source of truth. Set construction is per-call
  for these exports (negligible for unit-test / one-off probes);
  the bulk paths in `applyTools` / `applyPrompts` still construct
  ONE filter per pass via the original W12 code path.

`passesNameFilter` (the standalone array-based helper) deleted —
its only callers were the two exports, which now use the compiled
path. Public-API surface unchanged: the two exported functions
keep their signatures and semantics.

Test sweep: 19/19 pid-descendants + session-mcp-view tests pass;
typecheck + ESLint clean.

Continues commit chain: f05917071 (R9) → 20d2f1b90 (W11) →
6cf18f641 (W12) → 2a41c6fae (R10) → this (R2 followups).

* fix(core): F2 PR A R3 T3 — Windows CSV delimiter locale fix

`ConvertTo-Csv -NoTypeInformation` honors the system locale's list
separator on PowerShell 5.1. On German / French / Dutch / Italian /
... locales the separator is `;` not `,`, so the regex
`^"(\d+)","(\d+)"$` in `snapshotProcessTreeWin` never matched →
`parsedRows === 0` → snapshot threw → fell back to the per-pid CIM
filter path with ~0.5-1s extra PowerShell startup latency per
descendant on every pool shutdown.

Fix: 1-LOC `-Delimiter ","` on `ConvertTo-Csv`. Forces comma
regardless of locale or PowerShell version. PowerShell 7+ defaults
to comma already; 5.1 (the Windows-bundled version most users have
without explicit upgrade) honored locale. The explicit delimiter
makes both consistent.

Skipped wenshao's companion Suggestion T4 (test coverage for
walkDescendants MAX_DESCENDANTS / MAX_DEPTH caps) as F2 hardening
follow-up — the caps are simple 2-line guards exercisable by
inspection; ~50 LOC of mock infrastructure isn't commensurate
with the regression risk on currently-stable defensive code,
and (per the issue #4175 follow-up bucket) we keep dedicated
test-coverage work out of perf-cleanup PRs.

Continues commit chain: f05917071 (R9) → 20d2f1b90 (W11) →
6cf18f641 (W12) → 2a41c6fae (R10) → ced5d62b0 (R2) → this (R3 T3).

Test sweep: 6/6 pid-descendants tests pass; typecheck + ESLint clean.

* refactor(acp-bridge): F1 test split — lift bridge.test.ts (6861 LOC) to acp-bridge (#4445)

* refactor(acp-bridge): rename httpAcpBridge.test.ts -> bridge.test.ts (git mv)

Pure file rename; zero content change. Follow-up commits will:
- extract FakeAgent + makeChannel + makeBridge into testUtils.ts
- split 4 daemon-host integration tests back to cli/daemonStatusProvider.test.ts

Part of #4175 F1 test split (deferred from #4334).

* refactor(acp-bridge): extract testUtils + split daemon-host tests to cli (#4175 F1)

Net mechanical extraction following commit 2aff1a4d1 (pure git mv of
httpAcpBridge.test.ts -> bridge.test.ts). After this commit
`@qwen-code/acp-bridge` owns the bulk of the lifted bridge test
suite, and cli keeps only the 4 daemon-host integration tests that
need to wire `createDaemonStatusProvider()`.

Changes:

1. New `packages/acp-bridge/src/internal/testUtils.ts` (~280 LOC):
   FakeAgent, FakeAgentOpts, ChannelHandle, makeChannel, makeBridge
   (no statusProvider default — acp-bridge tests exercise the
   no-provider fallback path), WS_A/WS_B/SESS_A constants. Marked
   @internal; lives under `internal/` matching the existing
   `stderrLine.ts` package-private convention. Exposed via new
   `./internal/testUtils` subpath in package.json exports.

2. `packages/acp-bridge/src/bridge.test.ts` shrinks from 6861 ->
   ~6400 LOC: fixtures replaced with named imports from
   `./internal/testUtils.js`; cross-package import
   `from './daemonStatusProvider.js'` removed (4 daemon-host tests
   moved out); ACP SDK + bridgeErrors / workspacePaths / bridge /
   channel / bridgeTypes imports split into multiple statements
   reflecting actual post-F1 provenance.

3. New `packages/cli/src/serve/daemonStatusProvider.test.ts`
   (~240 LOC, 4 tests): wires real `createDaemonStatusProvider()`
   through a cli-side `makeBridge` wrapper to assert end-to-end
   daemon env / preflight cells. Imports
   `createHttpAcpBridge` via the `./httpAcpBridge.js` re-export
   shim — doubles as a shim surface smoke check.

Verification:
- acp-bridge: 291/291 tests pass (177 in bridge.test.ts).
- cli: daemonStatusProvider.test.ts 4/4 pass; full cli suite 6742/6767
  green (16 pre-existing failures in AuthDialog / memoryDiagnostics /
  useAtCompletion — all on `daemon_mode_b_main` baseline, last
  modified by commits predating this branch).
- Tests counts pre-split: 181 in httpAcpBridge.test.ts;
  post-split: 177 in bridge.test.ts + 4 in daemonStatusProvider.test.ts
  = 181 (parity preserved).

Part of #4175 F1 test split (deferred from #4334).

* refactor(acp-bridge): self-review round 1 — vitest alias + doc/comment polish

Five code-reviewer findings folded in on top of e97282f30:

S1 [Suggestion] — Test-utils ships to npm + cli reads stale dist.
  Added `packages/cli/vitest.config.ts:resolve.alias` mapping
  `@qwen-code/acp-bridge/internal/testUtils` → the .ts source. The
  package subpath export is RETAINED (required for TypeScript
  `nodenext` to resolve types — it won't fall back to tsconfig
  paths once exports rejects a subpath). Dual-channel approach
  documented in the testUtils JSDoc, including the alpha-stage 0.0.1
  tradeoff that the file still ships in dist (stripInternal /
  .npmignore deferred).

S2 [Suggestion] — Stale wording "two tests" in narrative comment.
  bridge.test.ts split-marker now correctly says "4 fallback tests"
  (no-provider × 2 surfaces + throwing-provider × 2 surfaces).

S3 [Suggestion] — "Shim smoke check" only half-applied.
  daemonStatusProvider.test.ts now routes `BridgeOptions` and
  `HttpAcpBridge` types through `./httpAcpBridge.js` shim too
  (alongside `createHttpAcpBridge`), so the entire factory surface
  the cli tests rely on flows through the F1 re-export shim.

N1 [Nit] — Asymmetric split-marker phrasing.
  Both markers now describe the 4 moved tests by surface
  (env real / preflight idle / preflight merged-live /
  preflight extMethod-throws) rather than "1 of" + "3 more".

N2 [Nit] — testUtils "the suite" ambiguity.
  makeChannel JSDoc now references `bridge.test.ts` explicitly
  instead of "the suite" (which was unambiguous pre-split when
  helpers + 10 createInMemoryChannel sites lived in the same file).

Verification: 291/291 acp-bridge tests pass; 4/4 cli daemon
integration tests pass; tsc clean on both packages (pre-existing
server.ts errors on baseline unchanged); eslint --max-warnings 0
clean on all 4 touched files.

* docs(cli): self-review round 2 — fix stale vitest.config.ts alias comment

Round 2 reviewer caught a 3-way contradiction in the round 1 docs:
- vitest.config.ts said: alias replaces the export, internal/* stays
  unpublished (matches stderrLine convention).
- package.json: subpath export IS declared.
- testUtils.ts JSDoc: both channels intentionally retained,
  testUtils ships in dist.

Round 1 explicitly chose to retain the export because TS `nodenext`
won't fall back to tsconfig `paths` once `exports` rejects a
subpath; the alias only serves to short-circuit *runtime* resolution
so cli reads src/ not dist/. Rewriting the vitest.config.ts comment
to reflect that dual-channel reality (and pointing readers at
testUtils.ts for the full rationale).

* fix(acp-bridge): #4445 round 3 fold-in — 4 of 7 reviewer threads adopted

PR #4445 review pass — 4 adopt + 3 decline (declines replied
inline; not folded here):

ADOPTED:

T1 [copilot daemonStatusProvider.test.ts:136 — bridge.shutdown
   missing]: added `await bridge.shutdown()` to test 2 (preflight
   idle). Three of four tests already shut down; symmetry +
   future-proof if `createHttpAcpBridge` gains background work
   even when no channel was spawned.

T5 [wenshao testUtils.ts:92 — makeBridge naming collision]: cli-
   side helper renamed `makeBridge` -> `makeBridgeWithDaemonStatusProvider`
   (4 call sites in daemonStatusProvider.test.ts), JSDoc updated to
   reference the wenshao thread. testUtils.makeBridge stays as the
   canonical name used by ~100 tests in bridge.test.ts. A future
   contributor can no longer pick the wrong helper by accident.

T6 [wenshao testUtils.ts:32 — JSDoc mis-claims @internal tag matches
   stderrLine.ts convention]: fixed wording. stderrLine.ts uses prose
   only; @internal is an additional package-private signal, not a
   convention match. Also restructured the npm-leak paragraph to
   describe the new .npmignore-via-files-negation enforcement (T7).

T7 [wenshao package.json:70 — testUtils ships to npm]: switched
   `files: ["dist"]` -> `files: ["dist", "!dist/internal/testUtils.*",
   "!dist/**/*.test.*"]`. Wenshao's suggested `"test"` exports
   condition wasn't viable: vitest sets `vitest` not `test`, and
   gating on `vitest` would hide types from the cli's tsc compile.
   The negation-pattern files-field excludes the built testUtils
   from the publish surface while keeping the subpath export entry
   that TypeScript `nodenext` needs to resolve types. Verified via
   `npm pack --dry-run`: dist/internal/stderrLine.* still ships
   (production internal helper); dist/internal/testUtils.* +
   dist/**/*.test.* are excluded.

DECLINED (replied on PR threads, not folded here):

T2/T3 [copilot — `handles` array unused in tests 3/4]: bookkeeping
   matches the pre-split bridge.test.ts verbatim; cleanup is scope
   creep on this rename PR.

T4 [copilot — testUtils eager-imports createHttpAcpBridge,
   cross-copy identity risk]: cli daemonStatusProvider.test.ts uses
   its OWN local `makeBridgeWithDaemonStatusProvider` and never
   imports testUtils.makeBridge — the cross-copy concern isn't
   triggered. Premature abstraction on a test-only fixture.

Verification: 291/291 acp-bridge tests pass; 4/4 cli daemon tests
pass; tsc clean both packages; eslint --max-warnings 0 clean on
2 touched .ts files; `npm pack --dry-run` confirms publish-surface
exclusions.

* fix(core): F2 cleanup PR B — self-heal observability (W133-a + W134) (#4460)

* fix(core): F2 cleanup PR B — self-heal observability (W133-a + W134)

W93 declined as already satisfied by W1 fix in #4336 commit 6
(spawnEntry's catch already calls forceShutdown which runs the full
cleanup table — listener removal, timer clear, subscriber detach,
sweep+disconnect, onClosed eviction). Source-verified non-repro.

W133-a: McpClient.onerror now captures the error in a private
`lastTransportError` field (reset at each connect()); the W120
silent-drop block at mcp-pool-entry.ts:346 reads it via the new
`getLastTransportError()` getter and appends `: <error.message>` to
the lastError string on the emitted 'failed' event. Preserves the
literal "silent transport drop" prefix invariant for log-grep
backward compat — pre-fix marker stays a substring.

W134: sweepAndDisconnect now returns SweepResult instead of void —
{ pidSweepError?, disconnectError?, descendantsFound?,
descendantsSignaled? }. The silent-drop fire-and-forget caller chains
to inspect the result and emits a structured warn log when either
pid-sweep threw OR sigtermPids partially signaled (signaled < found)
— surfaces orphan-process pressure without inflating PR scope (no
new SSE event or SDK reducer state; deferred to W134-followup if
maintainers want metrics).

forceShutdown / doRestart sweep callers ignore the return value (JS
implicit-void at await sites preserves behavior).

4 new tests in mcp-transport-pool.test.ts covering W133-a happy path
+ fallback (no prior onerror) + W134 pidSweepError + W134
partial-signal failure modes. Module-mocks pid-descendants.js for
controllable sweep behavior, and debugLogger.js to observe warn
calls (production logger is session-gated and a no-op in tests).
Singleton-stub debugLogger mock so production module-load
`createDebugLogger('McpPool:Entry')` and the test's retrieval get
the same vi.fn instances.

Verification:
- tsc clean: packages/core, packages/cli (server.ts pre-existing
  errors unchanged)
- F2 transport-pool: 32/32 pass (28 pre-existing + 4 new)
- mcp-client: 46/46 pass
- eslint --max-warnings 0 clean on 3 touched files

Part of #4175 #4336 follow-up bucket.

* fix(core): #4460 round 1 fold-in — 4 copilot doc/comment threads adopted

T1 [copilot mcp-pool-entry.ts:116 — stale line ref in SweepResult JSDoc]:
  replaced `mcp-pool-entry.ts:383` with stable method-anchor reference
  to the W120 silent-drop block inside `statusChangeListener`. Line
  numbers drift on every edit; method names don't.

T2 [copilot mcp-pool-entry.ts:453 — `?? 0` ambiguous in warn payload]:
  silent-drop warn log now prints `descendantsFound=unknown` and
  `descendantsSignaled=unknown` when the values are undefined (only
  reachable in the pidSweepError branch — sweep threw before
  assignment). Operators triaging the warn can now distinguish
  "sweep succeeded but found 0 descendants" from "sweep itself
  threw, count is genuinely unmeasured". Locked in via a new
  assertion in the W134 pidSweepError test.

T3 [copilot mcp-client.ts:116 — brittle line refs in lastTransportError
  JSDoc]: replaced `mcp-pool-entry.ts:346` and `mcp-client.ts:130`
  with stable method/block names (the `statusChangeListener` silent-
  drop block; the `client.onerror` arrow inside connect()). Same
  fix applied to the parallel comment in mcp-transport-pool.test.ts:730
  for consistency.

T4 [copilot mcp-transport-pool.test.ts:797 — singleton-stub mock comment
  contradictory]: rewrote the comment to unambiguously describe what
  the mock DOES (factory body runs once; inner arrow returns the same
  object on every call) instead of the prior hypothetical phrasing
  ("Returning a fresh object would have...") which read as a
  description of current behavior at first glance.

All 4 are doc/comment fixes — zero behavior change apart from the
T2 string format ('unknown' instead of '0'). Verified:
- 32/32 mcp-transport-pool.test.ts pass
- tsc clean on packages/core
- eslint --max-warnings 0 clean on 3 touched files

* fix(core): #4460 round 2 fold-in — remove dead SweepResult.disconnectError field

T5 [wenshao mcp-pool-entry.ts:134 — `disconnectError` is dead data]:
  glm-5.1 review caught that the field was populated when
  `client.disconnect()` threw (line 844) but no consumer ever read
  it — the silent-drop `.then()` handler gated only on
  `pidSweepError` and partial-signal; `forceShutdown` and `doRestart`
  ignore the return; no test asserted on it.

Removed the field from `SweepResult` and the assignment in the
disconnect catch. The pre-existing `debugLogger.error(`client.disconnect
failed for ...`)` inside `sweepAndDisconnect` already gives operators
the signal — adding it to the outer silent-drop warn would have been
duplicate noise. If a future consumer needs to gate logic on disconnect
failures, re-add the field + reader at that point.

Verification: 32/32 mcp-transport-pool.test.ts pass; tsc + eslint
clean on the touched file.

* feat(sdk/daemon-ui): unified completeness follow-up to #4328 (#4353)

* feat(sdk/daemon-ui): expand event coverage to 28+ daemon event types (PR-A)

Closes the "12+ daemon events fall through to debug" gap surfaced in the PR
the daemon currently emits (Stage 1 + Wave 3-4), so renderers stop having
to peek at `rawEvent.data` for known event categories.

Session-meta:
- session.metadata.changed (from session_metadata_updated)
- session.approval_mode.changed (from approval_mode_changed)
- session.available_commands (from available_commands_update; upgraded
  from a status-text fallback to a typed event carrying the command list)

Workspace state (Wave 3-4):
- workspace.memory.changed
- workspace.agent.changed
- workspace.tool.toggled
- workspace.initialized
- workspace.mcp.budget_warning
- workspace.mcp.child_refused
- workspace.mcp.server_restarted
- workspace.mcp.server_restart_refused

Auth device-flow (Wave 4 OAuth, RFC 8628):
- auth.device_flow.started
- auth.device_flow.throttled
- auth.device_flow.authorized
- auth.device_flow.failed (carries DaemonAuthDeviceFlowSdkErrorKind)
- auth.device_flow.cancelled

- `DaemonUiErrorEvent.errorKind?: DaemonErrorKind` — closed-enum error
  category propagated from daemon's typed-error taxonomy. Renderers can
  branch on errorKind for "retry auth" vs "check file path" affordances
  instead of regex-matching `text`.
- `DaemonUiToolUpdateEvent.provenance?: DaemonUiToolProvenance` +
  `.serverId?` — closed enum ('builtin' | 'mcp' | 'subagent' | 'unknown').
  Falls back to the `mcp__<server>__<tool>` naming heuristic when the
  daemon doesn't stamp provenance explicitly. Unblocks UI namespace
  dispatch without string-matching toolName.

Session-meta / workspace / auth events do NOT push transcript blocks.
They are intentional sidechannel observations: `lastEventId` advances
(monotonic invariant preserved), but the chat-stream transcript stays
focused on user/assistant/tool/shell/permission content. Renderers
consume them via selectors (introduced in follow-up PRs).

All new event types produce short structured lines in
`daemonUiEventToTerminalText` for tail-style debug consumers. Web/IDE
renderers should consume the typed events directly via subscription.

40/40 tests pass. New tests verify:
- All 16 new event types normalize correctly
- Malformed payloads fall back to debug without leaking raw data
  (`secret` field never appears in fallback text)
- MCP tool provenance heuristic (`mcp__github__create_issue` →
  provenance='mcp', serverId='github')
- errorKind propagation on session_died / stream_error
- Reducer is no-op on new event types; lastEventId still advances

This is PR-A of the unified-renderer-layer follow-up series:
- PR-A (this commit) — event coverage + closed-enum schema
- PR-B — server-side timestamps + ordering refactor
- PR-C — multimodal content + tool preview taxonomy
- PR-D — render contract (toMarkdown / toHtml / toPlainText) + adapter
  conformance test framework
- PR-E — reducer state machine (subagent / progress / current tool /
  cancellation propagation)

See https://github.com/QwenLM/qwen-code/pull/4328#issuecomment-4494179724
for the full proposal.

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): server timestamps + event-id-based ordering (PR-B)

Closes the "时间定义不标准" gap surfaced in the PR #4328 review:
- Client-side `Date.now()` drifts across clients
- No daemon-authoritative timestamp propagated to UI
- Out-of-order replay events get fresher `state.now` than originals,
  breaking `createdAt` ordering

- `DaemonUiEventBase.serverTimestamp?: number` — daemon-authoritative
  wall-clock timestamp extracted from envelope.
- `DaemonTranscriptBlockBase.serverTimestamp?: number` + `clientReceivedAt: number`.
- `createdAt` preserved as `@deprecated` alias for `clientReceivedAt`
  (backward compat for code written before this PR).

`extractServerTimestamp` looks at three candidate envelope locations:

1. `event.serverTimestamp` (preferred when daemon adds it)
2. `event._meta.serverTimestamp` (Anthropic-style metadata convention)
3. `event.data._meta.serverTimestamp` (sessionUpdate nested location)

The SDK is ready to consume serverTimestamp WHEN daemon emits it, without
requiring a coordinated SDK release. Undefined when daemon doesn't emit
(current state) — graceful degradation to client-clock ordering.

`selectTranscriptBlocksOrderedByEventId(state)` — returns blocks sorted by:

1. `eventId` (daemon-monotonic SSE cursor) — primary key
2. `serverTimestamp` (daemon wall clock) — fallback for synthetic frames
3. `clientReceivedAt` (local clock) — last resort

Use this when displaying long sessions where event id 5 may arrive AFTER
event id 7 (typical in SSE replay-after-reconnect).

`formatBlockTimestamp(block, opts)` — formats the most authoritative
timestamp on a block using `Intl.DateTimeFormat`. Prefers
`serverTimestamp` over `clientReceivedAt` for cross-client consistency.
Accepts locale / timeZone / dateStyle / timeStyle.

Daemon needs to stamp `_meta.serverTimestamp` on every SSE envelope. This
SDK PR is ready to consume it the moment the daemon ships the field; no
coordination needed.

- serverTimestamp extraction from all three envelope locations
- Defaults undefined when envelope has none
- `selectTranscriptBlocksOrderedByEventId` sorts mixed-arrival events by
  eventId (replay scenario)
- `formatBlockTimestamp` prefers serverTimestamp; returns localized string

PR-B of the unified follow-up to PR #4328 (PR-A + PR-B + PR-C + PR-D +
PR-E in one branch).

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): reducer state machine — currentTool / approvalMode / cancellation propagation (PR-E)

Closes the "reducer state machine 设计缺漏" gap surfaced in the PR #4328 review:
- No `currentTool` — UI scans `blocks[]` to find the running tool
- No mirrored approval mode — UI walks events to badge "plan"/"yolo"
- Cancellation does not propagate — in-flight tool blocks stuck at
  'in_progress' forever when the parent prompt is cancelled

## State additions (sidechannel, no transcript blocks)

`DaemonTranscriptSidechannelState`:
- `currentToolCallId?: string` — toolCallId of the in-flight tool
- `approvalMode?: string` — mirrored from session.approval_mode.changed
- `toolProgress: Record<string, { ratio?, step? }>` — per-tool progress
  shape (daemon-side emission of `tool.progress` events pending)

## Reducer behavior

### `tool.update` events

`IN_FLIGHT_TOOL_STATUSES` = { pending, confirming, running, in_progress }
`TERMINAL_TOOL_STATUSES` = { completed, success, failed, error, canceled, cancelled }

- Tool enters in-flight: set `currentToolCallId = event.toolCallId`
- Tool enters terminal: clear `currentToolCallId` if it matches
- Unknown status (forward-compat): leave pointer untouched

This avoids the failure mode where a future daemon-emitted status like
`'paused'` would silently mark unknown states as either in-flight or
terminal incorrectly.

### `session.approval_mode.changed`

Mirror `event.next` onto `state.approvalMode`. Renderers can render a
mode badge ("plan" / "default" / "auto-edit" / "yolo") with a single
selector call, no event-stream walking.

### `assistant.done` with `reason === 'cancelled'`

`propagateCancellationToInFlightTools` walks every tool block whose
status is still in-flight and force-sets it to 'cancelled'. The daemon
does not guarantee terminal `tool_call_update` for every in-flight tool
when the parent prompt is cancelled, so this propagation prevents UI
spinners from spinning forever.

`currentToolCallId` is also cleared in the same call.

Non-cancellation `assistant.done` (e.g., `reason: 'end_turn'`) does NOT
propagate — in-flight tools remain in-flight until the daemon emits
their terminal update naturally.

## Selectors

- `selectCurrentTool(state)` — returns the running tool block, or undefined
- `selectApprovalMode(state)` — returns the mirrored approval mode
- `selectToolProgress(state, toolCallId)` — per-tool progress query

All exported from `@qwen-code/sdk/daemon`.

## Scope deliberately deferred

Subagent nesting (`parentBlockId` / `delegationId` / `DaemonSubagentTranscriptBlock`)
is NOT in this PR. The shape needs design discussion (how to project nested
events; whether to bake delegation tracking into transcript or sidechannel).
PR-D / PR-F follow-up.

## Test coverage (51/51 pass)

- currentToolCallId set on enter, cleared on terminal
- approvalMode mirrors changes
- Cancellation marks in-flight tools 'cancelled', leaves completed alone
- Unknown status does NOT clear currentToolCallId (forward-compat)
- Non-cancellation `assistant.done` does NOT propagate

## Roadmap

PR-E of the unified follow-up to PR #4328 (PR-A + PR-B + PR-E in this
branch; PR-C / PR-D pending).

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): tool preview taxonomy + multimodal content extraction (PR-C)

Closes two related gaps surfaced in the PR #4328 review:
- `DaemonToolPreview` had only 4 kinds — UI fell back to `key_value` /
  `generic` for tools that deserved structured display
- `getTextContent` silently dropped non-text content (image / audio /
  resource), so multimodal conversations vanished from the UI

`DaemonToolPreview` extends from 4 to 8 variants:

- `file_diff` — `{ path, oldText?, newText?, patch? }` — file edit tools
  (Anthropic-style `oldText/newText`, aider-style `patch`, write-style
  `newText` alone)
- `file_read` — `{ path, range?: [start, end] }` — file read tools, with
  range extracted from `lineRange` tuple OR `offset/limit` pair
- `web_fetch` — `{ url, method? }` — HTTP fetch tools (requires URL
  with scheme to avoid false positives on relative paths)
- `mcp_invocation` — `{ serverId, toolName, argsSummary? }` — MCP server
  tool calls, identified via `mcp__<server>__<tool>` naming convention
  (same heuristic as PR-A `DaemonUiToolUpdateEvent.provenance`)

Detector order matters — MCP wins first (most specific), then file_diff,
file_read, web_fetch, then the existing command / key_value fallbacks.

New helper `extractContentPart(value): DaemonUiContentPart | undefined`
returns a discriminated union:

```ts
type DaemonUiContentPart =
  | { kind: 'text'; text: string }
  | { kind: 'image'; mediaType: string; source: { url?, data? } }
  | { kind: 'audio'; mediaType: string; source: { url?, data? } }
  | { kind: 'resource'; uri: string; mediaType?, description? };
```

The existing `getTextContent` is preserved for backward compat. Renderers
that need to surface non-text content (web UI thumbnails, IDE attachment
chips) now have a typed shape to consume.

- Wiring `extractContentPart` into the normalizer / reducer so text
  blocks accumulate `parts: DaemonUiContentPart[]` alongside `text`
  (additive shape change requires render contract coordination — PR-D).
- 5 additional tool preview kinds (image_generation / code_block /
  tabular / subagent_delegation / search) — useful but not urgent;
  current 8 kinds cover the typical agent flows.

- file_diff detection from Anthropic / aider / write shapes
- file_read with lineRange tuple AND offset+limit pair
- web_fetch with method, REJECTS relative paths (no scheme)
- mcp_invocation with serverId + toolName extraction
- Detector priority: MCP wins over file_diff on conflicting shapes
- extractContentPart for text / image (url) / audio (data) / resource
- Unknown content type returns undefined (skip rather than synthesize)
- Image without source returns undefined (defensive)

PR-C of the unified follow-up to PR #4328 (PR-A + PR-B + PR-E + PR-C in
this branch; PR-D render contract pending).

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): render contract — markdown / HTML / plain text helpers (PR-D)

Closes the "render 契约只覆盖 terminal" gap surfaced in the PR #4328 review:

> PR ships `daemonUiEventToTerminalText` for terminal. Web/IDE/channel
> adapters each roll their own projection. No shared contract → adapter
> divergence is inevitable.

## New helpers

```ts
daemonBlockToMarkdown(block, opts?): string  // GFM-compatible
daemonBlockToHtml(block, opts?): string      // conservatively escaped HTML
daemonBlockToPlainText(block, opts?): string // for copy-paste / logs
daemonToolPreviewToMarkdown(preview, opts?): string
```

All three respect the same `kind` discrimination so adapters can switch
between them without touching call sites.

## Per-kind projection

For each `DaemonTranscriptBlock['kind']`:

- `user` / `assistant` / `thought` — plain text with role labels
- `tool` — header with toolName + structured preview + status badge
- `shell` — fenced code block, stream-discriminated (stdout vs stderr)
- `permission` — title + options list + resolved/pending indicator
- `status` / `debug` / `error` — semantic class / role (error → role=alert)

For each `DaemonToolPreview['kind']`:

- `ask_user_question` — question + options as bullet list
- `command` — fenced bash with optional cwd comment
- `file_diff` — unified diff in fenced code block (oldText/newText OR patch)
- `file_read` — `path (lines N-M)` line
- `web_fetch` — `METHOD url` line
- `mcp_invocation` — `serverId::toolName` with args summary
- `key_value` — bullet list
- `generic` — emphasized summary

## Security

- Default HTML sanitizer escapes `<`, `>`, `&`, `"`, `'` and FIRST strips
  ANSI/control sequences via `sanitizeTerminalText` (defense against
  agent-emitted escape codes in HTML output).
- Custom sanitizer hook for consumers wanting markdown→HTML pipelines
  (markdown-it + DOMPurify, etc.).
- `sanitizeUrls` option strips token-like query params (`token=`, `key=`,
  `x-amz-`, etc.) from URLs in `web_fetch` previews.
- `maxFieldLength` truncation defaults 8192, prevents pathological
  rendering on huge content.

## Adapter conformance (out of scope for this commit)

The conformance test framework (fixture corpus + `runAdapterConformanceSuite`)
mentioned in PR-D scope is deferred to a follow-up. The render helpers
here are the precondition — once stable, the conformance framework can
use them as the reference projection.

## Test coverage (77/77 pass)

- All 9 block kinds render in markdown (verified for user/assistant/tool/
  shell/permission/error specifically)
- file_diff renders as unified diff with old/new lines
- mcp_invocation renders as `server::tool` format
- HTML escapes XSS (`<script>` → `&lt;script&gt;`)
- HTML strips terminal escape sequences before escaping
- Error blocks emit `role="alert"` for screen readers
- plain text drops markdown delimiters
- maxFieldLength truncates with ellipsis
- sanitizeUrls strips token query params
- Custom sanitizer hook works

## Roadmap

PR-D of the unified follow-up to PR #4328 — completes the 5-PR series
(A: event coverage, B: time schema, E: state machine, C: tool preview +
content extraction, D: render contract).

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): 5 additional tool preview kinds — taxonomy complete (PR-F)

Closes the "5 additional preview kinds" item in PR #4353's TODO §A
(SDK-only work).

## New preview kinds (8 → 13)

- `code_block` — `{ language?, code, origin? }` — REPL / formatter /
  generator output, fenced as `\`\`\`<language>` in markdown
- `search` — `{ query, resultCount?, top? }` — grep / ripgrep / find /
  glob results with up to 5 top hits
- `tabular` — `{ columns, rows, totalRows? }` — structured table output
  (50-row cap with `totalRows` truncation indicator); supports both
  `columns: string[] + rows: unknown[][]` explicit shape and legacy
  `data: Array<Record<>>` shape (auto-infers columns from first row)
- `image_generation` — `{ prompt, thumbnailUrl?, model? }` — dall-e /
  diffusion / imagen / flux / sora style tools
- `subagent_delegation` — `{ agentName, task, parentDelegationId? }` —
  Anthropic-style Task tool and similar sub-agent dispatchers

## Detector priority

Order matters — most specific wins. New detectors slot in between
`mcp_invocation` and `file_diff`:

```
mcp_invocation > subagent_delegation > search > image_generation
  > file_diff > file_read > web_fetch > code_block > tabular
  > command > key_value > generic
```

Rationale: subagent / search / image generation are most discriminable
(distinct toolName patterns); file ops next; code_block / tabular last
because their shapes (`code:`, `columns:`) can appear in other tools.

## Render projections

Both `daemonToolPreviewToMarkdown` and the plain-text rendering paths
extended with cases for all 5 new kinds:

- code_block: fenced markdown code block with language tag
- search: bold header + GFM bullet list of top results
- tabular: GFM pipe table with header / separator / body / truncation hint
- image_generation: bold header + blockquoted prompt + embedded markdown
  image (URL sanitization respected via `sanitizeUrls` opt)
- subagent_delegation: bold delegate-arrow header + blockquoted task +
  optional parent delegation reference

## Test coverage (91/91 pass, +14 new)

- Each detector with positive case
- Detector priority verified: subagent_delegation wins over file_diff
  when toolName='Task' has both subagent + file-edit fields
- Tabular row cap (50) + totalRows stamping for truncated data
- Legacy data: Array<Record<>> auto-column inference
- Each render projection with structural assertions (markdown table
  format, image embed, bullet lists)

## Roadmap

PR-F of the unified follow-up to PR #4328. Brings the preview taxonomy
to 13 kinds covering: file ops (3), web (1), code/data (2), media (1),
agent control (2 — ask_user_question + subagent_delegation), MCP (1),
search (1), generic fallbacks (2).

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(sdk/daemon-ui): adapter conformance framework + fixture corpus (PR-G)

Closes the "Adapter conformance test framework" item in PR #4353's TODO §A.
Lets any daemon-ui adapter (TUI / web / IDE / channel / mobile) validate
that it projects a fixed corpus of daemon SSE event streams to the same
semantic shape — catches projection drift before it reaches users.

## API surface

```ts
interface DaemonUiAdapterUnderTest {
  reduce(events: readonly DaemonUiEvent[]): unknown;
  renderToText(state: unknown): string;
}

interface DaemonUiConformanceFixture {
  name: string;
  description: string;
  envelopes: DaemonEvent[];           // raw daemon envelopes
  expectedContains: string[];          // phrases the rendered text MUST contain
  expectedAbsent?: string[];           // phrases that MUST NOT appear
  normalizeOptions?: { ... };          // forward-compat normalize opts
}

runAdapterConformanceSuite(adapter, opts?): ConformanceSuiteResult
DAEMON_UI_CONFORMANCE_FIXTURES: ReadonlyArray<DaemonUiConformanceFixture>
```

## Design

**Format-agnostic assertion**: adapters can render to ANSI / HTML /
markdown / JSX — the framework only inspects plain text via
`renderToText`. Catches semantic divergence (missing user message,
wrong tool status, leaked secret) without forcing identical formatting.

**Embedded fixture corpus** (no fs reads — works in browser bundle):
- `simple-chat` — user/assistant streaming flow
- `tool-call-lifecycle` — running → completed transition
- `file-edit-diff` — file_diff preview surfacing
- `mcp-invocation` — MCP serverId/toolName extraction via heuristic
- `permission-lifecycle` — request + resolved with outcome
- `mcp-budget-warning` — Wave 3 event (adapter must observe but rendering
  is its choice)
- `cancellation-propagates` — tool block status flows
- `malformed-payload-redaction` — uses `includeRawEvent: true` to verify
  even a debug-mode adapter doesn't leak `token: secret-do-not-leak`
- `auth-device-flow-success` — Wave 4 OAuth events
- `available-commands-typed-event` — PR-A upgrade from status text

Per-fixture `expectedContains` and `expectedAbsent` describe the
content contract independently of format.

## Suite result

```ts
{
  passed: number,
  failed: ConformanceFailure[],   // each carries missing + leaked + excerpt
  total: number,
}
```

**Does not throw** — caller asserts on `result.failed` so adapter test
suites can produce per-fixture diagnostics rather than a single opaque
exception.

## Filter options

`only` / `skip` allow targeted runs during adapter development:

```ts
runAdapterConformanceSuite(myAdapter, { only: ['simple-chat'] });
runAdapterConformanceSuite(myAdapter, { skip: ['cancellation-propagates'] });
```

## Test coverage (97/97 pass, +6 new)

- SDK reference adapter (reducer + markdown render) passes all fixtures
- SDK reference adapter (reducer + plainText render) also passes
- Buggy adapter (empty string output) fails every fixture with non-empty
  `expectedContains`
- Buggy adapter (raw event dump via JSON.stringify) caught by redaction
  fixture's `expectedAbsent`
- `only` filter narrows to a single fixture
- `skip` filter excludes named fixtures from the corpus

## Usage from adapter authors

```ts
// In your adapter's test file
import { runAdapterConformanceSuite } from '@qwen-code/sdk/daemon';
import { reduceForTui, renderTuiState } from './my-tui-adapter';

it('TUI adapter conforms to daemon UI corpus', () => {
  const result = runAdapterConformanceSuite({
    reduce: reduceForTui,
    renderToText: renderTuiState,
  });
  expect(result.failed).toEqual([]);
});
```

## Roadmap

PR-G of the unified follow-up to PR #4328. The corpus is intentionally
small (10 fixtures) but extensible — adapter authors can submit new
fixtures via additions to `DAEMON_UI_CONFORMANCE_FIXTURES` to lock in
regression coverage for edge cases their adapter encountered.

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* feat(webui+sdk/daemon-ui): wire transcriptAdapter to SDK render contract (PR-H)

Closes the "WebUI transcriptAdapter migration" item in PR #4353's TODO §A.
Validates the PR-D render contract end-to-end on the real WebUI consumer.

`daemonTranscriptToUnifiedMessages(blocks, options?)` gains a new options
parameter:

```ts
interface DaemonTranscriptAdapterOptions {
  useMarkdown?: boolean;                  // default: false
  enrichToolDetailsWithPreview?: boolean; // default: false
}
```

Defaults preserve legacy behavior — existing callers see no change.

For `user` / `assistant` / `thought` blocks, content is projected via
SDK's `daemonBlockToMarkdown` instead of raw sanitized text. The WebUI's
markdown renderer (markdown-it) then gets:

- `**You**\n\n<content>` for user blocks (bold "You" label)
- Raw text for assistant blocks (markdown formatting in agent output
  passes through cleanly)
- `> *thought:* <text>` blockquote for thought blocks

For `tool` blocks, `rawOutput` is replaced with `daemonToolPreviewToMarkdown(block.preview)`.
This lets WebUI surfaces without per-preview-kind React components still
display:

- `file_diff` as a fenced unified diff
- `mcp_invocation` as `server::tool` with args summary
- `tabular` as GFM pipe table
- `search` as bullet list with match count
- `image_generation` as embedded markdown image
- `subagent_delegation` as delegate arrow + task quote

Renderers with per-kind components should leave this opt-out.

`packages/sdk-typescript/src/daemon/index.ts` was missing exports for
PR-D / PR-F / PR-G / PR-B / PR-E surface — WebUI's `@qwen-code/sdk/daemon`
import path uses the daemon root, not the ui/ sub-index. Added 15+
re-exports so consumers don't need to use the longer
`@qwen-code/sdk/daemon/ui/index.js` path.

Now exported from `@qwen-code/sdk/daemon` root:
- `daemonBlockToMarkdown` / `daemonBlockToHtml` / `daemonBlockToPlainText`
- `daemonToolPreviewToMarkdown`
- `extractContentPart` + `DaemonUiContentPart` type
- `formatBlockTimestamp` + `selectTranscriptBlocksOrderedByEventId`
- `selectCurrentTool` / `selectApprovalMode` / `selectToolProgress`
- `runAdapterConformanceSuite` + `DAEMON_UI_CONFORMANCE_FIXTURES`
- All associated types

`webui/src/daemon/transcriptAdapter.test.ts` mock blocks updated to include
`clientReceivedAt` (required field added in PR-B). Mechanical change —
every `createdAt: N` test fixture gets a matching `clientReceivedAt: N`.

- WebUI `npm run typecheck` — clean
- SDK `npm run typecheck` — clean
- SDK `vitest run test/unit/daemonUi.test.ts` — 97/97 pass
- WebUI transcriptAdapter test fixtures typecheck against updated
  DaemonTranscriptBlockBase schema

PR-H of the unified follow-up to PR #4328. Closes the WebUI migration
gap in TODO §A.

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* docs(daemon-ui): add developer guide + migration cookbook (PR-I)

Closes the final "Documentation" item in PR #4353's TODO §A. Brings the
unified daemon UI surface to ~95% SDK-side completion.

## Files added

- `docs/developers/daemon-ui/README.md` — full API reference
  - Three-layer model (normalizer → reducer → render helpers)
  - Quick start with idiomatic event-loop pattern
  - Event taxonomy (28+ types categorized: chat-stream / session-meta /
    workspace / auth device-flow)
  - Render contract cookbook (markdown / HTML / plainText)
  - Tool preview taxonomy (13 kinds with use cases)
  - State selectors (currentTool / approvalMode / toolProgress / ordering)
  - Cancellation propagation explanation
  - Time semantics (eventId > serverTimestamp > clientReceivedAt
    precedence)
  - Adapter conformance usage
  - ErrorKind dispatch pattern
  - Tool provenance dispatch pattern
  - Forward-compat principles

- `docs/developers/daemon-ui/MIGRATION.md` — adapter author migration
  cookbook
  - Step-by-step recommended adoption order (9 steps, value-ranked)
  - Before/after code examples for each step
  - Backward-compat checklist (everything is additive — no breaking
    changes)
  - Cross-references to PR-A through PR-H commits

## Roadmap

PR-I of the unified follow-up to PR #4328. Documentation-only — no
code changes; no tests affected.

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* fix(daemon-ui): address review feedback

* fix(daemon-ui): address review hardening feedback

* fix(daemon-ui): handle resync-required events

* feat(sdk/daemon-ui): consume daemon-side subagent nesting context (PR-K)

Closes the SDK-side gap for §B1 in PR #4353's TODO list. PR-E originally
deferred subagent nesting because daemon-side parent-context wasn't yet
stamped on tool_call events. After the rebase onto current
daemon_mode_b_main, source verification confirms the daemon now emits
`tool_call._meta.parentToolCallId` + `tool_call._meta.subagentType` via
`SubAgentTracker.getSubagentMeta()` (core), so the SDK side is unblocked.

## Schema additions (additive, forward-compat-safe)

`DaemonUiToolUpdateEvent`:
  - parentToolCallId?: string  — toolCallId of the parent Task / delegation
  - subagentType?: string      — sub-agent type label (e.g. 'code-reviewer')

`DaemonToolTranscriptBlock`:
  - parentToolCallId?: string  — mirror of event field
  - subagentType?: string      — mirror of event field
  - parentBlockId?: string     — pre-resolved by reducer when parent already
                                 in state, so renderers don't re-correlate

## Normalizer wiring

`normalizeToolUpdate` checks both top-level and `_meta` for parentToolCallId
+ subagentType (fallback chain mirrors how provenance/serverId are read).
Top-level tool calls without sub-agent context omit the fields cleanly.

## Reducer behavior

- New tool block: resolves `parentBlockId` from `toolBlockByCallId` at
  create time. Out-of-order arrival (child before parent) leaves
  `parentBlockId` undefined — selectors fall back to `parentToolCallId`
  lookup.
- Existing tool block update: adopts parent context if not yet
  correlated, never overwrites established correlation (handles the
  flow where SubAgentTracker activates after the initial tool_call).

## New public selectors

- selectSubagentChildBlocks(state, parentToolCallId): returns the
  array of tool blocks invoked inside a given parent delegation
- isSubagentChildBlock(block): type guard for "this tool block came
  from a sub-agent"

Both exported from @qwen-code/sdk/daemon root + ui/index.

## Forward-compat properties

- Top-level tool calls (no sub-agent) work identically as before
- Trimmed parent blocks: child fallback to undefined parentBlockId
- Daemon emits both fields together; SDK reads independently to tolerate
  partial future stamping

## Test coverage (129/129 pass, +5 new tests)

- Extract parentToolCallId + subagentType from `_meta`
- Top-level tool calls have undefined parent fields (forward-compat)
- Reducer correlates parentBlockId at create time
- Reducer adopts parent context on later update (out-of-order arrival)
- isSubagentChildBlock discriminator

## Roadmap

PR-K of the unified follow-up to PR #4353. Closes §B1 (subagent nesting)
in the TODO declaration; daemon-side already shipped on
`daemon_mode_b_main` via SubAgentTracker (core).

Remaining TODO §B / §D items still depend on further daemon/Core work:
- §B2 `tool.progress` event type (daemon emit pending)
- §D MessageEmitter multimodal echo + HistoryReplayer inlineData/fileData
  (core change pending)

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* fix(daemon-ui): PR-K self-review hardening — back-fill / trim / self-ref / docs

Multi-round self-review of PR-K (d8375fe46) surfaced two real bugs, a
few defensive gaps, and missing docs/fixture coverage. All addressed
in one commit.

## Bugs fixed

### Bug 1 — `parentBlockId` never back-filled for out-of-order arrival

Original PR-K resolved `parentBlockId` only at child create time, which
broke this flow:

  1. Child arrives WITH parent stamp → block created with
     `parentToolCallId` set, `parentBlockId` undefined (parent not in
     state yet)
  2. Parent arrives later → block created, `toolBlockByCallId` indexed
  3. Subsequent child updates: existing-block branch only ran the
     back-fill inside `!existing.parentToolCallId`, which is false (we
     already adopted the stamp in step 1). `parentBlockId` stayed
     undefined forever.

Fix: separate the two correlations.
  - existing-block update: independently back-fill `parentBlockId`
    whenever `parentToolCallId` is set and `parentBlockId` is missing
  - new-block create: scan existing children whose `parentToolCallId`
    matches the new block's `toolCallId` and back-fill their
    `parentBlockId`. Cheap O(n) over current blocks.

### Bug 2 — dangling `parentBlockId` after trim

`trimTranscriptState` reset `toolBlockByCallId[id]` to the trimmed
sentinel for evicted blocks but did NOT walk surviving children to
null their `parentBlockId` references. Renderers walking
`blockIndexById.get(parentBlockId)` would get undefined, with no
"why" signal.

Fix: post-trim, walk remaining tool blocks; if `parentBlockId`
references an id not in `keptIds`, null it. `parentToolCallId` stays
(survives trimming so selector-keyed queries still work).

## Defensive hardening

- **Self-reference guard** (normalizer): drop
  `parentToolCallId === toolCallId` before it reaches the reducer.
  Daemon should never emit this, but defending costs nothing.
- **Selector docstring**: clarify `selectSubagentChildBlocks` returns
  **direct** children only; document cycle / depth-cap responsibility
  for renderers walking up the chain.
- **Cosmetic**: remove redundant `as DaemonToolTranscriptBlock` cast
  in `isSubagentChildBlock` (TypeScript already narrows after
  `block.kind === 'tool'` on the discriminated union).
- **Alphabetical**: move `isSubagentChildBlock` re-export to correct
  position in both `daemon/index.ts` and `daemon/ui/index.ts`.

## Docs + conformance gaps closed

- `README.md` — new "Sub-agent nesting (PR-K)" section with full
  reducer behavior, out-of-order handling note, recursive walk example,
  cycle-defense note.
- `MIGRATION.md` — new step 8a with before/after for nested rendering.
- `conformance.ts` — new `subagent-nesting` fixture covering parent +
  nested child via `tool_call._meta`. Markdown-safe phrases chosen
  (markdown escapes `-` so titles cannot be substring-matched as-is).

## Test coverage (+5 tests, 134/134 pass)

- Self-reference dropped in normalizer
- Back-fill on out-of-order parent arrival (child first, parent after)
- Back-fill on later child update when parent now exists
- Dangling `parentBlockId` nulled after parent trimmed
- New `subagent-nesting` conformance fixture passes SDK reference adapter

## Side-effect verification

Verified no regressions:
- Cancellation propagation still cancels parent + children together
  (iterates `toolBlockByCallId`, which includes both)
- Render contract unchanged (`daemonBlockToMarkdown` etc. project per
  block, no nested awareness required)
- No serializer to update
- `selectTranscriptBlocksOrderedByEventId` unaffected (parent-agnostic)

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* fix(daemon-ui): permission block trim contract — wenshao review

Addresses both items from wenshao's review on PR #4353:

## Critical — resolvePermissionBlock missing TRIMMED guard

The sibling `upsertPermissionBlock` (transcript.ts:544) correctly returns
early when `existingId === TRIMMED_PERMISSION_BLOCK_ID`, but
`resolvePermissionBlock` (transcript.ts:581) had no such guard. When
`maxBlocks` trimming evicted a pending permission request, a subsequent
`permission.resolved` event would:

1. Fail the `getWritableBlockById` lookup (sentinel is not a real block id)
2. Fall through and create a brand-new orphan resolution block

This wasted a block slot, accelerated further trimming, and silently
broke the trimmed-block contract that the request-side guard establishes.

Fix: mirror the request-side guard. Read the index entry up front,
return early on the sentinel.

## Suggestion — permissionBlockByRequestId grows unboundedly

`trimTranscriptState` writes `TRIMMED_PERMISSION_BLOCK_ID` for evicted
permission requests but never deletes those entries. Unlike the tool
side (which calls `pruneTrimmedToolIndexes` post-trim), the permission
index grew without bound in long sessions.

Fix: add `pruneTrimmedPermissionIndexes` analogous to the tool-side
helper. Caps the sentinel set at `maxBlocks` entries; older entries are
deleted (any later resolution event still drops cleanly via the new
Critical guard).

## Tests

- Updated existing `keeps orphan permission resolutions visible after
  request trimming` test to encode the corrected contract (drops silently
  instead of creating an orphan). Test rename: "drops resolution for
  trimmed permission requests (wenshao Critical)".
- New `Suggestion: pruneTrimmedPermissionIndexes caps the trimmed
  sentinel set` test verifies the cap.

Total: 136/136 tests pass, SDK + WebUI typecheck green.

## Side-effect verification

- `upsertPermissionBlock` already had the equivalent guard — no
  asymmetry remains.
- `pruneTrimmedPermissionIndexes` only touches entries holding the
  sentinel; live permission blocks are unaffected.
- Selectors over `state.blocks` (e.g. `selectPendingPermissionBlocks`)
  iterate the block array, not the index — unaffected by cap.

Generated with AI

Co-authored-by: Claude Opus 4.7 <[email protected]>

* fix(daemon-ui): address wenshao + doudouOUC inline reviews (2026-05-23)

Addresses the 13 inline review comments from wenshao (6) and doudouOUC
(7, one overlap) on the 2026-05-23 review round.

## Critical / Important

### sanitizeUrls not threaded through HTML preview path (doudouOUC)

`daemonBlockToHtml` for tool blocks called `daemonToolPreviewToPlainText`
which didn't accept `opts` — when callers set `sanitizeUrls: true`, the
markdown path stripped auth tokens but the HTML path leaked them into
the DOM. Now: helper accepts opts, threads through `web_fetch.url` and
`image_generation.thumbnailUrl`.

### enrichToolDetailsWithPreview overwrote rawOutput (doudouOUC)

The webui adapter replaced structured `rawOutput` with a markdown
summary string when `enrichDetails: true`. Downstream `ToolCallData`
consumers may branch on the shape (object vs string) and break. Plus
the actual tool output was silently dropped.

Fix: keep `rawOutput` verbatim, surface markdown via a new optional
`previewMarkdown` field added to `ToolCallData`.

### transcriptBlockToTerminalText zero test coverage (wenshao)

Added 12 tests covering each `switch` branch (user / assistant / thought
/ tool / shell stdout+stderr / permission unresolved+resolved / status /
debug / error) plus the unknown-kind degradation path. Verified
`assertNever` returns a graceful error line (does NOT throw) — wenshao's
reviewer was slightly wrong on the throw claim but coverage gap was
real.

### selectTranscriptBlocksOrderedByEventId no memoization (wenshao)

Selector was called from React `useSyncExternalStore` and re-sorted on
every dispatch — including sidechannel-only events that don't touch
blocks. Added WeakMap cache keyed on `state.blocks` reference; the
reducer preserves the same array reference for non-block-mutating
events, so the cache hits across renders.

### selectSubagentChildBlocks O(n) per call (wenshao)

Naive `state.blocks.filter()` was O(n) per call; rendering a tree with
m parents made it O(n*m). Built a memoized reverse index keyed on
`state.blocks` reference (WeakMap of parentToolCallId →
DaemonToolTranscriptBlock[]). Each lookup now O(1) after first call.

### Test file TS errors at root tsc (wenshao)

Fixed multiple TS errors in `daemonUi.test.ts` flagged by root
`tsc --noEmit`:
- Added `DaemonTranscriptState` + `DaemonUiEvent` imports
- `block.content` access via `as Array<Record<string, unknown>>` cast
- `delete` on globalThis property via narrower interface cast
- `debug?.text` via `DaemonUiEvent & { text: string }` narrowing (Extract on
  union with `'status' | 'debug'` literal would resolve to never)
- 6 occurrences of index-signature access via bracket notation
- `raw: null` added to 3 `DaemonUiPermissionOption` literals (required field)
- Explicit type annotations on conformance-suite `renderToText` params

Note: `webui/src/daemon/transcriptAdapter.test.ts` shows residual
"clientReceivedAt does not exist" errors at root tsc, but this is
environmental — the resolution trace shows `@qwen-code/sdk/daemon`
crossing into a sibling worktree's stale dist via shared workspace
node_modules. In a single-worktree CI checkout this resolves cleanly.

## Suggestions (cleanups)

### Hoist asDaemonErrorKind double-eval (doudouOUC)

`session_died` + `stream_error` cases each computed `asDaemonErrorKind`
twice in the conditional spread (predicate + value). Hoisted to const,
no functional change.

### renderToolHeader bypassed opts (doudouOUC)

Forwarded `opts` so `maxFieldLength` is honored for tool title /
toolName / toolKind.

### isSensitiveKey duplicates (doudouOUC)

Removed duplicate `endsWith('accesskey')` / `endsWith('secretkey')`
checks and the redundant exact-match `privatekey` (already covered by
`endsWith`).

### propagateCancellationToInFlightTools iterated trimmed (wenshao)

Filter `TRIMMED_TOOL_BLOCK_ID` sentinels up front. Avoids redundant
index dereferences in long sessions with many historical tools.

### toolProgress shallow clone (doudouOUC + wenshao)

`cloneTranscriptState` outer `...state` spread shared inner
`{ ratio?, step? }` references between snapshots. Once `tool.progress`
event handlers start mutating in place, the prior snapshot would leak.
Deep-clone the inner records now (cost bounded by in-flight tools,
small).

### isDeviceFlowErrorKind closed set (wenshao + doudouOUC)

Both reviewers suggested strict validation. We INTENTIONALLY kept
lenient pass-through — the public type
`DaemonAuthDeviceFlowSdkErrorKind` explicitly includes `(string & {})`
as a forward-compat escape hatch (existing test `keeps future
auth_device_flow_failed errorKind values observable` enforces this).
Now expose `KNOWN_DEVICE_FLOW_ERROR_KINDS` as documentation and
explain the design in the JSDoc.

## Validation

| | |
|---|---|
| SDK tests | 148/148 pass (+12 terminal coverage + assorted hardening) |
| SDK typecheck | clean |
| WebUI typecheck | clean |

## Side-effect verification

- WeakMap memos invalidate correctly: reducer creates a fresh
  `state.blocks` reference only on block-mutating events. Sidec…
…mands (QwenLM#4085)

* feat(cli): add --quiet-restore flag to suppress history output on session resume

* fix: preserve history state for /rewind while suppressing rendering

* refactor: model quiet-restore as display policy with shared utilities

* refactor: replace --quiet-restore with /history collapse|expand slash command

* fix: persist history collapse state as user setting

* fix(cli): address maintainer feedback on history collapse persistence and i18n

* test(cli): fix TypeScript compilation errors in historyCommand tests

* fix(cli): address maintainer review feedback on history collapse

* test: fix act() warning in slashCommandProcessor.test.ts

* fix: make applyCollapsePolicyAndSummary pure to avoid React batching bug

* chore: revert unrelated changes to lockfile and NOTICES.txt

* test: verify isRealUserTurn handles suppressOnRestore items correctly

* wip(cli): preserve local history review fixes before redesign

* feat(cli): refine history resume collapse commands

* fix(cli): address maintainer review feedback on history collapse

* test(cli): cover cold-boot collapsed resume

* fix(cli): address reviewer feedback on history collapse

* fix(cli): resolve rebase conflicts and missing imports

* fix(cli): strip suppressOnRestore in handleRewindConfirm

* fix(i18n): add Chinese translations for history collapse commands

* fix: address wenshao review comments on PR QwenLM#4085

- Restore restoreGoalFromHistory call in cold-boot resume path
- Extract stripSuppressOnRestore to shared utility in resumeHistoryUtils
- Add comment explaining historyRef pattern in slashCommandProcessor
- Use historyCommand.name constant instead of string literal
- Add missing i18n translation for collapse summary message
- Fix pluralization in createHistoryCollapseSummaryItem

* fix(i18n): add missing English translations for history collapse commands

* fix: address wenshao follow-up review comments

- Filter out collapse-summary items in rewind path (AppContainer.tsx)
- Show info messages for collapse-on-resume/expand-on-resume commands (slashCommandProcessor.ts)
- Use visibleHistory instead of uiState.history in summaryByCallId useMemo (MainContent.tsx)
- Remove dead hasHistoryManager guard and optional chaining (useResumeCommand.ts)

* fix: restore optional chaining for remount in useResumeCommand

* test: update slashCommandProcessor tests for history command feedback changes

* chore: remove generated artifact files from branch

- Remove .learnings/LEARNINGS.md (local workflow artifact)
- Remove .pr-body.md (PR description draft)
- Remove build_output.log (build log)
- Remove vscode_test_output.log (test output log)

These files are unrelated to the history-collapse feature and were causing
git diff --check whitespace errors.

* fix: address wenshao review comments on PR QwenLM#4085

- Remove stray [!tip] file from repo root
- Add selfManaged flag to MessageActionReturn for explicit UI feedback control
- Fix expand-now to return load_history type instead of calling loadHistory directly
- Replace hardcoded isSelfManaged path check with result.selfManaged in processor
- Fix MainContent merge detection to use visibleHistory.length (avoid flicker)
- Refactor applyCollapsePolicyAndSummary to not mutate input array
- Extract expandCollapsedHistory shared helper
- Restore dialog:memory test in slashCommandProcessor.test.ts
- Add stripSuppressOnRestore dedicated tests
- Add visibleHistory filtering test in MainContent.test.tsx
- Update historyCommand tests for new load_history return type
- Fix eslint errors: remove unused imports and fix dependency array

* fix: address wenshao review comments on PR QwenLM#4085

- Remove stray [!tip] file from repo root
- Add selfManaged flag to MessageActionReturn for explicit UI feedback control
- Fix expand-now to return load_history type instead of calling loadHistory directly
- Replace hardcoded isSelfManaged path check with result.selfManaged in processor
- Fix MainContent merge detection to use visibleHistory.length (avoid flicker)
- Refactor applyCollapsePolicyAndSummary to not mutate input array
- Extract expandCollapsedHistory shared helper
- Restore dialog:memory test in slashCommandProcessor.test.ts
- Add stripSuppressOnRestore dedicated tests
- Add visibleHistory filtering test in MainContent.test.tsx
- Update historyCommand tests for new load_history return type
- Fix eslint errors: remove unused imports and fix dependency array
- Fix TypeScript errors: add useEffect import, fix display.kind type assertions

* fix: add braces around if statement body (eslint curly rule)

Fixes lint error in editorGroupUtils.ts:
- Expected { after 'if' condition on line 32

* fix: address wenshao follow-up review comments on PR QwenLM#4085

- Revert expand-now to use loadHistory/refreshStatic directly (no load_history return)
- Remove dead selfManaged flag from MessageActionReturn and processor
- Fix visibleHistory filter to also exclude collapse-summary items
- Simplify applyCollapsePolicyAndSummary (return rawItems when !collapseOnResume)
- Fix test assertion shapes (content→text, timestamp as separate arg)
- Add mockClient for expand-now test
- Update historyCommand tests for new behavior
- Add expandCollapsedHistory dedicated tests
- Fix MainContent filtering test to use historyItemDisplayPropsSpy

* fix: address wenshao latest review comments on PR QwenLM#4085

- Fix visibleHistory filter: remove collapse-summary exclusion (summary should render when all items suppressed)
- Update MainContent test: assert summary item IS rendered alongside unsuppressed items
- Remove dead selfManaged flag from MessageActionReturn type
- Remove dead selfManaged check from slashCommandProcessor.ts
- Add remount?.() to useResumeCommand error path
- Remove unused 'History expanded.' translation key from en.js, zh.js, zh-TW.js
- Fix expand-now test: mock action to return undefined (matching real behavior)

* fix: address wenshao latest review comments on PR QwenLM#4085

- Add missing i18n translations to ca.js, de.js, fr.js, ja.js, pt.js, ru.js
- Simplify applyResumeDisplayPolicy: remove dead options parameter
- Fix expand-now test: mock action to return undefined (matches real behavior)
- Revert unrelated changes to package-lock.json and editorGroupUtils.ts

* fix: address wenshao latest review comments

- Add openDiffDialog to createMockActions() in slashCommandProcessor.test.ts
- Add sentToModel: false to user message assertions in slashCommandProcessor.test.ts
- Fix useResumeCommand.test.ts mock: spread original @qwen-code/qwen-code-core exports to include createDebugLogger
- Remove dead optional chaining (addItem?., clearItems?., loadHistory?.) in useResumeCommand.ts
- Simplify if (!config || !startNewSession) to if (!config) since startNewSession is required
- Fix truncatedCount off-by-one in AppContainer.tsx rewind path: exclude collapse-summary from effective length
- Apply collapse policy (applyCollapsePolicyAndSummary) in useBranchCommand.ts for /branch
- Add settings to UseBranchCommandOptions with proper useCallback dependency

* fix: add missing mockUpdateItem arg to test renderHook calls, remove stray file

- Add mockUpdateItem (17th arg) to resume-direct and memory dialog test calls
- Remove accidentally committed packages/core/.qwen/computer-use/installed.json
- Add .qwen/computer-use/installed.json to .gitignore

* fix: address review comments (type, gitignore, test, split-brain)

1. UIActionsContext: handleResume return type → Promise<void>
2. .gitignore: split corrupted merged line into .codegraph + .qwen/...
3. useBranchCommand.test: add settings to makeOptions(), add collapseOnResume test
4. useResumeCommand: reorder core-before-UI with rollback (matches branch pattern)
5. useResumeCommand.test: add getSessionId to mocks, add rollback test

* fix: complete history collapse translations in 6 locale files

- Added missing translation text for 'History collapsed' message
- Fixed syntax errors in de, fr, ja, pt, ru, zh-TW locale files

* fix: add missing history parameter in slashCommandProcessor test

- Fixed parameter order in 'should skip reload when consumeSlashReloadSuppression' test
- Added missing empty array for history parameter
- All 58 tests now pass

* merge: resolve conflicts with upstream main

- docs: keep ui.history.collapseOnResume setting, adopt upstream showCitations default
- fix: update rewindRecording call to include file history snapshots parameter

* fix(cli): repair history collapse CI failures

---------

Co-authored-by: qqqys <[email protected]>
* fix(cli): narrow context import format schema

* fix(cli): narrow dns resolution schema

* docs: keep settings type column consistent
* fix(core): block broad shell self-kill commands

* fix(core): harden self-kill command detection
* fix(cli): preserve trustedFolders comments on save

* fix(cli): fall back to clean trustedFolders writes

* test(cli): fix trustedFolders validation-failure coverage

* test(cli): exercise trustedFolders validation parse path

* fix(cli): guard trustedFolders fallback inputs

* fix(cli): guard trustedFolders fallback inputs

* fix(cli): harden trustedFolders fallback validation

* fix(cli): harden trustedFolders fallback validation

* test(cli): cover null trustedFolders fallback

* fix(cli): sync trustedFolders entries on save

* test(cli): expect stale trustedFolders entries to be removed

---------

Co-authored-by: Shaojin Wen <[email protected]>
…5430)

* fix(core): provide escape path when plan gate is unavailable

When runPlanApprovalGate returns { kind: 'unavailable' } after exhausting
retries (e.g. review model timed out, invalid JSON output), exitPlanMode
previously returned a rejected display that left the model stuck in plan
mode with no mechanism to exit.

Fix: fall back to user confirmation instead of trapping in plan mode.
The new fallbackToUserConfirmation() method restores the pre-plan approval
mode, saves the plan to disk, and returns a plan_summary (not rejected)
so the model can proceed.

Related:
- Issue QwenLM#5427 — Plan Approval Gate: unavailable after retries leaves user
  stuck in plan mode with no escape path
- Issue QwenLM#5210 — 0.18.1-ExitPlanMode卡住 (same symptom, closed due to
  missing reproduction info)

Signed-off-by: Alex <[email protected]>

* refactor(core): rename fallbackToUserConfirmation to fallbackToAutoExecute

Rename the method and update messages to accurately reflect behavior:
in AUTO/YOLO mode there is no user confirmation dialog — the system
falls back to pre-plan mode (auto-execute). Also remove the now-unused
formatUnavailableResponse export from planApprovalGate.ts.

Suggested-by: wenshao
Signed-off-by: Alex <[email protected]>

* fix(core): guide model to ask user when gate is unavailable

Update the unavailable fallback llmContent and messages to explicitly
instruct the model to ask the user whether to execute the plan, rather
than implying auto-execution. This ensures the user retains control
when the gate review agent fails.

Also update the test name and assertions to match the new behavior.

Suggested-by: wenshao
Signed-off-by: Alex <[email protected]>

* fix(core): switch to DEFAULT mode on gate unavailable to force confirmation

Instead of restoring AUTO/YOLO (which could let the model auto-execute
without user input), switch to DEFAULT mode so the next action triggers
a real user confirmation dialog. Rename the helper from
fallbackToAutoExecute to fallbackToUserDecision to match intent.

This ensures the user retains full control when the gate fails, rather
than being silently downgraded to auto-execute.

Suggested-by: claude-opus-4-8 via Qwen Code /review
Signed-off-by: Alex <[email protected]>

---------

Signed-off-by: Alex <[email protected]>
…d / Discover / Sources) (QwenLM#4850)

* feat(extensions): multi-tab /extensions dialog (Discover/Installed/Marketplaces)

Upgrade the /extensions management dialog from a linear wizard into a
multi-tab interactive dialog aligned with Claude Code's /plugin command.

UI (packages/cli):
- Discover: pull installable plugins from configured marketplaces,
  multi-select (Space), batch install (i) with Global/Project/Local scope,
  open homepage, per-plugin details.
- Installed: plugins + standalone MCP servers grouped by
  Favorites/Local/User/Project/Disabled; Space toggles enable/disable,
  f toggles favorite, Enter opens details with an action menu
  (toggle/favorite/mark-for-update/update/uninstall).
- Marketplaces: add/list/view/remove marketplace sources
  (owner/repo, SSH, HTTP JSON, local path).
- Tabbed shell with Tab/arrow switching and a focus-lock contract so a tab
  owns Escape while in a sub-view.

Core (packages/core):
- ExtensionPreferencesStore: favorites + per-extension scope intent.
- MarketplaceRegistryStore + discoverPlugins(): persistent marketplace
  source registry and cross-source discovery.
- loadMarketplaceConfigFromSource() in marketplace.ts (GitHub/local/HTTP-JSON).
- ExtensionManager methods for marketplaces, discovery, favorites and scopes;
  preference cleanup on uninstall.

Scope mapping: Global -> User; Project/Local -> workspace-scoped enablement
(install then re-scope so the choice actually restricts where it is active).

The Errors tab is intentionally deferred per the spec.

Tests: 19 core unit tests (preferences/registry/discovery) and 11 tabbed
dialog integration tests; existing extension suites updated. typecheck,
lint and i18n checks pass.

* feat(extensions): align Discover plugin detail with Claude Code

Rework the Discover tab's Enter detail view to match Claude Code's
"Plugin details" page in both layout and interaction:

- Layout: "Plugin details" header, title, "from <marketplace>", last
  updated / version, description, "By: <author>", a "Will install:"
  component summary (Skills/Commands/Agents/MCP servers), and a trust
  warning.
- Interaction: the scope choice is now an inline action selector on the
  detail page (Install for you / for all collaborators / in this repo
  only / Open homepage / Back to plugin list), selected with Enter —
  replacing the previous i/h shortcuts and the separate scope step.
- Footer shows "Enter to select · Esc to go back" while a tab sub-view
  is open.

Core: DiscoveredPlugin now carries declared `components` and a
best-effort `lastUpdated`, surfaced by discoverPlugins().

Adds a core test for component/lastUpdated extraction and a UI test for
the detail layout + inline selector.

* feat(extensions): align Add Marketplace view with Claude Code

Match CC's "Add Marketplace" screen: a bold "Add Marketplace" header,
an "Enter marketplace source:" prompt, and an "Examples:" bullet list
(owner/repo · git@…:owner/repo.git (SSH) · https://…/marketplace.json ·
./path/to/marketplace) above a bare cursor input (placeholder removed).

Update the Marketplaces add-view tests accordingly.

* feat(extensions): fix Discover hang + add search/scrolling, align list with CC

Discover reliability and UX fixes:

- Fix the "Discovering plugins…" hang: marketplace network fetches had no
  timeout, so a slow/unreachable source could block discovery forever. Add a
  10s per-request timeout (resolve null) plus socket drain on non-200.
- Cache the fetched listing in ExtensionManager for the session so revisiting
  the tab no longer refetches over the network; `installed` flags are
  recomputed cheaply, and the cache is invalidated on add/remove marketplace.

CC-aligned Discover list:

- Windowed/scrolling viewport (no longer renders the entire 200+ list at
  once) with "↑ more above" / "↓ more below" hints, sized to the terminal.
- Type-to-search filter with a search box and a "Discover plugins (pos/total)"
  count header.
- Item layout: cursor "›", ○/●/✓ checkbox, bold title · marketplace ·
  "<N> installs", with a truncated description line.
- Space toggles selection, Enter views detail (or installs the selected set);
  the conflicting "i" shortcut was removed in favor of search.

Core: DiscoveredPlugin gains a best-effort `installs` count.

Adds tests for windowing, search filtering, and install-count extraction.

* feat(extensions): align marketplace detail with CC + Browse-to-Discover

Rework the Marketplaces tab detail to match Claude Code:

- Show marketplace name, source, "N available plugins", and the plugins
  from this marketplace that are installed ("Installed plugins (K):" with
  descriptions) — instead of dumping a truncated list of all plugins.
- Replace the ad-hoc "d to remove" hint with an action selector:
  Browse plugins (N) · Update marketplace [(last updated DATE)] ·
  Remove marketplace.
- "Browse plugins" switches to the Discover tab filtered to this
  marketplace (only its plugins); the filter clears on manual tab switch
  and is shown in the Discover header.
- "Update marketplace" re-fetches the marketplace config, stamps a fresh
  "last updated", and invalidates the discovery cache.

Core: MarketplaceSource gains lastUpdatedAt; addMarketplace stamps it and
ExtensionManager.markMarketplaceUpdated() refreshes it + clears the
discovery cache.

Adds tests for the marketplace detail layout and the Browse-to-Discover
filtering flow.

* feat(extensions): show plugin type in Installed; guide single-extension adds

- Installed list: plugin rows now show their type + version ("Extension
  v0.7.0"), parallel to MCP rows ("MCP"), instead of a bare version.
- Add Marketplace: when the source is not a Claude marketplace but is a
  valid single extension source (Gemini/Claude/git/npm), the error now
  guides the user to install it directly ("... looks like a single
  extension, not a marketplace. Install it with: /extensions install X")
  instead of the generic "expected marketplace.json" message.

* fix(extensions): resolve git@ SSH marketplace sources

The Marketplaces add flow advertises [email protected]:owner/repo.git (SSH)
as a supported format, but loadMarketplaceConfigFromSource relied on
parseGitHubRepoForReleases, which rejects the git@ scp-like form. Extract
owner/repo directly from the [email protected]:owner/repo(.git) form before
falling back to the URL parser, so SSH marketplace sources actually
resolve. Adds a regression test.

* feat(extensions): cap Discover list window at 6 items

* feat(extensions): unify 'Extension' wording, reorder tabs, expand Marketplaces tab

- Terminology: use 'Extension' instead of 'Plugin' across the dialog
  (Discover extensions, Extension details, Back to extension list, etc.).
- Tabs reordered to Installed, Discover, Marketplaces; the dialog now
  opens on Installed by default.
- Marketplaces tab is now a sources hub:
  - new 'Install new extension' action (installs a single Gemini/Qwen/
    Claude/git/npm extension directly via parseInstallSource).
  - 'Add new marketplace' annotated as a Claude plugin marketplace.
  - items grouped into 'Extensions' and 'Marketplaces' sections; an
    extension row opens a compact detail with Uninstall.

Updates the dialog tests for the new wording, tab order and layout.

* feat(extensions): update Marketplaces tab footer hint

* feat(extensions): full extension actions in both tabs + context-aware Marketplaces footer

- Add a shared ExtensionActionsView (info + components + action menu +
  scope-select + uninstall-confirm) used by both the Installed and
  Marketplaces tabs, so the Marketplaces extension detail now offers the
  full set (Enable/Disable, Favorite, Mark for Update, Update Now,
  Uninstall) instead of just Uninstall/Back.
- Add a new 'Change scope' action (Global/Project/Local) that re-scopes
  enablement (User vs workspace), available in both tabs.
- Context-aware Marketplaces footer: shows 'Enter details' for an
  extension row, 'Enter open · d remove marketplace' for a marketplace
  row, and a neutral hint for the action rows — no longer says
  'd remove marketplace' when an extension is selected.

Adds a test for the full extension actions in the Marketplaces detail.

* feat(extensions): rename Marketplaces tab to Sources, hide Favorites + fix enable/disable in Sources detail

- Rename the user-visible tab label 'Marketplaces' -> 'Sources' (TabBar +
  TABS). The in-tab 'Marketplaces' section header (grouping marketplace
  sources) is kept. Also update the Discover empty-state hint to point at
  the 'Sources' tab.
- Hide the Add/Remove Favorites action in the Sources extension detail via
  a showFavorite prop (default true; Installed keeps it).
- Fix a stale enable/disable label in the Sources extension detail:
  ExtensionActionsView re-read enablement through the manager cache keyed by
  a tick, but refreshCache() briefly empties that cache, so the read raced
  and fell back to the stale extension prop (isActive: true). It now holds
  authoritative local state (enabled/isFavorite/scope) updated optimistically
  after each action — no cache read-back. The Installed tab was immune only
  because it fed a fresh extension object each load.

Adds regression tests for the enable/disable toggle staying in sync and for
change-scope re-scoping + re-enabling a disabled extension.

* feat(extensions): group Sources action rows + show current scope in selector

- Add an 'Add new' section heading above the '+ Install new extension' and
  '+ Add new marketplace' rows on the Sources tab, so those two actions are
  grouped like the Extensions and Marketplaces sections.
- In the Change scope selector, default the cursor to the extension's current
  scope and show a 'Current: <scope>' line. Previously it always defaulted to
  Global, so after changing scope it was unclear whether the change took
  effect. Applies to both the Sources and Installed extension detail (shared
  ExtensionActionsView).

Updates tests to assert the 'Add new' section title renders and that
re-entering the scope selector reflects the now-current scope.

* fix(extensions): move uninstall note to confirm step; complete zh/zh-TW i18n

- Move the 'Note: Uninstall permanently removes this extension.' warning out
  of the detail-view action list and into the uninstall confirmation step
  (replacing the near-synonymous 'This action cannot be undone.').
- Fix the Chinese/English mix in the extensions manager: the new multi-tab UI
  added ~104 English strings that had no locale entries, so they fell back to
  the English key at runtime. Add Simplified (zh) and Traditional (zh-TW)
  translations for all of them, plus the matching en.js base keys (en.js is
  the canonical superset; zh/zh-TW require strict key parity per check-i18n).

Placeholders, keyboard tokens (Tab/Enter/Esc/Space/↑↓/·) and the ⚠ glyph are
preserved across all locales.

* feat(extensions): label Installed scope groups as 用户级/项目级/本地级

Rename the Installed-tab scope group headers from User/Project/Local to
'X level' (用户级/项目级/本地级) so the grouping reads as scope levels.
Adds the new keys to en/zh/zh-TW locales.

* feat(extensions): reuse /mcp server detail for installed MCP servers

The Installed-tab MCP item detail was a read-only view (name/type/scope/
transport/status) with a meaningless 'Enter to select' and no actions. Replace
it with McpServerActionsView, which reuses the /mcp dialog's ServerDetailStep,
ToolListStep, ToolDetailStep and AuthenticateStep so the behaviour matches
/mcp exactly: live connection status, View tools, Enable/Disable, Reconnect
(when disconnected), Re-authenticate and Clear authentication.

Handlers mirror MCPManagementDialog (mcp.excluded settings + toolRegistry
discover/disable/disconnect + MCPOAuthTokenStorage). Delete the now-unused
McpDetailView and its obsolete locale keys; add the two new status strings to
en/zh/zh-TW.

* fix(extensions): populate MCP promptCount from prompt registry

Review follow-up: buildServer hardcoded promptCount to 0, diverging from
/mcp's fetchServerData. Query the prompt registry like the original so the
reused MCPServerDisplayInfo is computed consistently.

* refactor(extensions): rename the source-management layer from marketplace to source

The Sources tab treats both single-extension sources and Claude plugin
marketplaces as 'sources', so the source-management layer is renamed for
consistency:
  MarketplaceSource        -> ExtensionSource
  marketplaceRegistry(.ts) -> sourceRegistry(.ts)
  MarketplaceRegistryStore -> SourceRegistryStore
  add/get/remove/markMarketplaceUpdated -> add/get/remove/markSourceUpdated
  loadMarketplace/updateMarketplace     -> loadSource/updateSource
  MarketplacesTab -> SourcesTab; EXTENSIONS_TABS.MARKETPLACES -> SOURCES
  + the source-detail UI handlers.

Terms that refer to the Claude marketplace manifest *format* are kept, since a
marketplace is one source type: ClaudeMarketplaceConfig,
loadMarketplaceConfigFromSource, the .claude-plugin/marketplace.json path,
DiscoveredPlugin.marketplaceName, and the in-tab 'Marketplaces' group label.

* fix(extensions): keep marketplaces.json filename so saved sources survive the rename

The source/* rename accidentally renamed the persisted registry file from
marketplaces.json to sources.json, so previously added sources (e.g. a Claude
marketplace) appeared to vanish — the data was intact in marketplaces.json but
the code read sources.json. Restore the marketplaces.json filename for
backward compatibility.

* fix(extensions): stay on the Discover detail when an install fails

Previously runInstall always returned to the list after attempting an install.
Now it only returns to the list on success; on failure it stays on the
extension detail page so the error message remains visible and the user can
retry without re-navigating.

* feat(extensions): support 'git-subdir' plugin source in Claude marketplaces

Some Claude marketplace plugins live in a subdirectory of a git repo and use a
'git-subdir' source ({url, path, ref, sha}), which resolvePluginSource didn't
handle — installing failed with 'Unsupported plugin source type'. Add the
git-subdir branch: clone the repo (pinned to ref/sha when provided) and return
the subdirectory as the plugin source.

Verified against github.com/42Crunch-AI/claude-plugins @ v1.5.5: the cloned
plugins/api-security-testing subdir is a valid plugin (.claude-plugin/plugin.json).

* feat(extensions): drop the unused 'local' install scope

Simplify the install/visibility scope model from three options (user /
project / local) down to two (user / project). The 'local' option duplicated
the workspace-level enablement of 'project' without providing a meaningfully
different storage location, so it was UI clutter rather than a real feature.

- core: ExtensionScope = 'user' | 'project'; read() filters unknown values
  via a type guard, so any stale 'local' (or otherwise invalid) entry in
  extension-preferences.json is dropped and falls back to 'user' downstream.
- UI: remove the 'local' option from the Discover install menu, the change-
  scope picker, and the Installed tab's group ordering.
- copy: rename 'Project (All Collaborators)' to 'Project (Workspace)' and
  'Install for all collaborators on this repository' to 'Install for the
  current workspace', matching the new two-tier model.
- i18n: clean up the now-unused 'Local *' keys in en / zh / zh-TW and
  retranslate the renamed keys.
- tests: update the scope-change spec and replace the legacy-scope
  migration test with one that exercises the unknown-value filter.

* feat(extensions): add Ctrl+R shortcut to refresh Discover tab

Press Ctrl+R in the Extensions Manager Discover tab to bypass the discover cache and re-fetch all marketplace sources. The refresh hint is merged into the dialog footer, and a success status is shown after the refresh completes.

* fix(extensions): keep j/k typeable in Discover search

The Discover tab list reused the global SELECTION_UP/DOWN matchers,
which include bare j/k as Vim-style navigation. Combined with
type-to-search input, that made it impossible to type j or k into the
search query.

Switch the Discover list navigation to explicit arrow keys plus
Ctrl+P/Ctrl+N, so bare j/k fall through to the printable-character
branch and append to the query. Other extension tabs (Installed,
Sources) remain pure lists and keep the Vim navigation.

* feat(extensions): install standalone Claude Code plugins from a git URL

A repo whose root holds .claude-plugin/plugin.json (no marketplace.json) is
a standalone Claude plugin. Previously installing one by git URL failed with
"Configuration file not found" because the converter only handled gemini
extensions and marketplace-based Claude plugins.

Add convertClaudePluginStandalone: read plugin.json, fold MCP servers from a
root .mcp.json into the config, collect skills/commands/agents, and write
qwen-extension.json. The marketplace path is refactored to share the build
step. MCP entries are normalized from Claude's transport shape (type:'http' +
url) to Qwen's (httpUrl), and the cloned .git is dropped from the result.

Note: cloneFromGit does not init git submodules, so submodule-provided skills are not installed yet.

* i18n(zh): relabel user-scope install as 全局安装

The Discover detail's user-scope install option now reads 全局安装(用户作用域) instead of 仅为你安装(用户作用域), which better conveys that user scope installs the extension globally.

* fix(extensions): keep the manager mounted during install consent prompts

Consent, setting-input and plugin-choice requests raised by an install
used to replace the ExtensionsManagerDialog in DialogManager, unmounting
it mid-install: the dialog remounted on the default Installed tab with
pre-install data, and the completion reload signal hit the dead
instance. Render those prompts inside the dialog instead (tab content
hidden but mounted), and gate the previously always-active key handlers
(MCP detail steps, uninstall confirm) so hidden views can't double-handle
keys while a prompt is shown.

* feat(extensions): show loading feedback for scope change and toggles

Changing an extension's scope now swaps the selector for a
"Changing scope..." line (Esc ignored while in flight), and the
Installed tab's Space toggle reports "Enabling/Disabling ..." in the
status line right away — MCP enable rediscovers tools and can take a
while. Overlapping toggle/favorite presses are ignored until the
in-flight mutation finishes.

* feat(extensions): add --scope to install and a sources CLI command group

Bring the qwen extensions CLI up to par with /extensions manage:
install --scope user|project (workspace accepted as an alias) records
the scope preference and, for project, re-scopes enablement to the
current workspace only — mirroring the Discover tab's install flow.
New sources add/list/update/remove subcommands manage the Claude
marketplace sources that power the Discover tab.

* feat(extensions): trim the Sources tab and add marketplace detail retry/refresh

Drop the redundant installed-extensions list from the Sources tab (those
live on the Installed tab); the marketplace detail still summarizes which
of its plugins are installed, now capped with a "… and N more" line so a
long list stays short. Add an R key in the marketplace detail that
re-fetches the source — surfaced in the footer as a retry on load
failure and a refresh once loaded. Reword the install row to "Install a
new extension".

* feat(extensions): nest extension-bundled MCP servers under their extension

The Installed tab now lists each extension's bundled MCP servers as
indented child rows beneath it, with Enter opening the shared MCP detail
view (tools, OAuth authenticate/clear) just like the /mcp panel.

- Skip child rows shadowed by a same-named user/project server and ones
  blocked by the MCP allow-list, matching the runtime merge semantics.
- Space only blocks the disable direction for bundled servers; an
  individually-excluded server under an active extension can be
  re-enabled. Blocked Space/favorite and Enter on a disabled extension's
  server give info feedback instead of failing silently.
- Hide the always-failing Disable action for active extension-provided
  servers in ServerDetailStep (also fixes the /mcp panel).
- Window the Installed list to the terminal height with scroll hints,
  clamped offset and group-header anchoring.
- Fall back to the list if the open detail's item disappears on reload
  so the tab can't get stuck locked.
- Hermetic tests: stub loadSettings, stabilize two flaky assertions.

* feat(extensions): per-server disable for extension MCPs and live status

Extension-bundled MCP servers can now be disabled individually, aligned
with Claude Code. The record lives in extension-preferences.json keyed
by extension name (not the global mcp.excluded list), so it never
affects same-named servers from other sources, survives restarts via
config.isMcpServerDisabled, and is cleaned up on uninstall.

- All three surfaces support the toggle: Installed tab Space, the
  extensions MCP detail view, and the /mcp panel; ServerDetailStep
  offers Disable for extension servers again.
- Installed tab MCP rows now show the live connection state (connected
  / needs authentication / connecting / disconnected) instead of a bare
  enabled flag; selected rows highlight the badge and status text too.
- "Needs authentication" (401 marker or declared OAuth with no stored
  token) renders consistently in the /mcp list and both detail views;
  a successful connect clears the sticky 401 marker in core.
- All three surfaces subscribe to MCP status changes for live updates,
  with statuses re-stamped synchronously before setState to close the
  load/listener race.
- Perf: extension preferences are cached by mtime, and the disabled
  predicate finds the owning extension without rebuilding the merged
  server map.

* docs(extensions): document interactive manager and backfill missing i18n

Add a 'The interactive extension manager' section covering the
Discover/Installed/Sources tabs, per-server MCP enable/disable, and
keybindings.

Backfill en/zh/zh-TW entries for six previously-untranslated strings
referenced via t() (npm install flags, the install command description,
'Description', and 'Delete Session') so they render localized instead of
falling back to English.

* fix(extensions): harden untrusted-marketplace handling from PR review

Address review findings on the new marketplace/plugin attack surface:

Security
- Strip ANSI/control sequences from marketplace-sourced display strings
  (Discover + Sources) so a hostile source can't manipulate the terminal
  before install consent.
- Confine git-subdir source.path to the cloned repo (reject absolute/.. /empty)
  to stop path traversal; prefer the immutable SHA pin over a named ref.
- Refuse absolute/relative local-path plugin sources from remote marketplaces.
- Reject absolute/escaping mcpServers and hooks file paths in plugin.json so
  the converter can't read arbitrary out-of-tree files.
- Only follow http(s) plugin homepages (block file:// etc. via open()).
- Cap marketplace HTTP response bodies and add a wall-clock fetch deadline
  (req.setTimeout is socket-idle only) to prevent OOM / indefinite hangs.

Correctness / robustness
- A post-install scope/enablement failure no longer marks the install failed.
- .mcp.json without an mcpServers object is skipped instead of misparsed.
- Guard Ctrl+R refresh against concurrent in-flight discovery.
- Log (not swallow) OAuth token-store lookup failures.
- InstalledTab: single-pass tool-count map (drop N+1 getAllTools) and O(1)
  row index lookup (drop per-row items.indexOf).

Tests
- Make the .git-stripping assertion meaningful and cover the absolute-path
  mcpServers guard and the .mcp.json fallback.

* fix(extensions): consent layout, per-extension update check, uninstall progress

- ConsentPrompt: render the markdown prompt in a column. The inner Box
  defaulted to flexDirection=row, so a multi-paragraph consent (e.g. an
  extension bundling several MCP servers) tiled its blocks into narrow
  vertical columns. It now stacks vertically.
- "Mark for Update" now checks only the selected extension via
  checkForExtensionUpdate (previously ran the full checkForAllExtensionUpdates
  with a discarded result), stores the result, and reports "update available"
  vs "already up to date" so the "Update Now" action shows up immediately.
- Uninstall: show an "Uninstalling ..." line while removal runs so the confirm
  prompt no longer looks frozen after Enter.
- i18n (en/zh/zh-TW): add the new strings; drop the now-unused
  "Checked ... for updates." key.

* feat(extensions): clearer update-check feedback for "Mark for Update"

Distinguish the four check outcomes instead of collapsing everything to
"up to date": update-available, up-to-date, not-updatable, and error.
For not-updatable Claude marketplace plugins, spell out the reason and
workaround (they are install-time conversions with no git remote, so they
update by reinstalling). Also show a "Checking ... for updates..." line
first, since git/github-release/npm checks hit the network.

* fix(extensions): confine resource/source paths, sanitize homepage (review round 2)

- claude-converter: route commands/skills/agents resource paths (collectResources)
  and the relative string plugin-source through path-confinement — reject
  absolute / ..-escaping values — matching the existing mcpServers/hooks guard.
- sourceRegistry: sanitize plugin.homepage like the other untrusted marketplace
  display fields (it otherwise reaches status toasts unsanitized).
- InstalledTab: construct MCPOAuthTokenStorage once instead of once per server.

* fix(extensions): confine symlink targets when converting untrusted plugins

A plugin source from an untrusted marketplace/git repo can embed a
symlink whose name stays inside the package but whose target points at a
host file (e.g. skills/leak.txt -> ~/.ssh/id_rsa). The path-confinement
checks were purely lexical (path.resolve), while the downstream
copy/read calls follow symlinks, so the target's content could be
shipped into the installed extension.

- copyDirectory: pin the package real-path root and skip symlinks whose
  resolved target escapes it (this is the bulk-copy vector at
  buildQwenExtensionFromPlugin).
- resolvePluginRelativeFile: re-verify the real path with realpathSync
  after the lexical check (covers mcpServers/hooks/single-file resources).
- collectResources: skip symlinked files in a collected folder whose
  target escapes the resource dir.
- resolvePluginSource: reject a string source that resolves outside the
  marketplace dir through a symlink.

Adds regression tests for the bulk-copy and collected-folder paths.

* fix(extensions): confine manifest reads, share path-containment helpers

Follow-up to the symlink confinement work (review round 3):

- Guard the three manifest reads that bypassed the new checks: a hostile
  clone could make marketplace.json / plugin.json / .mcp.json themselves
  symlinks to JSON-shaped host files (e.g. ~/.docker/config.json), whose
  content was parsed into the merged config. Each read now verifies the
  real path stays inside the package before reading; .mcp.json is treated
  as absent, plugin.json/marketplace.json throw.
- Hoist the containment logic into gemini-converter as exported
  isPathWithin (lexical) + realPathWithin (symlink-resolved) so the rule
  lives in one place instead of being duplicated across both converters.
- Document copyDirectory's confineRoot parameter in its JSDoc.

Adds targeted tests for the resolvePluginRelativeFile and
resolvePluginSource symlink-rejection branches and the plugin.json
manifest guard.

* fix(extensions): cap manager dialog width to the main content area

On a wide terminal the /extensions manager clipped its right-aligned
status column to a sliver (e.g. "扩…"). Root cause: the dialog sized
itself to boxWidth = columns - 4 with no cap, while the app's main
content area is capped at 100 columns (AppContainer's mainAreaWidth).
Past ~104 columns the dialog grew wider than its container and the right
edge — including the status column flexGrow pushes to the far right — was
clipped off-screen. Narrow terminals were unaffected because columns - 4
stayed within the cap.

Cap boxWidth at Math.min(columns - 4, 100) to match the main content
area, mirroring the existing DiffDialog idiom.

Adds a wide-terminal regression test that renders through a 200-column
stdout and asserts no line exceeds the content area (the uncapped dialog
produced ~196-col lines).

* fix(diff): cap /diff dialog width to the main content area

Same wide-terminal clipping as the extensions manager: DiffDialog sized
itself to Math.min(columns - 4, 110), but the app's main content area is
capped at 100 cols (AppContainer's mainAreaWidth). On a wide terminal the
dialog grew to 110 columns inside the 100-column container and its right
border/edge was clipped off-screen. Narrow terminals were unaffected
because columns - 4 stayed within the cap.

Cap dialogWidth at Math.min(columns - 4, 100) to match the container.

Adds a wide-terminal regression test (200-column stdout) asserting no
rendered line exceeds the content area.

* fix(extensions): address review round 3 — symlink/ANSI confinement, crash & data-loss hardening

Security:
- claude-converter: confine git-subdir subdir against symlink escape;
  fail strict mode on a symlinked plugin.json; sanitize untrusted
  source/path in conversion error messages
- sourceRegistry: sanitize version/category/lastUpdated and component
  names before TUI render
- gemini-converter: guard gemini-extension.json reads with realPathWithin
- SourcesTab: sanitize persisted marketplace name in list + remove-confirm

Robustness:
- SourcesTab: wrap sync removeSource in try/catch (was crashing the TUI);
  only mark a marketplace updated when the refresh actually loaded
- InstalledTab: move bundled-MCP enable write inside try/catch
- DiscoverTab: return to the list (not an arbitrary plugin's detail) after
  a failed batch install
- install.ts: roll back the User-scope disable when the Workspace enable fails
- claude-converter: reject a null/non-object plugin.json with a clear error;
  warn instead of silently skipping a symlinked .mcp.json
- extensionPreferences/sourceRegistry: quarantine a corrupt state file to
  ${path}.corrupted so the next write can't clobber recoverable data

Tests:
- cover marketplace.json/plugin.json/.mcp.json symlink guards, strict-mode
  rejection, and null plugin.json
- delete the process.stdout.columns override on non-TTY in dialog width tests

* fix(extensions): guard toggleFavorite write against unhandled rejection

* test(extensions): normalize realpathSync mock so gemini guard passes on Windows

* fix(extensions): address review round 4 — shared sanitizer, narrowed quarantine, visible warnings, tests

- consolidate the three drifted ANSI/control-char strippers into a single
  shared stripAnsiAndControl in core textUtils (fixes the C1-range gap in
  workflow-orchestrator's copy); sourceRegistry/claude-converter now delegate
- claude-converter: also sanitize the git-subdir ref/sha in the not-found error
- corruptFile: surface the quarantine on stderr (debug log is gated off, so a
  silent move would still look like data loss)
- extensionPreferences/sourceRegistry: only quarantine on a JSON parse failure,
  not on transient read errors (EACCES/EMFILE/EISDIR) that leave a valid file
- install: surface a failed scope-change rollback instead of swallowing it

Tests:
- gemini-converter: negative-path coverage for the realPathWithin guards
- new corruptFile.test (rename-aside + best-effort failure)
- stripAnsiAndControl unit tests (ANSI/OSC/C0/C1)
- install rollback + rollback-also-fails cases

* test(extensions): assert discoverPlugins strips ANSI/control chars from display fields

Locks in the untrusted-metadata sanitization that was only covered
empirically before. Feeds a hostile plugin (cursor moves, line clears,
OSC title-injection, BEL) through discoverPlugins and asserts every
rendered field — name/version/description/author/homepage/category/
lastUpdated/component names plus the marketplace name — comes out clean.

Addresses the maintainer verification note on PR QwenLM#4850.

* fix(extensions): address review round 5 — scope-change rollback, version sanitization, visible read warnings

- Critical: the UI scope-change (ExtensionActionsView) and project-scope
  install (DiscoverTab) disabled User then enabled Workspace with no
  rollback — a failed Workspace enable left the extension disabled at all
  scopes (silently dead, and in DiscoverTab the outer catch swallowed it so
  the install still reported success). Mirror the CLI install.ts pattern:
  roll the User enable back on failure.
- Persist the scope preference only AFTER enablement succeeds (install.ts +
  both UI paths), so a rolled-back enable can't leave prefs pointing at a
  scope the extension isn't actually enabled at (Installed tab mislabel).
- Security: the persisted 'version' is rendered raw on the Installed tab and
  PluginDetailView — only 'name' is validated on load, so a marketplace
  plugin could inject ANSI/control sequences post-install on every render.
  Scrub via stripUnsafeCharacters at both sinks (covers already-installed
  extensions; the Discover-side sanitization doesn't reach this path).
- Transient read errors in extensionPreferences/sourceRegistry only logged
  via the gated debugLogger, so a user's favorites/scopes/sources could
  vanish with no trail. Add an stderr warning matching quarantineCorruptFile.
- Tests: assert quarantine runs on a parse error (.corrupted sibling) and
  does NOT run on a transient read error (EISDIR), for both stores.

* fix(extensions): address review round 6 — marketplace-name sanitization, rollback-failure surfacing, url-source guard, security tests

Code:
- ANSI injection via the Discover marketplace filter: the marketplace name
  (untrusted, from a remote marketplace.json) flowed through onBrowse to the
  Discover hint render unsanitized. Scrub it in handleBrowseSource — this also
  fixes the filter comparison (it is matched against the already-sanitized
  DiscoveredPlugin.marketplaceName).
- '(Tab to clear)' hint was misleading: Tab cycled tabs rather than clearing
  the marketplace filter in place. On Discover with an active filter, Tab now
  clears the filter in place, matching the hint.
- Scope-change rollback failures were silently swallowed by a bare catch in
  both the Discover batch install and ExtensionActionsView, unlike the CLI
  install.ts which surfaces them. Both now report the rollback failure so the
  user knows the extension may be disabled at all scopes (new i18n keys for
  en/zh/zh-TW).
- resolveInstallSource: the structured { source: 'url' } branch bypassed the
  local-path guard applied to string sources, letting a remote http
  marketplace redirect the installer at a local filesystem path. Apply the
  same guard.

Tests:
- marketplace fetchUrl: wall-clock deadline (stalled server) and body-size cap
  (oversized stream) now covered.
- sourceRegistry: remote-marketplace local-path rejection covered for both the
  string and { source: 'url' } source forms.
- claude-converter git-subdir: clone+sha-pin happy path plus path-escape,
  absolute-path, missing-subdir, and symlink-escape rejections covered.

Note: the bot's 'missing scope rollback' threads target a pre-631e271fb
snapshot — that rollback already landed in round 5.

---------

Co-authored-by: 克竟 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
doudouOUC and others added 26 commits June 25, 2026 08:08
…enLM#5804)

* feat(telemetry): Make sensitive span attribute limit configurable

Default sensitive native OTel span attribute payload truncation to 1 MiB and allow users to override the limit via settings or environment.

Co-authored-by: Qwen-Coder <[email protected]>

* codex: fix CI failure on PR QwenLM#5804

Add the new sensitive span attribute default export to telemetry/core mocks used by the full Windows test suite.

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Include invalid telemetry max-length values in errors, make the telemetry parser stricter, include the configured truncation limit in markers, and cover the exact truncation boundary.

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* test(cli): fix ACP worktree mock for telemetry limit

Co-authored-by: Qwen-Coder <[email protected]>

* fix(core): honor telemetry limit for model output spans

Co-authored-by: Qwen-Coder <[email protected]>

* test(core): cover telemetry span limit edge cases

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Keep sensitive span truncation results within the configured max length, make response-text extraction require an explicit cap, and cover whitespace-only sensitive span max length env values.

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Keep model-output span attribute writes best-effort and share visible response text extraction between log and sensitive span paths.

Co-authored-by: Qwen-Coder <[email protected]>

* fix(core): address telemetry review feedback

Bound prefixed tool span payloads, share sensitive max-length validation, and cover multi-part sensitive model output.

Co-authored-by: Qwen-Coder <[email protected]>

* fix(cli): update workspace facade core mock

Add telemetry sensitive span length constants to the qwen-code-core mock used by the workspace service facade test so settings schema imports can load.

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

* codex: address PR review feedback (QwenLM#5804)

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
Co-authored-by: 易良 <[email protected]>
* fix(packaging): bundle audio capture for mirror installs

* fix(packaging): include audio prebuilds before packaging

* fix(cli): narrow native audio load error wrapping

* test(packaging): cover native audio fallback paths

* fix(packaging): require native audio artifacts

* fix(packaging): allow fork release without audio prebuilds

* fix(packaging): keep fork audio dependency fallback

* test(packaging): harden audio bundle coverage

* fix(packaging): validate native audio artifacts

* fix(packaging): harden native audio fallback paths

* fix(packaging): tighten audio bundle copy
…timeout (QwenLM#5845)

* feat(core): allow QWEN_STREAM_IDLE_TIMEOUT_MS env to tune the stream idle timeout

The streaming inactivity timeout was only programmatically configurable via
ContentGeneratorConfig.streamIdleTimeoutMs (default 120s). Add a deployment knob
so a daemon deployment can tune it without code, the same way the QWEN_SERVE_*
params are set.

resolveStreamIdleTimeoutMs precedence: explicit config field (wins, including 0
to disable) > QWEN_STREAM_IDLE_TIMEOUT_MS env > default. A malformed env value is
ignored with a debug warning rather than failing the request.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): bound + resolve-once the stream idle timeout env

Audit follow-ups on QWEN_STREAM_IDLE_TIMEOUT_MS:

- Reject values above the JS timer ceiling (2147483647 ms): setTimeout silently
  compresses larger delays to 1ms, which would make the watchdog trip almost
  immediately and abort every streaming request. Oversized → default + warning.
- Resolve the timeout once in the pipeline constructor instead of per streaming
  request, so the env read and any invalid-value warning happen once per
  pipeline rather than on every model call.

Adds a test for the oversized-env case.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* test(core): harden stream-idle env fallback tests to verify the default is used

The malformed/oversized env tests only advanced 3000ms and asserted "not
tripped" — under fake timers that passes even if the bad value were used (fake
timers schedule at the literal delay, with no Node overflow-to-1ms). They now
advance to the default and assert the watchdog trips there, which distinguishes
"default used" from "bad value scheduled far away". Verified the oversized test
fails when the upper bound is removed.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): harden stream-idle timeout resolution (Codex review)

- Strict decimal-integer env parsing: reject hex ("0x10")/scientific ("1e3")/
  float/signed QWEN_STREAM_IDLE_TIMEOUT_MS via /^\d+$/, so a typo can't silently
  become a surprising timeout (matches utils/env.ts).
- Validate the explicit config field too: an out-of-range value (above the JS
  timer ceiling) would overflow setTimeout to a near-immediate fire; reject it
  and fall back instead.
- Test isolation: clear any ambient QWEN_STREAM_IDLE_TIMEOUT_MS in beforeEach so
  the default-timeout tests aren't silently overridden by the dev/CI shell.

Adds tests for the non-decimal env and out-of-range config cases (both verified
to fail when their guard is removed).

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): address stream-idle timeout review feedback

Resolves all 4 review comments on PR QwenLM#5845:

1. [Critical] Negative config: restore the old `<= 0` disable contract. The
   resolver now accepts any integer up to the timer ceiling; negatives pass
   through and the downstream `idleMs > 0` guard skips the watchdog. This fixes
   a behavioral regression where negative values (previously a valid way to
   disable) silently became a 120s timeout.

2. [Suggestion] Add a test for `QWEN_STREAM_IDLE_TIMEOUT_MS=0` proving the
   watchdog is disabled via the env path (regression guard against a regex
   tightening to `[1-9]\d*`). Also add a test for negative config.

3. [Suggestion] Env-in-pipeline vs config-assembly: acknowledged as an
   intentional scoping decision — the resolver lives at the layer that enforces
   the timeout, matching how the sibling `timeout` field works. No code change.

4. [Suggestion] Switch config warnings from debugLogger.warn (off by default)
   to console.warn so an operator misconfiguring the env gets visible feedback.
   The resolve-once design means these fire once per pipeline, not per request.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): address remaining stream-idle timeout review comments

- Use QWEN_STREAM_IDLE_TIMEOUT_MS_ENV constant in all test stubEnv calls instead
  of hardcoding the string (comment #5).
- Add config→env cascade test: invalid config + valid env → uses the env value,
  not the default (comment #6).

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): fix JSDoc (console.warn not debug) + add boundary acceptance test

- Fix JSDoc: says "debug warning" but implementation uses console.warn.
- Add test for exact MAX_STREAM_IDLE_TIMEOUT_MS boundary acceptance (guards
  against an off-by-one changing <= to <).

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* codex: address PR review feedback (QwenLM#5845)

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: Qwen-Coder <[email protected]>
…ion (QwenLM#5817)

* feat(cli): support a user-configurable keyterms file for voice dictation

Voice dictation biased the ASR with a hardcoded keyterm list, so users had
no way to improve recognition of domain-specific terms. Add an optional
general.voice.keytermsFile setting plus auto-discovery of
.qwen/voice-keyterms.txt; its terms (one per line, # comments) merge with
the globals, deduped case-insensitively and capped by count and length.

The file is read only in a trusted workspace and must be a regular,
non-symlink file under a size bound, so a cloned or untrusted repo cannot
plant a file or a symlink to a secret that would exfiltrate to the ASR
provider on the next dictation. Applies to the Qwen ASR transports only;
DashScope fun-asr/paraformer use a separate vocabulary_id mechanism.

Closes QwenLM#5816

Co-Authored-By: Qwen-Coder <[email protected]>

* fix(cli): harden voice keyterms file reads

* test(cli): cover hard-linked keyterms files

* test(cli): cover keyterms scope and char cap

* fix(voice): expand keyterms file home paths

* fix(voice): harden keyterms file reads

* fix(voice): reject swapped keyterms files

* fix(voice): preserve keyterms after budget skips

* fix(voice): cap keyterms by utf8 bytes

* fix(voice): fall back across keyterms scopes

* fix(voice): harden keyterms file reads

* fix(voice): detect keyterm echoes in large contexts

* fix(voice): preserve hash keyterms

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
* fix(core): reject userinfo URLs in WebFetch validation

* test(core): cover malformed WebFetch URLs

Add malformed URL cases that pass the initial scheme check but fail URL parsing, covering the validation fallback path.

Co-authored-by: Shaojin Wen <[email protected]>

---------

Co-authored-by: Shaojin Wen <[email protected]>
* ci: route the merge queue's Linux jobs onto ECS

The merge queue runs in the base-repo context but classify_pr was PR-only, so its ubuntu_runner output was empty in the queue and the Ubuntu Test + Integration jobs fell back to the shared hosted pool — piling onto the scarce hosted Linux runners exactly when the queue is busiest. Run classify_pr on merge_group too and route both the Ubuntu gate and Integration onto the same in-repo ECS pool as PRs; the MAINTAINER_ECS_RUNNER_DISABLED kill-switch and the hosted fallback are intact, and fork PRs are unaffected.

Also extend the checkout-verification guard to the merge queue: now that the queue's Ubuntu checkout runs on ECS behind the squid egress proxy, a stale-ref checkout could silently test the wrong tree, and a wrong-tree pass in the queue would merge bad code. One sub-second merge-base check.

Routing approach carried forward from QwenLM#5853 by @wenshao (closed); this adds the merge-queue checkout guard on top.

* ci: fix verify-step wiring test and guard integration_cli on ECS

The merge-queue ECS routing renamed the test job's checkout guard to "Verify
checkout includes expected head commit", but no-ak-integration-ci.test.js still
asserted the old "Verify PR checkout includes head commit" name, failing the
wiring test. Update the assertion.

integration_cli now also routes to ECS (via classify_pr on merge_group) yet
lacked the protections the Ubuntu gate has. Mirror them: fetch-depth 1 (nothing
walks history; a full clone is the heaviest transfer on the ECS runner) and the
same stale-checkout guard, keyed on merge_group.head_sha.

* ci: mirror the Node 22 version probe into integration_cli

The self-hosted Node step claimed to mirror the Ubuntu gate but omitted the
major-version probe, so a non-22 Node on the ECS runner would run integration
tests with no log signal. Add the same warning-only check.
)

The collapsed thinking summary dropped the elapsed time once thinking
finished, showing a bare "Finished thinking" / "已完成思考". This keeps
the duration after completion (matching the streaming state and common
reasoning-trace conventions) and refines the wording:

- en: "Thought for 5s" (live) / "Done thinking" (history, no duration)
- zh: "已思考 5s" (live) / "思考完成" (history, no duration)

History messages loaded without a known duration fall back to the
duration-less label.
The two '<ToolMessage /> localized badge' locale tests await
setLanguageAsync(), which loads locale resources lazily. Under the
heavily parallelized macOS CI runner the call intermittently exceeds
the 5s default and times out, repeatedly kicking PRs out of the merge
queue (e.g. QwenLM#5828) despite unrelated changes.
After QwenLM#5842, CodeQL and the E2E suite were the only things running on every push to `main` — the per-commit, post-merge backstop. With merges landing back-to-back, those runs (CodeQL ~30min, three E2E jobs ~25/36/36min, the latter never cancel-superseded) stacked on the scarce hosted Linux pool and were a main driver of the recent runner-saturation incident.

- CodeQL moves to its own scheduled codeql.yml (nightly + workflow_dispatch). It was never a required check and findings still surface in the Security tab, so per-commit scanning bought little. ci.yml loses its now-empty `push` trigger as a result (every remaining job is gated to pull_request / merge_group).
- E2E gets event-scoped concurrency so back-to-back pushes to `main` cancel superseded runs (only the latest tree matters and it covers every merged change), plus a nightly full regression as the guaranteed signal in case a busy merge window keeps cancelling the push run. Manual workflow_dispatch added.

The merge_group gate (ubuntu + integration + mac + win) still validates every PR before it lands; this only changes the non-gating post-merge work.

Follow-up (separate PR): alert on E2E/CodeQL failure (a deduped ci-failure issue) now that they run unattended.
The conflict-resolution agent step runs with `sandbox: true`, which on
Linux needs docker or podman to launch the sandbox. The self-hosted ECS
pool ships no container runtime, so the job died at the agent step
(exit 44, "failed to determine command for sandbox") before it could
resolve anything — see run 28158417390.

Pin the job to ubuntu-latest, which ships docker and is ephemeral (a
good fit for running the untrusted PR's build/lint/test in the
verification gate). Update the cleanup and PAT-scrub comments that
assumed a reused self-hosted workspace; both steps stay as defensive
no-ops on hosted runners.
…w mutation tools individually (QwenLM#5661)

* feat(tui): remove tool group borders and collapse completed tool results

Remove round borders from ToolGroupMessage, CompactToolGroupDisplay, and
InlineParallelAgentsDisplay. Completed tools now default to a single
collapsed header line with dimColor styling. Executing/error/confirming
tools continue to show their full result block.

Part of QwenLM#4588 (Track 3: Simplify tool-call rendering).

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): gate collapse on compact mode and fix innerWidth calculation

- Only collapse completed tool results in compact mode, preserving
  full visibility in non-compact mode
- Subtract 2 from innerWidth to account for ToolMessage paddingX={1}
- Update snapshots to reflect removed borders

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): address review feedback on collapse and visual alignment

- Gate isDim on compact mode so non-compact tools stay fully styled
- Add paddingX={1} to CompactToolGroupDisplay for left-edge alignment
- Delete Border Color Logic test block (borders removed)
- Add compact-mode test coverage for Error/Executing/Pending/forceShowResult
- Clean up stale border references in comments

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* feat(tui): unify tool output with semantic summaries

Replace the dual compact/normal mode tool output with a single unified
mode. Completed tools always show a semantic overview line
("Read 3 files, edited 2 files") instead of dumping full results.

- Add buildToolSummary() for category-based semantic summaries
- Remove compactMode gate from shouldCollapse and isDim in ToolMessage
- Make all-completed tool groups use CompactToolGroupDisplay
- Remove unused useCompactMode hook calls from ToolMessage

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* test(tui): add buildToolSummary unit tests and fix stale comment

- Add 10 dedicated unit tests for buildToolSummary covering edge cases
- Fix stale comment referencing old compactMode gate logic

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): address audit findings for unified tool output

- Add Canceled status to allComplete check in ToolGroupMessage
- Move memory-only group rendering before showCompact to prevent
  them being swallowed by CompactToolGroupDisplay
- Fix LLM summary duplication: absorbedCallIds now tracks completed
  groups in non-compact mode; HistoryItemDisplay no longer bypasses
  summaryAbsorbed when !compactMode
- Update StandaloneSessionPicker test for new compact rendering
- Fix design doc category order example and add missing rendering rules

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): address inline review findings

- Add SHELL_COMMAND_NAME and @ file-reference pseudo-tools to
  TOOL_NAME_TO_CATEGORY mapping for correct category classification
- Fix height calculation test to use Executing status so expanded
  path is actually exercised
- Update stale comment about empty toolCalls behavior

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): remove unused compactMode import in HistoryItemDisplay

Fixes CI build failure caused by TS6133 (noUnusedLocals) — the
compactMode destructure became dead code after the summary gating
was moved to summaryAbsorbed.

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* ci: trigger re-run with updated merge ref

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* refactor(tui): partition tools by type instead of completion status

Align tool display with read/search collapse pattern: only
information-gathering tools (read, search, list) are collapsed into a
summary line; mutation tools (edit, write, command, agent) always
render individually with their results.

- Remove compactLabel prop and cross-group merge logic from MainContent
- Add isCollapsibleTool predicate and partition in ToolGroupMessage
- Remove shouldCollapse gate from ToolMessage (results always shown)
- Update CATEGORY_ORDER to search → read → list → command → ...
- Update tests and snapshots to match partition-based rendering

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): collapse text/ANSI output for completed tools

Only string and ANSI results are hidden for completed (Success/Canceled)
tools — diff, plan, todo, and task results always render since they
carry non-repeatable information the user needs to review inline.

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): unify summary format and show results in error-expanded groups

- buildToolSummary always uses count format ("Read 1 file") instead of
  description for single tools, ensuring consistent display across all
  collapsible tool groups
- Pass forceExpandAll to forceShowResult so sibling Success tools in
  error-expanded groups keep their results visible for diagnostics
- Add memory-only group test coverage (Recalled N memories / Wrote N)

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* test(tui): improve coverage for partition logic and result collapse

- Add isCollapsibleTool unit tests (read/search/list → true, others → false)
- Add partition tests: pure collapsible → summary, mixed → summary + individual
- Add forceExpandAll tests: error group bypasses partition, all siblings get forceShowResult
- Add diff bypass test: completed Success tool with diff result is not collapsed
- Update MockTool to surface forceShowResult flag for assertion
- Update snapshots reflecting forceExpandAll → forceShowResult propagation

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): align CompactToolGroupDisplay style with ToolInfo

Replace dimColor={!isActive} with bold to match ToolInfo's styling in
ToolMessage. Completed summary lines now render at normal brightness
with bold text, consistent with sibling non-collapsible tools in the
same group.

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): address review findings on result collapse and memory safety

- Only collapse results for collapsible tools (read/search/list), not
  MCP/WebFetch/other tools whose output is the answer
- Only collapse on Success, not Canceled (partial output may be useful)
- Exclude errored memory ops from allMemOpsComplete early return so
  error details remain visible
- Add memory badge to all-collapsible early return path
- Simplify forceShowResult to forceExpandAll (per-tool conditions were
  already subsumed by group-level flags)
- Account for collapsible summary row in height budget
- Remove vestigial mergedHistory alias
- Remove tool_group from compactToggleHasVisualEffect (compact mode no
  longer affects tool rendering)
- Fix outdated JSDoc in buildToolSummary

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* docs(tui): sync design doc with actual implementation

Update unified-tool-output.md to reflect:
- Type-based partition (isCollapsibleTool) instead of completion-based
- Count format for all summaries ("Read 1 file" not "Read package.json")
- shouldCollapseResult gated on collapsible tools and Success only
- Bold styling for all tool names (isDim removed)
- tool_use_summary renders unconditionally (absorption removed)
- forceShowResult simplified to forceExpandAll
- compactToggleHasVisualEffect no longer triggers on tool_group

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* test(tui): update AppContainer test for compactToggleHasVisualEffect change

tool_group no longer triggers a visual effect on Ctrl+O, so the test
now expects refreshStatic to be skipped for tool-group-only histories.

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): restore per-tool forceShowResult and harden edge cases

- Revert forceShowResult to per-tool computation so shell output
  capping is preserved for successful siblings in force-expanded groups
- Exclude Canceled tools from collapsible partition so partial output
  stays visible via individual ToolMessage rendering
- Extract shared MemoryBadge (deduplicate IIFE in all-collapsible and
  mixed paths)
- Add memory badge height to staticHeight budget in mixed path
- Add legacy ToolDisplayNamesMigration entries (SearchFiles, FindFiles,
  ReadFolder, Task, TodoWrite) to TOOL_NAME_TO_CATEGORY
- Fix stale comment referencing removed showCompact

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* test(tui): add coverage for canceled partition, memory badge, and legacy names

- Canceled collapsible tool renders individually (not absorbed into
  summary line), preserving partial output visibility
- Mixed group with memory counts renders memory badge alongside
  collapsible summary and individual tools
- Legacy display names (SearchFiles, FindFiles, ReadFolder, Task,
  TodoWrite) map to correct categories in isCollapsibleTool and
  buildToolSummary

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): document dual effect of isCollapsibleTool and add ANSI collapse test

Update isCollapsibleTool JSDoc to document both decision points
(ToolGroupMessage partition and ToolMessage.shouldCollapseResult) so
future maintainers understand that adding a category suppresses both
grouping and result output.

Add test for ANSI renderer branch of shouldCollapseResult to ensure
ANSI output from collapsible tools is also collapsed.

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* fix(tui): address review round 6 — type fix, stale refs, and test gaps

- Fix TS2740: add required AnsiToken properties to ANSI collapse test
- Rename mergedLengthRef → visibleHistoryLengthRef to match removed
  mergedHistory concept
- Fix design doc Rule 5: forceExpandAll forces results only for
  triggering tools, not all siblings
- Update compactToggleHasVisualEffect JSDoc: tool_group no longer
  checked, only gemini_thought items affected by compact mode
- Fix diff bypass test: use collapsible tool name (ReadFile) so
  shouldCollapseResult is actually exercised
- Add all-collapsible memory badge test covering the early-return path

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

* test(tui): add isUserInitiated and memory-only error test coverage

- Add test: user-initiated group renders all collapsible tools
  individually (bypasses partition into summary line)
- Add test: memory-only group with errored tool falls through to
  expanded path instead of showing compact badge

Generated with AI

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: 秦奇 <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
QwenLM#5872)

On macOS, terminals in the default "Option as compose character" mode
(iTerm2 "Normal", VS Code without macOptionIsMeta) turn Option+t into the
dagger glyph "†" (U+2020) with no modifier metadata, so the app cannot tell
Option was held — the "expand thinking" shortcut silently typed "†" into the
prompt instead of toggling. Terminals that speak the Kitty keyboard protocol
(e.g. Ghostty) report a real Alt+t event, which is why it already worked there.

Rewrite a lone "†" to a synthetic Alt+t in the keypress pipeline. This both
fires TOGGLE_THINKING_EXPANDED and, via the meta flag, stops the glyph from
being inserted into the input buffer, so it behaves exactly like Alt+t. Scoped
to darwin to avoid affecting legitimate "†" input on other platforms.

Generated with AI

Co-authored-by: 秦奇 <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
* feat(mcp): reconcile MCP servers live on settings change

Hot-reload MCP servers when settings.json changes (issue QwenLM#3696 sub-task 3):
editing mcpServers / mcp.allowed / mcp.excluded now connects, disconnects, or
restarts only the affected servers in place, without restarting the session or
losing conversation context.

- Part A: Config runtime setters + reinitializeMcpServers incremental
  reconcile; align the shared-pool path with the QwenLM#4615 pending-approval gate
- Part B: SettingsWatcher subscriber (hotReload.ts), gated on a mcpServers +
  gating-list diff; flip the three MCP schema keys to hot-reloadable
- Part D: re-fire the approval modal for a gated server left pending by an edit
- Part E: /mcp shows why a gated server was skipped (pending / rejected)
- Record connection fingerprints on the bulk and lazy-connect paths so an edit
  to a server first connected via those paths is not silently dropped
- Design doc (en/zh) incl. the admission-stance boundary clarification

Co-Authored-By: Claude Opus 4.8 <[email protected]>

# Conflicts:
#	packages/cli/src/config/settingsSchema.test.ts

# Conflicts:
#	packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx

# Conflicts:
#	packages/cli/src/gemini.tsx

* feat(mcp): reconcile MCP servers live on settings change

Hot-reload MCP servers when settings.json changes (issue QwenLM#3696 sub-task 3):
editing mcpServers / mcp.allowed / mcp.excluded now connects, disconnects, or
restarts only the affected servers in place, without restarting the session or
losing conversation context.

- Part A: Config runtime setters + reinitializeMcpServers incremental
  reconcile; align the shared-pool path with the QwenLM#4615 pending-approval gate
- Part B: SettingsWatcher subscriber (hotReload.ts), gated on a mcpServers +
  gating-list diff; flip the three MCP schema keys to hot-reloadable
- Part D: re-fire the approval modal for a gated server left pending by an edit
- Part E: /mcp shows why a gated server was skipped (pending / rejected)
- Record connection fingerprints on the bulk and lazy-connect paths so an edit
  to a server first connected via those paths is not silently dropped
- Design doc (en/zh) incl. the admission-stance boundary clarification

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* fix(mcp): harden hot-reload teardown and reconcile (review follow-ups)

Address reviewer findings on the MCP hot-reload changes:

- Extract purgeServerRegistries() and use it at every teardown path, fixing
  the discovery-timeout handler which leaked prompts/resources (only tools
  were purged) for a server that stalled tools/list past the timeout.
- Surface reconcile failures via AppEvent.LogError so a failed settings edit
  is visible to the user, not just under --debug.
- Make a single-session config edit to a discovery filter (trust /
  includeTools / excludeTools) reconnect the server so discover() re-applies
  it: connectionIdOf stays transport-only; add singleSessionConnectedKeyOf and
  rename connectionFingerprints -> connectedConfigKeys.
- Make a coalesced reinitializeMcpServers await the in-flight pass + its drain
  (store mcpReconcilePromise) so the caller no longer emits approval events /
  logs "complete" before its change is applied; coalesced callers share the
  failure.
- Assert removeResourcesByServer in the fingerprint-change tests.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* feat(mcp): bound hot-reload MCP admission and explain why servers are unavailable (QwenLM#3696) (QwenLM#5561)

- K: treat the startup --allowed-mcp-server-names flag as an immutable upper
  bound — a runtime settings edit may narrow MCP admission within it but never
  widen beyond it; with no flag, settings fully drive admission.
- H: preserve an explicit `mcp.allowed: []` as deny-all (don't collapse to
  undefined / allow-all), matching boot semantics, and make mcpGatingEqual
  distinguish absent (allow-all) from [] (deny-all) so the change reconciles.
- B: classify why an MCP server is unavailable (removed / not_allowed /
  excluded / pending_approval) and route the tool-not-found message to the
  right recovery action; track removals against the gating-independent merged
  map (dropping the prev-effective snapshot param).

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* docs(mcp): document hot-reload admission bound, deny-all, and unavailable reasons (Part F)

Reflect the K/H/B changes in the sub-task 3 design doc: add Part F (CLI
--allowed-mcp-server-names as an immutable upper bound, mcp.allowed: [] as
deny-all, and getMcpServerUnavailableReason routing the tool-not-found message),
and fix the now-superseded "settings can widen beyond the startup allowlist"
admission-stance note and verification item 11.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* test(serve): pre-approve gated MCP servers in daemon baseline harness

The pool/daemon discovery path now honors QwenLM#4615 pending-approval gating, so the workspace-scoped MCP servers the amplification suite declares in .qwen/settings.json are skipped as pending and never spawn (the suite timed out waiting for grandchildren). Add approveWorkspaceMcpServers() to the harness (keyed by the realpath workspace to match the daemon's canonicalized --workspace) and pre-approve the fixtures before boot, mirroring simple-mcp-server.test.ts.

---------

Co-authored-by: heyang.why <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
…QwenLM#5870)

* ci(qwen-resolve): support fork PRs and slim /resolve to conflict-only

Closes the fork gap QwenLM#5779/QwenLM#5862 left for the maintainer /resolve command, so it
can clear merge conflicts on community (fork) PRs, and narrows the command to
exactly one job: resolve the conflict and push it back.

- Fork PRs: fetch the head via refs/pull/N/head and push the resolved branch
  back to the PR's head repository (via Allow edits by maintainers) instead of
  bailing as unsupported. Validated end-to-end against a fork PR.
- Conflict-only: drop the build/typecheck/lint/test gate and npm install/refresh;
  keep the structural checks (markers, index, merge-tree, default-merge, scope).
  Test fallout is left to the PR's own CI and follow-up tasks.
- Push-failure classification: workflow_scope (the merge carries the base's
  .github/workflows/** changes, which a token without the workflow scope cannot
  push), permission (403 / 404), and moved (stale force-with-lease) each get an
  actionable comment; the redacted git stderr is logged for diagnosis.

NOTE: the push bot's PAT (CI_DEV_BOT_PAT) needs the `workflow` scope, since
resolving merges the base in and that update touches workflow files.

Guard tests updated; 12/12 pass.

* ci(qwen-resolve): avoid PR head ref collisions

* ci(qwen-resolve): address review comments

- workflow_scope: anchor classification on GitHub's server phrase
  'refusing to allow ... workflow' instead of a loose workflow.*scope, which
  the attacker-controlled branch name in git's rejected-ref echo could trip.
- prepare: bail when the head repository was deleted (null headRepository →
  malformed push URL).
- moved: include the run-artifact link, consistent with the other cases.
- permission: drop 'could not read' (matched transient network errors).
* feat(serve): query a single session's status by id

Add a daemon HTTP endpoint, GET /session/:id/status, that returns the
live status summary for one session by its id — the same per-item shape
that the workspace session list produces (sessionId, workspaceCwd,
createdAt, displayName, clientCount, hasActivePrompt). It answers 200
with the summary when the daemon holds a live session with that id, and
404 when the id is unknown.

Previously the only way to read a session's live state was the full
paginated workspace session list, forcing a caller that already holds a
session id to fetch every page and filter client-side just to answer
"is this session still running?". A by-id lookup is the natural
primitive for polling a single known session's hasActivePrompt /
clientCount — for example, a client UI that disables controls or shows a
"task in progress" hint while a specific session is running.

The data already exists on the bridge, so this adds one accessor
(getSessionSummary) sharing the same summary builder as the list path,
one route, unit tests, and a docs note.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* docs(serve): clarify /session/:id/status returns the live bridge view

The session-status docs said the response is "the same item shape that
GET /workspace/:id/sessions lists". That parity only holds at the bridge
layer; the HTTP list endpoint enriches each item with persisted
session-store data, so for the same live session the two routes diverge
on createdAt (persisted first-prompt time vs live spawn time), updatedAt
(present only on the list), and displayName (derived from the stored
title/prompt vs the live session's own, usually unset). Reword to
describe /status as the raw live-session view, spell out those
differences, and fix the 404 note to match the actual { error, sessionId }
body (no code field).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* feat(serve): advertise GET /session/:id/status via session_status capability

The new single-session status route had no entry in the capability
registry, so clients couldn't feature-detect it the way they pre-flight
the sibling read-only session routes (session_context, session_tasks,
session_stats, session_lsp, …). Add an always-on `session_status` tag,
mirror it in the registered-features test, and document it in the
protocol feature list, the capability→route map, and the capability
versioning reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* test(serve): pin that /session/:id/status omits displayName when unset

The docs state the route returns displayName only when the live session
has one, but no test asserted the key is absent from the HTTP body in
that case — it relied implicitly on res.json() dropping the
undefined-valued key. Add a sibling 200 test with a summary that has no
displayName and assert the key is not present, so a future change to the
shared summary builder can't silently break the documented shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* test(serve): add session_status to the integration capabilities baseline

The capabilities-envelope integration test pins the full caps.features
list returned by a live daemon, so adding the session_status capability
tag to the registry made the live list diverge from the test's hardcoded
baseline (CI: expected 65, received 66). Add session_status to that
baseline in the same position the registry emits it (after session_lsp),
and to the session-lifecycle capability-tag reference for completeness.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

---------

Co-authored-by: 云胧 <[email protected]>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Running in $HOME is already handled by the memory layer (empty effective cwd skips the workspace search), so the home directory is a fully supported working directory, not a degraded state. The warning was pure noise with no actionable guidance, and co-working from $HOME is a legitimate use case that peer coding agents also allow without complaint. Root-directory and ripgrep-availability warnings remain untouched.
…wenLM#5802)

* fix(cli): show ⌥T instead of alt+T on macOS for thinking expansion

On macOS the Option key (⌥) maps to the meta keybinding, but the UI
hint displayed "alt+t" which is confusing since Mac keyboards have no
dedicated Alt key. Show the native ⌥ symbol on darwin so the on-screen
hint matches the actual key users need to press.

* fix(cli): address review feedback on macOS key hint PR

- Use ASCII 'option+t' instead of Unicode '⌥t' to match the existing
  CLI key-hint convention (KeyboardShortcuts.tsx uses alt/cmd/ctrl
  strings exclusively)
- Use t() parameter interpolation instead of template literals so the
  translation key stays stable: t('({{keyHint}} to expand)', {keyHint})
  rather than generating separate keys per platform

Signed-off-by: Alex <[email protected]>

* fix(cli): move toggleKeyHint to module scope

Placed next to THINKING_ICON constant for consistency with
KeyboardShortcuts.tsx patterns (getNewlineKey, getPasteKey at module
scope). Avoids recomputing on every render.

Signed-off-by: Alex <[email protected]>

* fix(cli): export toggleKeyHint as shared constant

Eliminates copy-paste duplication across 3 files. Tests now import
from the source module (same pattern as THINKING_ICON), so any future
change to the platform logic or label text only needs to be made once.

Signed-off-by: Alex <[email protected]>

---------

Signed-off-by: Alex <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
…ifications (QwenLM#5844)

* feat(core): make self-paced /loop lean on monitor/background-task notifications

A self-paced /loop only knew how to keep itself alive by scheduling a
timer wakeup, even when a Monitor or a backgrounded agent it started
re-invokes the session on its own via a <task-notification> once it
finishes. Teach the LoopWakeup tool description and the bundled loop
skill that such work makes the wakeup a long fallback heartbeat
(1200-1800s), not a short poll: a short poll wastes a prompt-cache
window, and the notification already wakes the loop the moment the work
terminates. Keep the fallback rather than omitting it — a monitor can
auto-stop on idle/max-events, be owned by another agent, or the work
can hang.

Guidance only: qwen already auto-wakes the session on these
notifications; this just stops the loop from polling work that reports
on its own.

Closes QwenLM#5841

Co-Authored-By: Qwen-Coder <[email protected]>

* fix(core): clarify loop task notifications

* fix(core): clarify loop notification wakeups

* fix(core): preserve loop restart count

* fix(core): clarify monitor-owned loop notifications

* fix(core): persist loop restart count guidance

* fix(core): include monitor command in notifications

* fix(core): cap ambiguous loop follow-ups

* test(core): cover loop fallback cleanup guidance

---------

Co-authored-by: Qwen-Coder <[email protected]>
* fix(cli): improve token speed accounting

Signed-off-by: seekskyworld <[email protected]>

* fix(cli): address token speed review feedback

Signed-off-by: seekskyworld <[email protected]>

* fix(cli): refine token speed pause handling

Signed-off-by: seekskyworld <[email protected]>

* test(cli): cover repeated tool pause baselines

Signed-off-by: seekskyworld <[email protected]>

---------

Signed-off-by: seekskyworld <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
…out (QwenLM#5865)

* fix(core): stream chat-compression side-query to survive gateway timeout

The context-compression side-query runs non-streaming, so the whole LLM
inference must finish before the first HTTP byte arrives. Behind a BFF
gateway whose `proxy_read_timeout` is ~60s, a long compression inference
(observed ~1.9 min) is killed at 60s with a 504 — surfaced to qwen-code
as a 422 — which fails compression and breaks the session.

Add an opt-in `stream?: boolean` to the text side-query path
(`BaseLlmClient.generateText` -> `runSideQuery`) and have only
`ChatCompressionService.compress` opt in. Streaming keeps the connection
alive (the first delta arrives within seconds, resetting the gateway
timeout), so a slow inference no longer trips the gateway. Streamed
deltas are collected into the same `{ text, usage }` result, so every
other side-query caller keeps the unchanged non-streaming path.

Refs QwenLM#5861

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* docs(core): de-duplicate the `stream` JSDoc across the side-query layers

Keep the full gateway-timeout rationale canonical on
`GenerateTextOptions.stream` and slim `SideQueryTextOptions.stream` to a
brief opt-in note that links to it, instead of repeating the same ~7-line
block in both. Also harmonize "Defaults to falsy" -> "Defaults to `false`"
for the typed boolean. Addresses review feedback on QwenLM#5865.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* test(core): cover streaming side-query error and abort paths

Add two regression tests for the streaming branch of generateText: a
mid-stream throw rejects the whole call (partial text is never returned
as success) and is reported, and an abort firing mid-stream surfaces the
original error unwrapped while skipping reportError via the
`abortSignal.aborted` guard. The first is the gateway-timeout-mid-
inference scenario this PR targets. Addresses review feedback on QwenLM#5865.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* test(core): cover the empty streaming side-query response

Add a boundary test for a stream that yields zero chunks: generateText
must resolve to an empty string with undefined usage rather than throw.
Addresses review feedback on QwenLM#5865.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* test(core): cover per-model streaming and usage on a content chunk

Two streaming-branch gaps surfaced in review:

- The per-model `fastContentGenerator` mock had no `generateContentStream`,
  so no test exercised streaming against a `resolveForModel`-selected
  generator — the exact `model` + `stream: true` combination compression
  uses. Add that mock method and a per-model streaming test asserting the
  resolved generator's stream is consumed (not the injected default).
- `mockTextStream` only emitted usage on a separate trailing chunk. Add a
  test where the final content-bearing chunk carries both a text delta and
  usageMetadata (the realistic Gemini/OpenAI shape), guarding against a
  refactor that skips text extraction on usage-bearing chunks.

Addresses review feedback on QwenLM#5865.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* feat(core): tag streaming failures in generateText error reports

Surface a `[streaming]` marker in the generateText error report when the
streaming branch was active, so an oncall can tell a mid-stream failure
apart from the original non-streaming gateway timeout this PR fixes. The
already-destructured `stream` flag drives it; partial-text length / chunk
count are intentionally left out (they would require hoisting mutable
per-attempt state across the retryWithBackoff boundary).

Also assert the request shape (model, contents, abortSignal-bearing
config, promptId) in the main and per-model streaming tests, matching the
non-streaming tests so a request-construction regression is caught.

Addresses review feedback on QwenLM#5865.

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)
The daemon host process does not need --expose-gc (global.gc() is only
used by memoryPressureMonitor inside ACP children, which independently
add --expose-gc via spawnChannel.ts). Detect `serve` as the first
positional arg and import cli.js directly in-process, eliminating one
full Node process startup (~370ms on EDR-instrumented hosts).

Use pathToFileURL() for the dynamic import so Windows drive-letter
paths are not misinterpreted as URL schemes.
…enLM#5876)

The collapsed tool-group summary read "执行了 N 个工具", but in Chinese a tool is "调用" (invoked), not "执行" (executed); 执行 collocates with 操作/命令/任务. "工具调用" is also the established term elsewhere in the codebase. Switch the zh string to "调用了 N 个工具". The English "Ran N tools" is unchanged.
)

* feat(cli): tighten response timestamp consistency and tests (QwenLM#5610)

- Preserve timestamps for resumed assistant messages in convertToHistoryItems
  using ChatRecord.timestamp (ISO 8601 → epoch ms)
- Add explicit hour/minute/second 2-digit options to toLocaleTimeString for
  guaranteed HH:MM:SS format across ICU variants
- Add positive stream tests asserting commitItem attaches numeric timestamp
  to gemini items and does not attach one to user items
- Update existing resumeHistoryUtils tests to include timestamp in mock data

Co-authored-by: Qwen-Coder <[email protected]>

* test(cli): broaden timestamp negative test to cover all non-gemini items (QwenLM#5610)

Review feedback: the previous test only asserted on user items, but the
issue asks to verify timestamps are not attached to continuation items
(gemini_content). Changed to assert on all non-gemini types.

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: 俊良 <[email protected]>
Co-authored-by: Qwen-Coder <[email protected]>
Tool call descriptions (shell commands, file paths, etc.) were truncated
at the terminal line width with no way to see the full text after the
output scrolled out of view. The ANSI echo shows the command during
execution but disappears afterward, hindering session review.

Change wrap from truncate-end to wrap so long descriptions automatically
flow to the next line, keeping the full text visible in the message
header for later reference.

Signed-off-by: Alex <[email protected]>
@github-actions

Copy link
Copy Markdown

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 78.06% 78.06% 83.09% 80.2%
Core 84.11% 84.11% 85.33% 84.54%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   78.06 |     80.2 |   83.09 |   78.06 |                   
 src               |    75.9 |     75.4 |   82.97 |    75.9 |                   
  gemini.tsx       |   67.27 |    72.18 |   81.25 |   67.27 | ...-971,1010-1014 
  ...ractiveCli.ts |    74.8 |    72.44 |   76.19 |    74.8 | ...1810-1812,1847 
  ...liCommands.ts |   88.86 |    84.25 |     100 |   88.86 | ...38,407,441,562 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   58.56 |    62.95 |   83.81 |   58.56 |                   
  acpAgent.ts      |   58.43 |    62.99 |   84.02 |   58.43 | ...7237,7251-7259 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   91.17 |       90 |   83.33 |   91.17 |                   
  filesystem.ts    |   91.17 |       90 |   83.33 |   91.17 | 24-25,31-32,98-99 
 ...ration/session |   86.64 |    79.19 |   89.92 |   86.64 |                   
  ...ryReplayer.ts |   76.84 |    85.33 |   85.71 |   76.84 | ...50-365,378-379 
  Session.ts       |   87.31 |    78.16 |   91.26 |   87.31 | ...4764,4790-4794 
  ...entTracker.ts |   91.39 |    89.47 |   88.88 |   91.39 | ...31,195,266-275 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   84.21 |    83.33 |     100 |   84.21 | ...37-153,209-211 
  tasksSnapshot.ts |   94.06 |    86.66 |     100 |   94.06 | 60-66             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ssion/emitters |   96.25 |    94.25 |   96.96 |   96.25 |                   
  BaseEmitter.ts   |    92.3 |    81.81 |     100 |    92.3 | 23-24             
  ...ageEmitter.ts |   95.23 |    95.23 |     100 |   95.23 | 48-55             
  PlanEmitter.ts   |     100 |      100 |     100 |     100 |                   
  ...allEmitter.ts |   98.44 |    94.62 |     100 |   98.44 | 318-319,420,428   
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
 ...ession/rewrite |    91.3 |    88.09 |   94.44 |    91.3 |                   
  LlmRewriter.ts   |      81 |       84 |     100 |      81 | ...,88-89,155-159 
  ...Middleware.ts |   96.74 |    86.84 |     100 |   96.74 | 135,143-145       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/commands      |   83.73 |    61.85 |   59.25 |   83.73 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   56.66 |      100 |       0 |   56.66 | 15-19,27-34       
  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        |   51.85 |      100 |       0 |   51.85 | 24-35,38          
  serve.ts         |   84.19 |    57.31 |     100 |   84.19 | ...31-534,547-551 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
 ...mmands/channel |   41.76 |     85.1 |   56.09 |   41.76 |                   
  ...l-registry.ts |    6.66 |      100 |       0 |    6.66 | 6-32,35-53        
  config-utils.ts  |   93.33 |      100 |      75 |   93.33 | 21-26             
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  pairing.ts       |   26.31 |      100 |       0 |   26.31 | ...30,40-50,52-65 
  pidfile.ts       |   97.11 |    94.73 |     100 |   97.11 | 27-28,45          
  start.ts         |   31.94 |    53.84 |   71.42 |   31.94 | ...83-486,495-497 
  status.ts        |   17.85 |      100 |       0 |   17.85 | 15-26,32-76       
  stop.ts          |      20 |      100 |       0 |      20 | 14-48             
 ...nds/extensions |   87.25 |     89.3 |   85.24 |   87.25 |                   
  consent.ts       |   72.53 |       90 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |      100 |     100 |     100 |                   
  enable.ts        |     100 |      100 |     100 |     100 |                   
  install.ts       |   85.05 |    83.33 |      75 |   85.05 | ...05-208,211-220 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |    37.5 |      100 |   33.33 |    37.5 | 23-45,57-64,67-70 
  update.ts        |   96.29 |      100 |     100 |   96.29 | 101-105           
  utils.ts         |      75 |    53.84 |     100 |      75 | ...27-131,133-137 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.15 |    84.39 |   83.33 |   90.15 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   92.59 |    83.87 |      80 |   92.59 | ...62-164,180-181 
  reconnect.ts     |   78.73 |    66.66 |   85.71 |   78.73 | 42-55,168-190     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   11.57 |      100 |       0 |   11.57 |                   
  cleanup.ts       |   17.94 |      100 |       0 |   17.94 | ...01-106,108-109 
  deterministic.ts |   13.75 |      100 |       0 |   13.75 | ...22-738,740-741 
  fetch-pr.ts      |   11.36 |      100 |       0 |   11.36 | ...80-201,203-204 
  load-rules.ts    |   11.32 |      100 |       0 |   11.32 | ...41-153,155-156 
  pr-context.ts    |    6.22 |      100 |       0 |    6.22 | ...97-312,314-315 
  presubmit.ts     |    9.35 |      100 |       0 |    9.35 | ...62-287,289-290 
 ...nds/review/lib |      30 |      100 |       0 |      30 |                   
  gh.ts            |   22.58 |      100 |       0 |   22.58 | ...49,53-54,62-69 
  git.ts           |   22.72 |      100 |       0 |   22.72 | 15-18,29-39,43-44 
  paths.ts         |   52.94 |      100 |       0 |   52.94 | ...26,37-38,42-43 
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   93.48 |    86.83 |    94.5 |   93.48 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  config.ts        |    86.7 |    84.76 |   82.75 |    86.7 | ...2092,2094-2102 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   87.37 |    85.84 |   92.85 |   87.37 | ...43-544,550-551 
  hot-reload.ts    |     100 |    86.11 |     100 |     100 | 46,156,165,216    
  keyBindings.ts   |    97.1 |       50 |     100 |    97.1 | 212-215           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      92 |     90.9 |     100 |      92 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  settings.ts      |   88.05 |    88.06 |   89.65 |   88.05 | ...-966,1000-1006 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |     87.5 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   93.78 |    94.69 |     100 |   93.78 | ...43-344,380-391 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |   69.39 |    66.66 |   63.15 |   69.39 |                   
  ...tputBridge.ts |   69.48 |     67.3 |    64.7 |   69.48 | ...82-383,391-394 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   84.08 |       80 |    86.2 |   84.08 |                   
  index.ts         |   67.29 |    76.92 |      80 |   67.29 | ...70-271,294-299 
  languages.ts     |   96.92 |    86.66 |     100 |   96.92 | 134-135,167,184   
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   72.45 |    71.03 |   74.07 |   72.45 |                   
  session.ts       |   76.46 |    69.34 |   85.71 |   76.46 | ...32-833,842-852 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...90-591,594-595 
 ...active/control |   76.29 |    88.23 |      80 |   76.29 |                   
  ...rolContext.ts |    6.89 |        0 |       0 |    6.89 | 50-86             
  ...Dispatcher.ts |   91.66 |    91.83 |   88.88 |   91.66 | ...49-367,383,386 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |    26.7 |    37.93 |   35.48 |    26.7 |                   
  ...Controller.ts |   36.97 |       80 |      80 |   36.97 | ...15-117,127-210 
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   31.32 |     38.7 |      40 |   31.32 | ...68-577,592-597 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   21.97 |    28.57 |   27.27 |   21.97 | ...39-451,460-489 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |    98.1 |    94.18 |   95.23 |    98.1 |                   
  ...putAdapter.ts |   98.02 |    93.33 |   98.07 |   98.02 | ...1303,1398-1399 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 83-84,124-125     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   83.12 |    73.43 |    87.5 |   83.12 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   83.77 |    74.19 |   92.85 |   83.77 | ...05-306,317-320 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |   83.19 |    81.85 |   84.84 |   83.19 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.26 |    92.64 |     100 |   93.26 | ...07-308,311-313 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |       96 |     100 |     100 | 386               
  daemon-logger.ts |   98.24 |    86.95 |   96.29 |   98.24 | 119-120,196       
  ...s-provider.ts |   67.01 |    51.42 |     100 |   67.01 | ...40-245,278-286 
  daemon-status.ts |   97.78 |    82.71 |     100 |   97.78 | ...28,630-631,682 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   90.47 |    78.57 |     100 |   90.47 | ...20-123,189-196 
  event-bus.ts     |     100 |      100 |     100 |     100 |                   
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   95.34 |     89.4 |     100 |   95.34 | ...08,683,699,709 
  fast-path.ts     |   82.24 |    77.51 |      80 |   82.24 | ...95-496,504-507 
  ...ry-channel.ts |       0 |        0 |       0 |       0 | 1-14              
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...back-binds.ts |     100 |      100 |     100 |     100 |                   
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   90.37 |    87.77 |   93.75 |   90.37 | ...95-297,348-352 
  ...qwen-serve.ts |   78.49 |    81.98 |   54.87 |   78.49 | ...2338,2352-2355 
  server.ts        |   82.71 |     82.3 |   86.79 |   82.71 | ...5970,6036-6045 
  status.ts        |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   89.58 |       84 |     100 |   89.58 | ...50-153,186-189 
  ...ace-agents.ts |   62.47 |    70.34 |   90.47 |   62.47 | ...1346,1356-1366 
  ...ace-memory.ts |   87.13 |    78.46 |     100 |   87.13 | ...54-361,421-428 
  ...ers-status.ts |      97 |    78.94 |     100 |      97 | ...45,148,254-260 
 ...serve/acp-http |   70.64 |    71.29 |   93.93 |   70.64 |                   
  ...n-registry.ts |   89.19 |    82.43 |   93.33 |   89.19 | ...08,482,502-516 
  dispatch.ts      |   64.29 |    66.03 |     100 |   64.29 | ...2875,2949-2952 
  index.ts         |   75.95 |    69.79 |   92.85 |   75.95 | ...14,825,854-856 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  sse-stream.ts    |   93.91 |    87.87 |   84.61 |   93.91 | ...50-152,154-156 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,93,97-100   
 src/serve/auth    |   86.86 |    79.18 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |       80 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 src/serve/fs      |   85.31 |    81.43 |     100 |   85.31 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 201               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.82 |    77.08 |     100 |   77.82 | ...64,493-497,510 
  policy.ts        |   90.32 |    89.18 |     100 |   90.32 | 142-150           
  ...ile-system.ts |    84.3 |    79.27 |     100 |    84.3 | ...2061,2088-2089 
 src/serve/routes  |   79.09 |     76.9 |    89.7 |   79.09 |                   
  a2ui-action.ts   |     100 |     94.2 |     100 |     100 | 120,124,169,273   
  ...-file-read.ts |   94.41 |    76.92 |     100 |   94.41 | ...28-329,390-392 
  ...file-write.ts |    82.1 |    60.52 |     100 |    82.1 | ...42-244,247-249 
  ...ermissions.ts |   87.38 |    76.19 |     100 |   87.38 | ...05-106,132-133 
  ...e-settings.ts |   23.62 |      100 |      50 |   23.62 | ...13-226,233-330 
  ...tup-github.ts |   77.52 |    70.27 |   84.21 |   77.52 | ...87,309,352-353 
  ...pace-trust.ts |   76.84 |    72.22 |      50 |   76.84 | ...,63-64,117-118 
  ...pace-voice.ts |   87.09 |     82.6 |    90.9 |   87.09 | ...96,322-323,452 
 src/serve/voice   |   70.58 |    95.74 |   72.72 |   70.58 |                   
  ...ice-config.ts |   13.33 |      100 |       0 |   13.33 | 35-63,71-87       
  voice-ws.ts      |   78.03 |    95.74 |   84.21 |   78.03 | ...84,399,437-439 
 ...kspace-service |    85.4 |    83.68 |      92 |    85.4 |                   
  index.ts         |   84.86 |    83.33 |    90.9 |   84.86 | ...76-681,741-806 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   91.89 |    88.43 |   98.24 |   91.89 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 99-112            
  ...killLoader.ts |     100 |    93.33 |     100 |     100 | 48,67             
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   75.84 |    80.64 |   83.33 |   75.84 | ...10-211,277-278 
  ...mandLoader.ts |     100 |    97.14 |     100 |     100 | 66                
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  ...low-loader.ts |     100 |    96.29 |     100 |     100 | 88                
  setup-github.ts  |    90.5 |    81.81 |     100 |    90.5 | ...35-436,443-444 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.71 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   85.99 |    87.09 |     100 |   85.99 | ...68,275,329-343 
  ...e-settings.ts |     100 |    95.45 |     100 |     100 | 19                
  ...ranscriber.ts |   90.41 |       82 |   95.83 |   90.41 | ...29-631,634-636 
 ...ght/generators |    88.3 |    85.49 |   92.59 |    88.3 |                   
  DataProcessor.ts |   88.22 |    85.48 |      95 |   88.22 | ...1341,1345-1352 
  ...tGenerator.ts |   98.21 |    85.71 |     100 |   98.21 | 46                
  ...teRenderer.ts |   45.45 |      100 |       0 |   45.45 | 13-51             
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.35 |    84.84 |     100 |   97.35 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   80.53 |     74.6 |     100 |   80.53 |                   
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.01 |    83.33 |      80 |   94.01 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   69.03 |    70.08 |   61.11 |   69.03 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   70.14 |    65.32 |   57.14 |   70.14 | ...3594,4101-4105 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |   29.23 |      100 |       0 |   29.23 | 25-75             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   56.25 |    33.33 |      40 |   56.25 | ...30-231,236-241 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...96,401,409-411 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   58.45 |    65.94 |      50 |   58.45 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.03 |    70.37 |      56 |   60.03 | ...87,791,800,803 
  useAuth.ts       |    94.6 |    73.52 |     100 |    94.6 | ...21-222,241-247 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   78.85 |    81.27 |   87.57 |   78.85 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |   89.47 |    81.25 |     100 |   89.47 | 92-93,95-100      
  arenaCommand.ts  |   62.81 |    58.73 |   65.21 |   62.81 | ...90-595,680-688 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |   89.44 |    80.35 |     100 |   89.44 | ...81,106-111,190 
  clearCommand.ts  |   79.64 |       68 |     100 |   79.64 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   70.86 |    74.07 |      75 |   70.86 | ...,61-93,117-122 
  ...extCommand.ts |   65.58 |    68.25 |   84.61 |   65.58 | ...54-587,598-599 
  copyCommand.ts   |   98.49 |    95.78 |     100 |   98.49 | ...80,280,321,327 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |     87.5 |     100 |     100 | ...61,224-225,238 
  ...ryCommand.tsx |   81.84 |    86.11 |   91.66 |   81.84 | ...66-271,318-325 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |    50.3 |    48.14 |   69.23 |    50.3 | ...08,262-314,375 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   91.46 |    84.44 |      90 |   91.46 | ...87-190,202-205 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   84.33 |    72.72 |     100 |   84.33 | 68,82-87,89-94    
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   92.17 |    82.69 |     100 |   92.17 | ...39,159,168-178 
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   76.15 |    82.27 |   77.77 |   76.15 | ...44-349,403-408 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...berCommand.ts |      96 |       70 |     100 |      96 | 58,63             
  renameCommand.ts |   85.71 |    86.04 |     100 |   85.71 | ...02-209,216-221 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |    85.5 |    81.25 |     100 |    85.5 | 36-44,70          
  statsCommand.ts  |    90.6 |    77.95 |     100 |    90.6 | ...91-694,785-792 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.43 |      100 |      50 |    6.43 | 31-330            
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |   63.31 |    77.65 |   71.42 |   63.31 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   35.48 |      100 |       0 |   35.48 | 26-48             
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   16.27 |      100 |       0 |   16.27 | 19-58             
  ...TextInput.tsx |   88.36 |    88.57 |     100 |   88.36 | ...80-282,296-298 
  Composer.tsx     |   94.39 |    66.66 |     100 |   94.39 | ...-71,83,138,151 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  ...ification.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-577             
  DiffDialog.tsx   |   31.17 |    19.51 |   30.76 |   31.17 | ...07-712,722-735 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   76.87 |    52.08 |     100 |   76.87 | ...98-203,221-225 
  ...ngSpinner.tsx |   68.42 |       80 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   76.19 |    81.81 |     100 |   76.19 | 24-30,46-50       
  Header.tsx       |   98.62 |    94.28 |     100 |   98.62 | 162,164           
  Help.tsx         |   98.32 |       90 |     100 |   98.32 | ...24,381,447-448 
  ...emDisplay.tsx |   73.43 |    63.29 |     100 |   73.43 | ...37,440,443-449 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   81.07 |    80.12 |   77.77 |   81.07 | ...1976,2002,2054 
  ...Shortcuts.tsx |   20.87 |      100 |       0 |   20.87 | ...6,49-51,67-125 
  ...Indicator.tsx |   98.14 |    97.82 |     100 |   98.14 | 157-158           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   98.43 |    94.82 |   66.66 |   98.43 | 89,166-170        
  MemoryDialog.tsx |   64.76 |     77.9 |    62.5 |   64.76 | ...01,420,469-471 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   83.64 |    71.16 |     100 |   83.64 | ...74-690,747-751 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    84.21 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   68.27 |    71.66 |      75 |   68.27 | ...16-824,830-831 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   92.78 |    82.35 |      75 |   92.78 | ...5,77-79,93,124 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |       0 |        0 |       0 |       0 | 1-275             
  StatsDialog.tsx  |       0 |        0 |       0 |       0 | 1-238             
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |       0 |        0 |       0 |       0 | 1-258             
  ...atmapView.tsx |       0 |        0 |       0 |       0 | 1-107             
  ...essionTab.tsx |       0 |        0 |       0 |       0 | 1-215             
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.33 |    88.23 |     100 |   96.33 | 137-140           
  ...nsDisplay.tsx |   91.37 |    79.41 |     100 |   91.37 | ...70,173,200-202 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  ...ingViewer.tsx |   12.61 |      100 |       0 |   12.61 | 32-140            
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    81.81 |     100 |     100 | 71-86             
  ...ification.tsx |       0 |        0 |       0 |       0 | 1-22              
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   91.42 |    64.28 |     100 |   91.42 | 15,21,24          
  ...s-helpers.tsx |       0 |        0 |       0 |       0 | 1-102             
 ...nts/agent-view |   53.71 |    70.87 |   42.85 |   53.71 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   64.78 |    29.41 |   33.33 |   64.78 | ...51,269,277-279 
  AgentFooter.tsx  |   17.07 |      100 |       0 |   17.07 | 28-66             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |   42.38 |    68.69 |   73.68 |   42.38 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-164             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |   78.59 |    78.07 |   88.37 |   78.59 |                   
  ...sksDialog.tsx |   73.81 |    74.32 |   79.16 |   73.81 | ...1546,1568-1574 
  ...TasksPill.tsx |   67.03 |     86.2 |     100 |   67.03 | ...02-122,130-138 
  ...gentPanel.tsx |   97.43 |    85.39 |     100 |   97.43 | 121,436-440       
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.58 |    78.18 |   83.33 |   84.58 |                   
  ...gerDialog.tsx |   82.46 |    77.77 |     100 |   82.46 | ...89,191-198,258 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.15 |    84.74 |   58.82 |   46.15 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.13 |    88.09 |   66.66 |   75.13 | ...52,173,202-208 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   66.18 |    67.65 |   66.66 |   66.18 |                   
  DiscoverTab.tsx  |   57.21 |     63.2 |   55.55 |   57.21 | ...98,661-665,669 
  InstalledTab.tsx |   71.62 |    68.65 |   83.33 |   71.62 | ...67,772-773,810 
  SourcesTab.tsx   |   69.25 |     70.4 |   66.66 |   69.25 | ...16,535,607-619 
 ...tensions/views |   23.73 |    44.82 |       5 |   23.73 |                   
  ...tionsView.tsx |    6.02 |      100 |       0 |    6.02 | 52-65,68-368      
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...97-404,407-419 
  ...etailView.tsx |    9.56 |      100 |       0 |    9.56 | 40-67,70-158      
 ...mponents/hooks |   86.85 |    81.37 |   91.89 |   86.85 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   14.85 |    88.23 |   71.42 |   14.85 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |       0 |        0 |       0 |       0 | 1-925             
  ...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         |       0 |        0 |       0 |       0 | 1-24              
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   52.64 |    72.37 |   57.14 |   52.64 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-88              
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |    64.8 |    62.26 |   33.33 |    64.8 | ...75-284,295-317 
  ...rListStep.tsx |   82.05 |    75.55 |     100 |   82.05 | ...63,169,174-179 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   85.46 |     81.3 |   78.82 |   85.46 |                   
  ...ionDialog.tsx |   80.84 |     77.6 |    62.5 |   80.84 | ...98,516,534-536 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    91.83 |     100 |     100 | 27,31,33,35       
  ...onMessage.tsx |   91.93 |    82.35 |     100 |   91.93 | 57-59,61,63       
  ...nMessages.tsx |   87.33 |    76.31 |   91.66 |   87.33 | ...44-350,407-413 
  DiffRenderer.tsx |   93.19 |    86.17 |     100 |   93.19 | ...09,237-238,304 
  ...tsDisplay.tsx |   97.82 |    77.27 |     100 |   97.82 | 87,89             
  ...usMessage.tsx |   76.31 |     42.1 |   66.66 |   76.31 | ...99,101,124,155 
  ...tsDisplay.tsx |   95.05 |    87.69 |     100 |   95.05 | ...32,134,167-172 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   16.66 |      100 |       0 |   16.66 | 22-38             
  ...sMessages.tsx |   55.67 |       40 |   28.57 |   55.67 | ...20-125,133-145 
  ...ryMessage.tsx |   14.28 |      100 |       0 |   14.28 | 23-62             
  ...onMessage.tsx |   82.31 |    74.02 |   33.33 |   82.31 | ...69-471,478-480 
  ...upMessage.tsx |   96.04 |    93.91 |     100 |   96.04 | ...76,265-271,364 
  ToolMessage.tsx  |   88.72 |    76.66 |    92.3 |   88.72 | ...66-771,798-800 
 ...ponents/shared |   85.06 |    81.42 |    95.5 |   85.06 |                   
  ...ctionList.tsx |     100 |      100 |     100 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  MaxSizedBox.tsx  |   83.01 |    86.25 |   88.88 |   83.01 | ...12-513,618-619 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   77.22 |    85.71 |     100 |   77.22 | 45-63,70-73       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |    88.7 |    83.64 |      90 |    88.7 | ...14-515,745-773 
  text-buffer.ts   |   85.94 |    81.73 |   97.91 |   85.94 | ...2651,2749-2750 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-694             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.04 |    53.19 |    37.5 |   14.04 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.42 |    59.52 |     100 |   35.42 | ...20-432,437-439 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   70.21 |    67.32 |    64.7 |   70.21 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   87.87 |    73.68 |     100 |   87.87 | 69-76             
  McpStatus.tsx    |   89.49 |    60.52 |     100 |   89.49 | ...72,175-177,262 
  SkillsList.tsx   |   27.27 |      100 |       0 |   27.27 | 18-35             
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   81.55 |    78.24 |   83.07 |   81.55 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   92.45 |    62.79 |      50 |   92.45 | ...69-270,272-276 
  ...deContext.tsx |   88.88 |      100 |       0 |   88.88 | 21                
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   81.86 |    81.65 |     100 |   81.86 | ...1257,1262-1264 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   78.68 |    73.77 |   91.66 |   78.68 | ...86-389,398-401 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...erContext.tsx |     100 |      100 |      50 |     100 |                   
  ...edContext.tsx |     100 |      100 |     100 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 141-142           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 224-225           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
 src/ui/daemon     |   90.65 |    73.61 |   95.45 |   90.65 |                   
  ...ui-adapter.ts |   90.65 |    73.61 |   95.45 |   90.65 | ...44,762-763,849 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   83.57 |    81.34 |   88.13 |   83.57 |                   
  ...dProcessor.ts |   88.11 |    82.81 |     100 |   88.11 | ...68-569,575-580 
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...86-287,292-293 
  ...dProcessor.ts |   84.59 |    64.11 |   84.21 |   84.59 | ...1105,1126-1130 
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      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 |   90.43 |     87.9 |     100 |   90.43 | ...15-422,462-471 
  ...ifications.ts |   86.91 |    96.29 |     100 |   86.91 | 116-130           
  ...tIndicator.ts |   83.49 |    70.96 |     100 |   83.49 | ...58,166,168-176 
  ...waySummary.ts |   96.22 |    69.69 |     100 |   96.22 | 125-127,169       
  ...ndTaskView.ts |   93.84 |    74.46 |     100 |   93.84 | ...25-129,218,224 
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   93.19 |    71.05 |     100 |   93.19 | ...37,183,256-259 
  ...ompletion.tsx |   95.36 |    82.81 |     100 |   95.36 | ...32-233,235-236 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   94.11 |    89.65 |     100 |   94.11 | ...32-133,137-138 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   77.27 |       50 |     100 |   77.27 | ...2,75-79,93-101 
  ...eteCommand.ts |   78.53 |    88.57 |     100 |   78.53 | ...96-104,112-113 
  ...ialogClose.ts |   36.76 |    10.52 |     100 |   36.76 | ...75-181,188-193 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.64 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |    93.5 |     92.3 |     100 |    93.5 | ...87-291,304-310 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   83.56 |    80.09 |      95 |   83.56 | ...3272,3355-3363 
  ...BranchName.ts |     100 |    91.66 |     100 |     100 | 30                
  ...oryManager.ts |   97.94 |    98.24 |     100 |   97.94 | 139-142           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |       0 |        0 |       0 |       0 | 1-90              
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       75 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.07 |    85.29 |     100 |   93.07 | ...23-126,138-139 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...delCommand.ts |     100 |     87.5 |     100 |     100 | 29                
  ...ouseEvents.ts |   91.93 |       95 |      75 |   91.93 | 29-33             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |   86.95 |    77.41 |   91.66 |   86.95 | ...70,311-323,371 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   88.54 |    91.83 |     100 |   88.54 | ...73-278,381-391 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...tleRepaint.ts |     100 |      100 |     100 |     100 |                   
  ...umeCommand.ts |   93.47 |       68 |     100 |   93.47 | ...17,152,193-198 
  ...ompletion.tsx |   90.59 |    83.33 |     100 |   90.59 | ...01,104,137-140 
  ...ectionList.ts |   97.05 |    96.11 |     100 |   97.05 | ...90-191,245-248 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-73              
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |    97.1 |       93 |     100 |    97.1 | ...70-374,475-482 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   53.06 |       50 |   66.66 |   53.06 | ...53,61-68,79-85 
  ...rminalSize.ts |   76.19 |      100 |      50 |   76.19 | 21-25             
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |      100 |     100 |     100 |                   
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    90.9 |    90.62 |     100 |    90.9 |                   
  ...AppLayout.tsx |   90.72 |       90 |     100 |   90.72 | 57-59,101-106     
  ...AppLayout.tsx |   91.17 |    91.66 |     100 |   91.17 | 70-75             
 src/ui/models     |   80.24 |    79.16 |   71.42 |   80.24 |                   
  ...ableModels.ts |   80.24 |    79.16 |   71.42 |   80.24 | ...,61-71,123-125 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/state      |   94.91 |    81.81 |     100 |   94.91 |                   
  extensions.ts    |   94.91 |    81.81 |     100 |   94.91 | 68-69,88          
 src/ui/themes     |    98.5 |    73.06 |     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.33 |     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      |   83.84 |    83.35 |   93.42 |   83.84 |                   
  ...Colorizer.tsx |   80.42 |    85.41 |     100 |   80.42 | ...00-201,298-324 
  ...nRenderer.tsx |   68.83 |    70.14 |      50 |   68.83 | ...52-254,274-293 
  ...wnDisplay.tsx |   86.01 |    87.66 |     100 |   86.01 | ...87,704,729-754 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.08 |    80.45 |      95 |   92.08 | ...76-679,723-728 
  ...odeDisplay.ts |   96.55 |     90.9 |     100 |   96.55 | 34                
  asciiCharts.ts   |   96.77 |    87.62 |     100 |   96.77 | 173-180,281       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   51.92 |    72.72 |   91.66 |   51.92 | ...21,624-633,636 
  commandUtils.ts  |      96 |    88.77 |     100 |      96 | ...72,174-175,302 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   90.38 |    73.91 |     100 |   90.38 | 23,25,29,31,33    
  formatters.ts    |    95.4 |    98.38 |     100 |    95.4 | 123-126           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |    96.77 |     100 |     100 | 43                
  historyUtils.ts  |   95.55 |    95.08 |     100 |   95.55 | 95-98             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |    8.23 |      100 |       0 |    8.23 | ...31-132,135-136 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   90.21 |    85.71 |     100 |   90.21 | ...,91-95,107-108 
  ...t-position.ts |     100 |      100 |     100 |     100 |                   
  ...ToolGroups.ts |   98.65 |    96.72 |     100 |   98.65 | 48-49             
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.14 |    73.77 |     100 |   92.14 | ...29,136,140-143 
  osc8.ts          |   94.84 |    88.74 |     100 |   94.84 | ...57,442,446-447 
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |   99.02 |    97.56 |     100 |   99.02 | 106               
  ...storyUtils.ts |   66.99 |    75.96 |   93.33 |   66.99 | ...41-463,584-585 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.61 |    94.89 |   92.85 |   97.61 | ...50-251,386-387 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   89.33 |    93.47 |     100 |   89.33 | ...,66-78,180-181 
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 30-42             
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |      57 |     40.8 |   79.41 |      57 |                   
  collect.ts       |   55.92 |    50.58 |   86.36 |   55.92 | ...25-640,642-647 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   58.11 |    20.51 |      80 |   58.11 | ...13-314,328-363 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |      40 |      100 |       0 |      40 | 11-13             
 ...ort/formatters |    3.38 |      100 |       0 |    3.38 |                   
  html.ts          |    9.61 |      100 |       0 |    9.61 | ...28,34-76,82-84 
  json.ts          |      50 |      100 |       0 |      50 | 14-15             
  jsonl.ts         |     3.5 |      100 |       0 |     3.5 | 14-76             
  markdown.ts      |    0.94 |      100 |       0 |    0.94 | 13-295            
 src/ui/voice      |   81.12 |    72.76 |    79.1 |   81.12 |                   
  ...d-recorder.ts |     6.2 |        0 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.14 |     64.7 |   92.85 |   91.14 | ...76,282,292-295 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |     100 |    88.88 |     100 |     100 | 18                
  ...am-session.ts |   87.45 |    63.33 |   81.81 |   87.45 | ...03,320-322,339 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   73.83 |    89.58 |   91.04 |   73.83 |                   
  acpModelUtils.ts |   94.44 |     92.3 |     100 |   94.44 | 44,68-69,73-74    
  apiPreconnect.ts |   96.72 |    97.14 |     100 |   96.72 | 165-168           
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |   82.53 |    93.33 |      80 |   82.53 | 74,105-115        
  commands.ts      |     100 |      100 |     100 |     100 |                   
  commentJson.ts   |   90.51 |    91.89 |     100 |   90.51 | 67-76,116         
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.38 |    71.83 |   88.88 |   70.38 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   90.85 |    96.36 |    92.3 |   90.85 | 69-70,298-310     
  events.ts        |     100 |      100 |     100 |     100 |                   
  gitUtils.ts      |    92.7 |    84.09 |     100 |    92.7 | ...07-110,158-161 
  ...AutoUpdate.ts |    92.2 |    95.23 |   88.88 |    92.2 | 130-141           
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.71 |    94.18 |     100 |   97.71 | ...57,274-275,320 
  languageUtils.ts |   98.47 |    97.67 |     100 |   98.47 | 153-154           
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   96.04 |     94.4 |     100 |   96.04 | ...7-78,83-84,324 
  ...iveHelpers.ts |   96.93 |    93.84 |     100 |   96.93 | ...15-416,514,527 
  osc.ts           |    97.5 |      100 |   88.88 |    97.5 | 195-196           
  package.ts       |   88.88 |       80 |     100 |   88.88 | 31-32             
  processUtils.ts  |     100 |      100 |     100 |     100 |                   
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   93.22 |    81.25 |     100 |   93.22 | 65-67,80          
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |       0 |        0 |       0 |       0 | 1-1042            
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.51 |    91.85 |   89.74 |   82.51 | ...76-694,701-709 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   27.55 |    76.11 |   45.83 |   27.55 | ...44-845,848-867 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       60 |     100 |     100 | 23,32             
  systemInfo.ts    |   95.12 |    89.06 |     100 |   95.12 | ...43-244,249-253 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   94.11 |    83.33 |     100 |   94.11 | 13                
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |       50 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   91.63 |    91.02 |      95 |   91.63 |                   
  cleanup.ts       |   95.77 |    95.83 |     100 |   95.77 | 70-72             
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   91.91 |    90.47 |    87.5 |   91.91 | 58-62,73,131-135  
  throttledOnce.ts |   86.66 |     86.2 |     100 |   86.66 | ...99,105,137-138 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   84.11 |    84.54 |   85.33 |   84.11 |                   
 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        |   89.65 |    81.31 |   94.65 |   89.65 |                   
  ...transcript.ts |    92.3 |    85.93 |     100 |    92.3 | ...05,324-325,456 
  ...ent-resume.ts |   83.33 |    71.42 |   79.41 |   83.33 | ...1260-1264,1267 
  ...ound-tasks.ts |   96.83 |    89.13 |     100 |   96.83 | ...1170,1190-1193 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...n-registry.ts |   95.65 |    89.28 |     100 |   95.65 | ...12-413,485-489 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.54 |    66.87 |   78.72 |   76.54 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.37 |    63.37 |   78.26 |   75.37 | ...1860,1866-1867 
  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 |   76.47 |    86.27 |   73.75 |   76.47 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   92.06 |    91.04 |      90 |   92.06 | ...95,250-270,329 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   88.03 |     84.9 |   82.21 |   88.03 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |    79.2 |    74.69 |   65.95 |    79.2 | ...1834,1861-1908 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   87.93 |    79.06 |   63.63 |   87.93 | ...00-401,404-405 
  ...nteractive.ts |   79.52 |       80 |   74.07 |   79.52 | ...83,485-488,491 
  ...statistics.ts |   98.19 |    82.35 |     100 |   98.19 | 127,151,192,225   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.57 |    87.64 |   82.35 |   91.57 | ...1739,1788-1791 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...ow-sandbox.ts |   96.87 |    94.51 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |   97.87 |    82.69 |     100 |   97.87 | 136-137,234       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   80.31 |    83.19 |    86.5 |   80.31 |                   
  TeamManager.ts   |   67.11 |    76.25 |   74.41 |   67.11 | ...1433,1456-1457 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.47 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...37-141,148-152 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    93.38 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    77.77 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   79.66 |    84.58 |   66.38 |   79.66 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   78.14 |    83.81 |    62.7 |   78.14 | ...5507,5512-5513 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.63 |    91.86 |   89.58 |   94.63 | ...15-416,419-420 
 ...nfirmation-bus |   98.29 |    97.14 |     100 |   98.29 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   88.92 |    84.29 |   92.14 |   88.92 |                   
  baseLlmClient.ts |   86.28 |    78.43 |   77.77 |   86.28 | ...66,568-578,587 
  client.ts        |   87.62 |    81.01 |      90 |   87.62 | ...2616,2711-2712 
  ...tGenerator.ts |   88.07 |       75 |     100 |   88.07 | ...79-383,391-395 
  ...lScheduler.ts |   88.36 |    82.62 |    96.2 |   88.36 | ...4262,4290-4301 
  geminiChat.ts    |   89.04 |    87.24 |      95 |   89.04 | ...3253,3320-3321 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |    95.83 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   92.59 |       75 |      50 |   92.59 | 41-42             
  ...on-helpers.ts |   86.72 |    73.68 |     100 |   86.72 | ...00-201,215-224 
  ...issionFlow.ts |   98.78 |       96 |     100 |   98.78 | 93                
  prompts.ts       |   88.93 |    87.87 |   72.72 |   88.93 | ...-910,1113-1114 
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    89.28 |     100 |     100 | 30,65-66          
  ...allIdUtils.ts |   98.23 |     92.1 |     100 |   98.23 | 36,45             
  ...okTriggers.ts |   99.43 |     91.5 |     100 |   99.43 | 175,186           
  turn.ts          |   97.22 |    88.88 |     100 |   97.22 | ...96,509-510,556 
 ...ntentGenerator |   95.04 |    82.54 |      94 |   95.04 |                   
  ...tGenerator.ts |   96.59 |    84.07 |   92.85 |   96.59 | ...,973,1001-1003 
  converter.ts     |   94.51 |    80.72 |     100 |   94.51 | ...06-607,617,823 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.53 |    71.64 |   93.33 |   91.53 |                   
  ...tGenerator.ts |      90 |    70.96 |   92.85 |      90 | ...80-286,304-305 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   94.58 |    84.69 |    92.1 |   94.58 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   94.48 |    83.39 |   91.66 |   94.48 | ...1108-1109,1137 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.63 |    85.05 |   93.97 |   88.63 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |    87.7 |    82.36 |   96.15 |    87.7 | ...1508,1677-1692 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   58.33 |    71.42 |      50 |   58.33 | ...70,73-77,85-89 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.51 |     88.6 |     100 |   95.51 | ...07-708,716,784 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |    90.2 |    87.65 |     100 |    90.2 | ...39-343,373-374 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |    97.1 |    90.49 |   96.07 |    97.1 |                   
  dashscope.ts     |   97.78 |     92.3 |   94.44 |   97.78 | ...15-316,458-459 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |    97.5 |    96.55 |   88.88 |    97.5 | 123-124,197       
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
 src/extension     |   77.79 |    79.89 |   84.61 |   77.79 |                   
  ...-converter.ts |   78.29 |    70.87 |     100 |   78.29 | ...1108,1153-1154 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |    73.8 |       75 |     100 |    73.8 | 44-54             
  ...ionManager.ts |   60.68 |    71.42 |   55.17 |   60.68 | ...1613,1638-1639 
  ...references.ts |     100 |    89.58 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |   92.65 |    91.89 |     100 |   92.65 | ...28-232,312-313 
  ...-converter.ts |    75.9 |    83.33 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   84.71 |     85.4 |     100 |   84.71 | ...61-662,670-671 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |    95.83 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   87.11 |    84.28 |     100 |   87.11 | ...44,348-354,429 
  npm.ts           |   74.67 |    71.64 |     100 |   74.67 | ...19-421,428-432 
  override.ts      |   94.11 |    88.88 |     100 |   94.11 | 63-64,81-82       
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   93.96 |    83.14 |     100 |   93.96 | ...35-341,362-363 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.75 |    83.33 |     100 |   88.75 | ...28-231,234-237 
 src/followup      |   76.02 |    74.12 |   90.62 |   76.02 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   63.01 |    40.29 |   71.42 |   63.01 | ...73-574,577-582 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 95                
  ...nGenerator.ts |   67.96 |    77.58 |      80 |   67.96 | ...67-218,297-299 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   89.57 |    83.57 |   94.44 |   89.57 |                   
  ...eGoalStore.ts |    85.1 |    95.45 |   84.61 |    85.1 | ...63-166,174-182 
  goalHook.ts      |   97.26 |    91.66 |     100 |   97.26 | 100-105           
  goalJudge.ts     |   84.33 |    74.28 |     100 |   84.33 | ...57-358,366-368 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   86.94 |    85.48 |   88.05 |   86.94 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.35 |    90.69 |     100 |   96.35 | ...00-301,382,384 
  ...entHandler.ts |   95.32 |    85.05 |   94.11 |   95.32 | ...71,928-929,939 
  hookPlanner.ts   |   86.29 |    83.33 |   85.71 |   86.29 | ...15-219,226-237 
  hookRegistry.ts  |   91.48 |    84.61 |     100 |   91.48 | ...97,416,420,424 
  hookRunner.ts    |   62.42 |    72.04 |   66.66 |   62.42 | ...64-765,774-775 
  hookSystem.ts    |      87 |      100 |   68.88 |      87 | ...15-716,722-723 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   96.37 |     90.9 |      90 |   96.37 | 342-350,424-425   
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   96.66 |    91.66 |     100 |   96.66 | ...90,209-210,223 
  ssrfGuard.ts     |   77.22 |    85.36 |     100 |   77.22 | ...57,261-267,273 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   92.83 |       94 |    87.5 |   92.83 | ...87-488,573-577 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   75.63 |    83.78 |   78.33 |   75.63 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |    66.3 |    82.26 |   66.66 |    66.3 | ...9-970,999-1007 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   43.47 |     58.9 |   52.48 |   43.47 |                   
  ...nfigLoader.ts |   78.28 |     64.7 |      95 |   78.28 | ...35-437,441-447 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   25.31 |    62.06 |   41.66 |   25.31 | ...85-704,710-740 
  ...eLspClient.ts |   32.77 |       80 |   17.64 |   32.77 | ...84-288,294-295 
  ...LspService.ts |   51.85 |    65.98 |   68.57 |   51.85 | ...1339,1399-1409 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |   82.39 |    77.73 |   78.33 |   82.39 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.52 |    58.06 |     100 |   79.52 | ...33-940,947-949 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.24 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.27 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   75.01 |    78.14 |    73.5 |   75.01 |                   
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |      66 |    73.33 |      50 |      66 | 51,108-149        
  ...entPlanner.ts |   57.84 |    72.72 |   33.33 |   57.84 | ...35,140-147,152 
  entries.ts       |   63.77 |    79.16 |      50 |   63.77 | ...72-180,183-189 
  extract.ts       |   91.36 |    72.41 |     100 |   91.36 | ...99,118-121,189 
  ...entPlanner.ts |   67.59 |     73.8 |      50 |   67.59 | ...31,240-243,415 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   46.21 |    61.53 |   44.44 |   46.21 | ...06,213,216-348 
  indexer.ts       |    86.3 |       50 |     100 |    86.3 | ...56,62-63,75-76 
  manager.ts       |    78.5 |    82.19 |   77.77 |    78.5 | ...1470,1483-1485 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   79.06 |    95.12 |     100 |   79.06 | 32-33,49-86       
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   94.87 |    78.57 |     100 |   94.87 | ...63,166,304-305 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  scan.ts          |   92.92 |    78.26 |     100 |   92.92 | ...51-52,62,90-91 
  ...entPlanner.ts |   58.33 |    67.34 |   56.25 |   58.33 | ...61-282,358-403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   93.33 |    81.25 |     100 |   93.33 | ...,94-95,119-120 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   79.38 |    81.03 |   81.81 |   79.38 | ...58-272,286-291 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   90.54 |    87.95 |   89.74 |   90.54 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   90.24 |    91.42 |     100 |   90.24 | 142,148,151-160   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.66 |    92.75 |     100 |   98.66 | 163,325,331       
  modelRegistry.ts |     100 |    98.91 |     100 |     100 | 177               
  modelsConfig.ts  |   86.79 |    86.23 |   85.36 |   86.79 | ...1344,1373-1374 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   82.91 |     91.3 |   69.56 |   82.91 |                   
  autoMode.ts      |   97.74 |       94 |     100 |   97.74 | ...29,557-564,673 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.44 |     100 |      94 | 158-165,385-389   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   84.91 |     89.1 |      80 |   84.91 | ...1026,1132-1136 
  rule-parser.ts   |   97.42 |    93.82 |     100 |   97.42 | ...-890,1039-1041 
  ...-semantics.ts |   70.36 |    91.07 |   46.66 |   70.36 | ...2237,2300-2303 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 219               
 src/plan-gate     |   76.16 |    91.42 |      80 |   76.16 |                   
  ...viewAgents.ts |   52.28 |    88.46 |   66.66 |   52.28 | ...24-220,242-243 
  ...provalGate.ts |   92.47 |    92.85 |   85.71 |   92.47 | ...86-187,268-274 
  state.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   80.44 |    75.28 |   68.75 |   80.44 |                   
  all-providers.ts |   69.23 |      100 |       0 |   69.23 | 71-72,76-82,86-92 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   98.93 |    87.71 |     100 |   98.93 | 286-287           
  ...der-config.ts |    72.6 |    69.49 |   73.91 |    72.6 | ...94-495,502-511 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.56 |    89.28 |   55.55 |   97.56 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |    85.3 |    78.57 |   95.89 |    85.3 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.55 |    73.24 |   90.62 |   82.55 | ...1183-1199,1229 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   87.84 |    84.89 |    93.9 |   87.84 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.35 |    85.34 |     100 |   97.35 | ...94,117,417-418 
  ...ionService.ts |   96.46 |    94.44 |     100 |   96.46 | ...41,657,786-794 
  ...ingService.ts |   84.06 |    82.35 |   81.39 |   84.06 | ...1459,1474-1475 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |   99.52 |    96.42 |     100 |   99.52 | 98                
  cronScheduler.ts |   95.09 |    90.18 |     100 |   95.09 | ...-940,1239-1240 
  cronTasksFile.ts |   95.03 |    89.47 |     100 |   95.03 | ...44-147,172-173 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   82.07 |       92 |      80 |   82.07 | ...43,149-150,155 
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   91.27 |    82.69 |    90.9 |   91.27 | ...94,196,294-301 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    69.4 |    68.82 |   93.33 |    69.4 | ...2064,2092-2093 
  ...ionService.ts |   99.07 |    98.48 |     100 |   99.07 | 462-463,510-511   
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   96.06 |    91.48 |   96.96 |   96.06 | ...49,850,864-866 
  ...orRegistry.ts |   97.27 |    91.22 |     100 |   97.27 | ...50-451,606-607 
  ...ttachments.ts |   97.24 |    90.39 |     100 |   97.24 | ...08,646,661-662 
  sessionRecap.ts  |     9.7 |      100 |       0 |     9.7 | 42-172            
  ...ionService.ts |   86.32 |    78.79 |   94.87 |   86.32 | ...1592,1662-1682 
  sessionTitle.ts  |   93.87 |    71.15 |     100 |   93.87 | ...32-235,266-267 
  ...ionService.ts |   82.58 |    78.02 |   90.62 |   82.58 | ...2173,2179-2184 
  ...pInhibitor.ts |   97.34 |    92.68 |     100 |   97.34 | ...28,167,361-362 
  ...Estimation.ts |     100 |    86.66 |     100 |     100 | 96-97             
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...oryService.ts |   89.03 |    65.38 |     100 |   89.03 | ...23-325,330-331 
  ...reeCleanup.ts |   14.56 |      100 |   33.33 |   14.56 | 58-185            
  ...ionService.ts |   87.98 |     86.6 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.35 |    95.65 |     100 |   99.35 |                   
  microcompact.ts  |   99.35 |    95.65 |     100 |   99.35 | 224-225,618       
 ...s/visionBridge |   96.73 |    93.97 |   93.75 |   96.73 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |      96 |     90.9 |      90 |      96 | ...07,208,290,373 
 src/skills        |   88.18 |    86.66 |   90.16 |   88.18 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |     93.1 |     100 |     100 | 93,112            
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   83.39 |    81.42 |   82.35 |   83.39 | ...1199,1206-1210 
  skill-paths.ts   |   89.65 |    86.95 |     100 |   89.65 | ...11-112,117-118 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |       98 |     100 |   97.91 | 277-278           
 src/subagents     |   85.84 |    85.55 |   94.33 |   85.84 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |    81.2 |    79.93 |   91.17 |    81.2 | ...1432,1509-1510 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   78.88 |       87 |    80.8 |   78.88 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   98.96 |    79.48 |     100 |   98.96 | 169,183           
  ...on-tracing.ts |   74.55 |    73.21 |   70.58 |   74.55 | ...95,336-338,354 
  ...attributes.ts |   97.47 |    93.15 |     100 |   97.47 | 39-44             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   52.49 |    66.66 |   59.18 |   52.49 | ...1305,1322-1342 
  metrics.ts       |   76.07 |    78.57 |   78.94 |   76.07 | ...1021,1024-1035 
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  sdk.ts           |   86.75 |     88.4 |   66.66 |   86.75 | ...17-621,659-681 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.04 |    88.07 |   96.55 |   90.04 | ...1504,1535-1538 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   78.73 |    85.27 |   83.54 |   78.73 | ...1293,1297-1304 
  uiTelemetry.ts   |   93.07 |    92.85 |   83.33 |   93.07 | ...62,290,410-411 
 ...ry/qwen-logger |   68.44 |    80.61 |   65.51 |   68.44 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   68.44 |    80.41 |   64.91 |   68.44 | ...1078,1116-1117 
 src/test-utils    |   93.44 |    96.07 |   77.77 |   93.44 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   91.71 |    97.29 |   74.19 |   91.71 | ...54,218-219,232 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   83.07 |     82.7 |   87.53 |   83.07 |                   
  ...erQuestion.ts |   90.74 |    82.43 |    92.3 |   90.74 | ...23-424,431-432 
  cron-create.ts   |   88.69 |    94.73 |   66.66 |   88.69 | ...,45-46,183-191 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.16 |    93.75 |    87.5 |   98.16 | 50-51             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |   80.82 |    83.48 |      75 |   80.82 | ...08-709,819-869 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |   81.08 |    66.66 |   85.71 |   81.08 | ...,74-79,112-126 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |   82.53 |    77.19 |     100 |   82.53 | ...91-394,426-429 
  glob.ts          |   95.92 |    87.69 |    92.3 |   95.92 | ...16,172,303,306 
  grep.ts          |   83.09 |    86.66 |   80.95 |   83.09 | ...60-661,711-712 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  loop-wakeup.ts   |   99.24 |    92.85 |     100 |   99.24 | 44                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.77 |    60.09 |   90.32 |   72.77 | ...1211,1213-1214 
  ...nt-manager.ts |   81.09 |    79.55 |    85.1 |   81.09 | ...3135,3137-3138 
  mcp-client.ts    |   75.11 |    82.64 |      85 |   75.11 | ...1900,1904-1907 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   91.43 |     89.9 |   96.66 |   91.43 | ...72-673,723-724 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 102,109           
  monitor.ts       |   91.65 |    84.05 |   88.46 |   91.65 | ...87,600,796-801 
  notebook-edit.ts |   85.11 |    76.42 |   81.25 |   85.11 | ...54-870,916-917 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    89.74 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   94.79 |    90.32 |   81.81 |   94.79 | ...04,307,390-391 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ripGrep.ts       |   95.87 |     88.4 |   94.73 |   95.87 | ...56-657,663-664 
  ...-transport.ts |    6.34 |        0 |       0 |    6.34 | 47-145            
  send-message.ts  |   81.39 |    88.88 |    62.5 |   81.39 | ...22-228,311-319 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   76.79 |    81.58 |   91.11 |   76.79 | ...4718,4781-4782 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |    90.2 |     93.1 |   88.88 |    90.2 | ...64,468,497-519 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |   93.85 |     92.3 |   81.81 |   93.85 | 41-45,59-60,91    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   80.67 |       78 |    92.3 |   80.67 | ...75-383,415-426 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  todoWrite.ts     |   89.27 |    82.05 |   92.85 |   89.27 | ...50-555,577-578 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   76.04 |     76.1 |   81.39 |   76.04 | ...62-863,871-872 
  tool-search.ts   |   92.35 |    85.84 |    92.3 |   92.35 | ...08-213,320-329 
  tools.ts         |   92.36 |    90.74 |   90.47 |   92.36 | ...99-500,516-522 
  web-fetch.ts     |   90.12 |    85.71 |   92.85 |   90.12 | ...11-312,326-327 
  write-file.ts    |   82.65 |    80.45 |   84.61 |   82.65 | ...65-668,696-731 
 src/tools/agent   |   80.69 |    83.58 |      80 |   80.69 |                   
  agent.ts         |   80.62 |    83.71 |   79.51 |   80.62 | ...3100,3127-3190 
  fork-subagent.ts |   82.35 |    77.77 |   85.71 |   82.35 | 83-101,133-134    
 ...tools/artifact |   95.58 |    91.01 |   88.37 |   95.58 |                   
  artifact-tool.ts |   90.23 |    81.39 |   69.23 |   90.23 | ...81-282,290-293 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.05 |    81.35 |   75.36 |   90.05 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   73.22 |    89.65 |   64.28 |   73.22 | ...70-172,233-242 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |   96.29 |     85.5 |     100 |   96.29 | 75-76,184,251-257 
 ...tools/workflow |   87.46 |    79.41 |   85.71 |   87.46 |                   
  workflow.ts      |   87.46 |    79.41 |   85.71 |   87.46 | ...51-652,664-667 
 src/utils         |   90.32 |    88.72 |   95.06 |   90.32 |                   
  LruCache.ts      |       0 |        0 |       0 |       0 | 1-41              
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.76 |    93.26 |     100 |   94.76 | ...30-531,634-638 
  bareMode.ts      |   27.27 |      100 |       0 |   27.27 | 9-15,18-19        
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.11 |    89.47 |     100 |   91.11 | ...46-147,154-155 
  cronDisplay.ts   |     100 |    91.66 |     100 |     100 | 15,43,57          
  cronParser.ts    |   95.34 |     93.1 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.42 |    94.11 |   88.23 |   96.42 | 185-189           
  editHelper.ts    |   93.63 |    83.52 |     100 |   93.63 | ...28-429,463-464 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.78 |    89.13 |      95 |   96.78 | ...51-252,257,403 
  errorParsing.ts  |    97.7 |    97.05 |     100 |    97.7 | 72-73             
  ...rReporting.ts |   88.46 |       90 |     100 |   88.46 | 69-74             
  errors.ts        |   73.14 |    79.22 |   55.55 |   73.14 | ...59-275,279-285 
  fetch.ts         |    70.8 |     77.5 |   71.42 |    70.8 | ...41-142,161,186 
  fileUtils.ts     |   91.66 |    86.12 |   95.23 |   91.66 | ...1232,1236-1242 
  forkedAgent.ts   |   80.68 |    78.12 |   83.33 |   80.68 | ...39-545,550-556 
  formatters.ts    |   81.81 |       75 |     100 |   81.81 | 15-16             
  ...eUtilities.ts |   89.21 |    86.66 |     100 |   89.21 | 16-17,49-55,65-66 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,330-335 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  gitDiff.ts       |   92.36 |    80.09 |     100 |   92.36 | ...55-856,928-929 
  gitDirect.ts     |   98.46 |    90.17 |     100 |   98.46 | 148,268,352       
  ...noreParser.ts |   93.84 |     91.3 |     100 |   93.84 | ...03-104,185-186 
  gitUtils.ts      |   72.91 |    90.32 |   83.33 |   72.91 | ...,77-78,102-153 
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   93.13 |     92.3 |     100 |   93.13 | ...16-317,356-359 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.01 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   93.77 |    89.02 |     100 |   93.77 | ...13-319,406-407 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.18 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.83 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   90.85 |    87.87 |     100 |   90.85 | ...97-199,222-227 
  partUtils.ts     |     100 |    98.63 |     100 |     100 | 206               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |    93.3 |    92.22 |     100 |    93.3 | ...92-393,395-397 
  pdf.ts           |   93.68 |    87.05 |     100 |   93.68 | ...96-297,321-325 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   58.57 |       76 |     100 |   58.57 | ...4,88-89,95-100 
  ...noreParser.ts |   92.45 |     90.9 |     100 |   92.45 | ...72-173,186-187 
  rateLimit.ts     |   93.75 |    88.34 |     100 |   93.75 | ...13,218-219,262 
  readManyFiles.ts |   95.13 |    85.18 |     100 |   95.13 | ...24-226,252-253 
  retry.ts         |   95.93 |    91.83 |     100 |   95.93 | ...33,524-525,543 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.52 |    96.84 |     100 |   97.52 | ...05,255-256,282 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   50.94 |    85.71 |      70 |   50.94 | ...54-255,268-346 
  ...sDiscovery.ts |   97.42 |    92.85 |     100 |   97.42 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   82.18 |    85.18 |   95.23 |   82.18 | ...24,549,578-587 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safeJsonParse.ts |   74.07 |    83.33 |     100 |   74.07 | 40-46             
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   90.78 |    88.23 |     100 |   90.78 | ...41-42,93,95-96 
  ...aValidator.ts |   91.97 |    83.42 |     100 |   91.97 | ...44,866-867,880 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.72 |    92.12 |     100 |   91.72 | ...36-539,615-616 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |     83.8 |     100 |   95.98 | ...70,386,466,485 
  shell-utils.ts   |   86.24 |    89.61 |     100 |   86.24 | ...2003,2010-2014 
  ...lAstParser.ts |   95.57 |    85.88 |     100 |   95.57 | ...1066-1068,1078 
  ...ContextEnv.ts |     100 |      100 |     100 |     100 |                   
  ...nlyChecker.ts |   95.08 |    91.66 |     100 |   95.08 | ...15-316,324-325 
  sideQuery.ts     |   86.71 |    87.71 |     100 |   86.71 | ...73-179,181-187 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   81.48 |    77.77 |     100 |   81.48 | 54-59             
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    92.85 |     100 |     100 | 71                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  tool-utils.ts    |    93.6 |     91.3 |     100 |    93.6 | ...58-159,162-163 
  ...ultCleanup.ts |   15.74 |    33.33 |      25 |   15.74 | 33-134            
  ...Compaction.ts |   95.68 |    95.32 |     100 |   95.68 | ...29-334,533-534 
  truncation.ts    |   75.55 |    86.02 |   71.42 |   75.55 | ...44-449,453-477 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |     87.5 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.68 |    80.38 |   94.69 |   83.68 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   82.47 |    76.22 |      95 |   82.47 | ...1525,1559-1560 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   68.81 |    73.82 |   83.87 |   68.81 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

Alex-ai-future added a commit that referenced this pull request Jul 1, 2026
- Reject inline prompt + scope flag combination with clear error (#1)
- Add mutual exclusivity check for --project and --global (#5)
- Verify setValue scope parameter in tests + add --global test (#2)
- Extract scopeSuffix to shared variable, remove duplication (#3)
- Remove dead i18n keys 'Select Model (this project)' / '(global)' (#4)
- Fix scopeSuffix placement on model line not API key line (QwenLM#8)
- Add fr.js / ja.js translations for scope keys (QwenLM#10)
- Remove unused export ModelDialogPersistScope (#6)
- Wrap non-interactive help text in t() with new flags (QwenLM#7)
- Fix argumentHint grouping to show mode vs scope flags (QwenLM#11)

Signed-off-by: Alex <[email protected]>
qwen-code-dev-bot pushed a commit that referenced this pull request Jul 6, 2026
…inates (QwenLM#6235)

* Squashed 'packages/mobile-mcp/' content from commit c5d7d27fd

git-subtree-dir: packages/mobile-mcp
git-subtree-split: c5d7d27fd61e4762e15ae4b1c68b6c011be88bb7

* feat(mobile-mcp): vendor mobile-mcp with opt-in 0-1000 relative coordinates

Fork mobile-next/mobile-mcp (v0.0.61) into packages/mobile-mcp/ via git
subtree, renamed to @qwen-code/mobile-mcp with the following additions:

Relative coordinate shim (src/coord-norm.ts):
- MOBILE_MCP_COORDINATE_SPACE=1 enables 0-1000 normalized coordinates
- MOBILE_MCP_COORDINATE_SCALE configurable (default 1000, 999 for mobile_use)
- Input denormalization for click/double_tap/long_press/swipe
- Output normalization for list_elements and get_screen_size
- Tool description rewriting when enabled
- Default off = zero behavior change

Android enhancements:
- mobile_install_app: -r/-g/-d/-t install flags (Android only)
- mobile_ui_dump: full UIAutomator XML hierarchy dump
- mobile_adb_pull / mobile_adb_push: file transfer via ADB

Infrastructure:
- cd-mobile-mcp.yml: npm publish workflow (tag mobile-mcp-v*)
- scripts/sync-from-upstream.sh: git subtree pull for upstream sync
- .vendored-from / .vendored-patches.md: vendoring metadata
- Upstream telemetry disabled by default
- eslint.config.js: exclude packages/mobile-mcp from root lint

* chore(mobile-mcp): update package-lock.json for workspace dependencies

* fix(mobile-mcp): quote all YAML strings to pass yamllint

* fix(mobile-mcp): fix cd workflow yaml to pass both yamllint and actionlint

* fix(mobile-mcp): address review findings on our additions

- ensureScreenSize: log warning instead of silent failure (#4)
- invalidateScreenSize on orientation change (#5)
- adb_push: path.posix.resolve to prevent /sdcard/ traversal (#6)
- adb_pull: readOnlyHint → destructiveHint (writes local file) (QwenLM#9)
- adb_push: remove validateOutputPath on read-source local_path (QwenLM#11)
- normalizeElementResult: log error instead of bare catch (QwenLM#16)
- rewriteDescription: remove dead duplicate regex (QwenLM#17)
- cd workflow: add test step between build and publish (QwenLM#19)

* fix(mobile-mcp): update server.json identity and fix package.json main entrypoint

---------

Co-authored-by: Shaojin Wen <[email protected]>
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.