Skip to content

feat(omni): S2 input expansion — image/audio/URL sources and token-dimension transport guard - #8512

Merged
LaZzyMan merged 15 commits into
omni-experimentfrom
omni/s2-input-expansion
Aug 6, 2026
Merged

feat(omni): S2 input expansion — image/audio/URL sources and token-dimension transport guard#8512
LaZzyMan merged 15 commits into
omni-experimentfrom
omni/s2-input-expansion

Conversation

@LaZzyMan

@LaZzyMan LaZzyMan commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Implements the S2 slice of the omni experiment: extends the S1 video-only upload delivery to the full input surface — image and audio modalities, URL media sources, tool-result media (the second normalization trigger point), raw-resource token estimation, and a token dimension on the transport guard.

  • Three modalities, original bytes: image/audio/video are all delivered via the DashScope upload channel with NO resizing or transcoding — lossy transforms are reserved for omni policies (S4), which must disclose. Non-sniffable formats (bmp/tiff/heic, exotic containers) fall back to the baseline inline path via a cheap content pre-sniff.
  • Converter: new fileData → input_audio branch passing the bare oss:// URL (previously audio fileData silently textified after a successful upload); getAudioFormat widened to flac/ogg/m4a in lockstep with the recognizer.
  • URL sources: @https://… (previously silently dropped) is intercepted ahead of filesystem resolution, streamed to downloads/ with SSRF/redirect policy, hashed while writing, re-recognized from local bytes, and delivered through the same pipeline. Per-URL failure isolation; user cancellation ends the turn gracefully.
  • Token estimation & guard: versioned raw-resource estimator (raw-resource-v1) attached to read results as the single tokenEstimate location; omni.transport.maxEstimatedTokens (default 0 = observability only — the formula is pending provider confirmation; positive values fail closed before any copy/upload).
  • Second trigger point: processToolResultOmniMedia converts inline tool-result media to oss:// fileData at both physical funnels (CoreToolScheduler terminal sites + ACP Session.runTool), as a sibling of the vision bridge; per-result upload budget (8 parts / 128 MiB) bounds malicious tool output; the sniffed modality — not the declared MIME type — gates conversion.

Why it's needed

Second vertical slice of the omni roadmap (#8197), building on S1 (#8422). Real-model testing during S1 showed the token dimension binds far earlier than the byte dimension (a 36MB/8.4min video exceeds qwen3.5-omni-plus's 196608 input ceiling while 424MB/60s passes), so S2 lands the guard structure with the formula as a swappable slot.

Reviewer Test Plan

How to verify:

  1. npm run build && npm run bundle; env QWEN_CODE_ENABLE_OMNI=1, DashScope endpoint + static key, model qwen3.5-omni-plus.
  2. Local media: node dist/cli.js "@photo.png @clip.mp3 @video.mp4 分别描述" --approval-mode yolo --output-format json --openai-logging --openai-logging-dir ./logs → all three parts in the request log are oss:// (image_url / input_audio / video_url); objects under .qwen/omni/objects/ hash-match the sources byte-exactly.
  3. URL: node dist/cli.js "@https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg 描述" → download card, oss:// delivery, no .part leftovers. A 404 URL shows an error card and the turn continues. @http://localhost/... is refused (SSRF).
  4. Token guard: settings {"omni":{"transport":{"maxEstimatedTokens":196608}}} + a long video → rejected before upload with estimate/method/threshold/setting in the error; without the setting the estimate is attached but nothing is blocked.
  5. Fallback: a .bmp under omni → delivered inline exactly as baseline; omni disabled → all modalities inline as baseline.
  6. Unit: cd packages/core && npx vitest run src/omni/ (77 tests).

Evidence:

  • 19/19 real-API E2E assertions across five groups (three modalities × local/URL, guard both dimensions, tool-result funnel shape vs baseline splitToolMedia, vision-bridge mutual exclusion, gating/fail-closed regressions, TUI Esc during download), verified against pinned S1-era baselines.
  • Real-content checks on qwen3.5-omni-plus: 2-minute commentary audio answered consistently with its Whisper transcript; byte-exact object invariant (sha256(object) == sha256(source)) for all modalities.
  • Two adversarial review rounds (security + correctness) applied; three E2E-hidden defects found and fixed with regression tests (URL-only prompt dropped its delivered media; bmp/tiff fail-closed regression; unhandled rejection on cancel during download).

Tested on:

Environment Status
macOS (arm64), Node 22, real DashScope API, qwen3.5-omni-plus passed
Unit/typecheck (core + cli), 1250+ affected tests passed

Risk & Scope

  • All behavior remains behind the S1 gate (omni enabled + trusted workspace + static DashScope key + explicit baseUrl); gate-off paths are byte-identical to base (E2E-verified).
  • Known limits (by design, tracked): no upload cache yet (S3); token-guard default off pending formula confirmation with the model provider; download consent UX deferred (structure reserved: display cards exist); Qwen OAuth unsupported for the uploads channel.
  • Tool-result funnel keeps failed/over-budget parts inline (safe: locally produced, already in memory) and preserves the identity-equality contract used for content-length accounting.

Linked Issues

Closes #8184. Roadmap: #8197. S1: #8422. Design docs: #8110.

中文说明

本 PR 做了什么

实现 omni 实验 S2 切片:把 S1 的视频上传投递扩展到完整输入面——图片/音频模态、URL 媒体来源、工具结果媒体(第二归一化触发点)、原始资源 token 估算、transport guard 的 token 维度。

  • 三模态原样上传:不缩放不转码(有损处理属 S4 policy 职责,必须披露);不可嗅探格式(bmp/tiff/heic 等)经廉价预嗅探回落基线 inline 路径。
  • converter:新增 fileData → input_audio 分支(bare oss:// URL;此前音频 fileData 上传成功后会被静默文本化);getAudioFormat 扩展到 flac/ogg/m4a。
  • URL 来源@https://…(此前被静默忽略)在文件系统解析前拦截,流式下载(SSRF/重定向策略、边下边 hash)、本地重新识别、同管线投递;单 URL 失败隔离;下载中取消优雅结束。
  • token 估算与 guard:版本化估算器(raw-resource-v1)作为唯一 tokenEstimate 存放位置;omni.transport.maxEstimatedTokens 默认 0(仅观测——公式待模型方确认;设正值后在拷贝/上传前 fail closed)。
  • 第二触发点processToolResultOmniMedia 在 core scheduler 与 ACP 双漏斗把工具结果的 inline 媒体转为 oss:// fileData;单结果上传预算(8 个/128MiB)约束恶意工具输出;以嗅探模态(非声明 MIME)作为门。

验证

见英文 Test Plan。证据:19/19 真实 API E2E 断言(对照钉死的 S1 期基线);qwen3.5-omni-plus 真实内容校验(2 分钟解说音频与 Whisper 转写一致;对象字节不变式三模态成立);两轮对抗审查(安全+正确性)落地,含 3 个 E2E 阶段隐藏缺陷的修复与回归测试。

风险与范围

全部行为在 S1 门控之后;门控关闭路径与基线逐字节一致(E2E 验证)。已知边界(按设计,均有跟踪):上传缓存待 S3;token guard 默认关闭待公式确认;下载 consent UX 推迟(结构已预留);Qwen OAuth 暂不支持上传通道。

关联

Closes #8184;Roadmap #8197;S1 #8422;设计文档 #8110

… guard

Extends the S1 video-only upload delivery to the full S2 input surface:

- recognition: generalized to image/audio/video with content sniffing
  (magic bytes for png/jpeg/webp/gif, mp3/wav/flac/ogg/m4a, plus the S1
  video set) and per-modality ffprobe metadata; modality mismatches
  between sniff and reference fail closed
- delivery: all modalities upload ORIGINAL bytes — no resizing or
  transcoding on the default path (lossy transforms are the job of omni
  policies, which must disclose); images skip renderImageOverview when
  omni is active and carry a dimensions+zoom-hint text part instead
- converter: new fileData→input_audio branch passing the bare oss:// URL
  (previously audio fileData silently textified as 'Unsupported file
  media type' after a successful upload); getAudioFormat widened to
  flac/ogg/m4a in lockstep with the recognizer
- URL inputs: @https://… is intercepted ahead of filesystem resolution
  (previously silently dropped via the ENOENT skip), streamed to
  downloads/ with SSRF/redirect policy mirroring fetchWithPolicy, hashed
  while writing, re-recognized from local bytes, and delivered through
  the same pipeline; per-URL failure isolation keeps the turn alive
- token estimation: versioned raw-resource estimator (method
  raw-resource-v1) attached to read results as the single tokenEstimate
  location; formula is a swappable slot pending provider confirmation
- transport guard: byte ceiling (S1) plus omni.transport.maxEstimatedTokens
  (default 0 = disabled — observability only until the formula is
  confirmed; positive values fail closed before any copy/upload)
- second normalization trigger point: processToolResultOmniMedia converts
  inline tool-result media to oss:// fileData at both physical funnels
  (CoreToolScheduler terminal sites and ACP Session.runTool), as a
  sibling of the vision bridge — converted parts are invisible to
  isImagePart so bridge behavior is untouched

Part of the omni-experiment S2 slice (#8184).
The no-file-paths early return in resolveAtCommandQuery did not count
urlMediaRefs, so a prompt whose only @-reference was a URL ran the full
download → recognize → store → upload pipeline and then discarded both
the delivered fileData parts and their display cards. Found by S2 E2E
verification (the model improvised around the missing image via its own
tools, masking the drop).

Part of the omni-experiment S2 slice (#8184).
Security lens:
- tool-result media funnel: per-result upload budget (8 parts /
  128 MiB aggregate — a malicious tool result must not fan out
  unbounded uploads from the user's account); excess parts stay inline
- modality gate on tool-result parts now keyed to the SNIFFED modality,
  not the declared MIME type (a part declared audio whose bytes are a
  video container no longer bypasses a video-disabled config)
- fs error messages are path-scrubbed before reaching model-visible
  error text (basenames survive, absolute paths do not)

Correctness lens:
- non-sniffable media formats (bmp/tiff/heic images, exotic containers)
  fall back to the baseline inline path via a cheap content pre-sniff
  instead of failing closed — fail-closed remains for genuine pipeline
  failures, not for formats the recognizer simply does not support
- user cancellation during URL media download ends the turn gracefully
  instead of rejecting through resolveAtCommandQuery (which has no
  throw contract) into an unhandled-rejection banner

Part of the omni-experiment S2 slice (#8184).
@LaZzyMan LaZzyMan added the omni-experiment Omni multimodal experiment (omni-experiment branch) label Aug 4, 2026
@LaZzyMan
LaZzyMan marked this pull request as ready for review August 4, 2026 06:26
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🔄 Qwen Triage is runningwatch live progress. Stage results will post in this thread as they complete.

🔄 Qwen Triage 正在运行 —— 查看实时进度。各阶段结果完成后会更新在本线程。

The serve fast-path bundle-closure CI check failed: iconv-lite encoding
tables (553KB) became statically reachable from the acpAgent chunk.

Root cause: the CLI-side dynamic imports of the FULL core barrel
(`import('@qwen-code/qwen-code-core')` in atCommandProcessor) request
the whole namespace object, defeating tree-shaking of the barrel — which
statically re-exports sync-file-encoding → iconvHelper → iconv-lite
tables — and esbuild folds a dynamic import of an already-statically-
imported module into a static chunk edge.

Fixes:
- add a `./omni` subpath export to @qwen-code/qwen-code-core (pattern:
  existing ./transcriptRecords) and point every CLI-side dynamic import
  at it, so only the omni module graph is requested;
- re-export processToolResultOmniMedia from omni/index (circular-safe:
  both modules only bind functions) so the subpath serves the
  tool-result funnel;
- coreToolScheduler and ACP Session load the funnel via dynamic import
  (mirroring fileUtils' existing pattern for the omni module).

Verified: `npm run check:serve-fast-path-bundle` passes; bisected
against base in a clean worktree to isolate the offending edge.

Part of the omni-experiment S2 slice (#8184).
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.17% 83.17% 89.24% 82.46%
Core 87.42% 87.42% 89.01% 86.05%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.17 |    82.46 |   89.24 |   83.17 |                   
 src               |   84.45 |    80.93 |   89.13 |   84.45 |                   
  cli.ts           |   94.21 |    83.33 |     100 |   94.21 | ...72-573,583-584 
  gemini.tsx       |   73.89 |    76.49 |    82.6 |   73.89 | ...1183-1187,1308 
  ...ractiveCli.ts |   85.65 |    81.55 |   87.17 |   85.65 | ...2390,2396,2448 
  ...liCommands.ts |   88.34 |     83.6 |      90 |   88.34 | ...63,480,514,635 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   69.15 |    71.79 |   89.53 |   69.15 |                   
  acpAgent.ts      |    68.8 |    71.63 |   89.55 |    68.8 | ...02,11107-11109 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.04 |    95.71 |   93.33 |   97.04 |                   
  filesystem.ts    |   97.04 |    95.71 |   93.33 |   97.04 | ...21-122,238-239 
 ...ration/session |   91.54 |    86.56 |   96.49 |   91.54 |                   
  Session.ts       |   91.11 |    85.43 |   96.01 |   91.11 | ...9147,9174-9178 
  ...entTracker.ts |   91.87 |    89.18 |   88.88 |   91.87 | ...33,197,280-289 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |    93.1 |    90.72 |     100 |    93.1 | 71,82-85,111-121  
  ...y-replayer.ts |   98.53 |    95.52 |     100 |   98.53 | 238-240           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    86.76 |     100 |   89.76 | ...54-270,326-328 
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.68 |     93.7 |   96.66 |   95.68 |                   
  ...ageEmitter.ts |   95.34 |    94.11 |     100 |   95.34 | 52-59             
  PlanEmitter.ts   |     100 |    83.33 |     100 |     100 | 59                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   99.17 |    97.43 |     100 |   99.17 | 352-353           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/commands      |   89.02 |    73.18 |   64.51 |   89.02 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.03 |      100 |      50 |   98.03 | 62                
  serve.ts         |   86.85 |     67.3 |     100 |   86.85 | ...32-635,649-653 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   86.94 |    87.09 |   89.61 |   86.94 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |      80 |    84.61 |      80 |      80 | 37-40,49-52,63-66 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.87 |    96.35 |     100 |   95.87 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.88 |    85.33 |   94.11 |   93.88 | ...1207,1214-1215 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.49 |    96.51 |     100 |   98.49 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |   72.85 |      100 |      50 |   72.85 | 22-28,57-68       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   81.42 |    87.71 |     100 |   81.42 | ...70-174,234-236 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |   75.05 |    73.17 |   76.92 |   75.05 | ...31,537-540,552 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.82 |    87.82 |   87.09 |   88.82 |                   
  consent.ts       |   72.53 |       90 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     90.9 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |      75 |    55.55 |     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.17 |    84.39 |   83.33 |   90.17 |                   
  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.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   84.59 |    86.04 |   85.08 |   84.59 |                   
  agent-prompt.ts  |   90.88 |    92.78 |      96 |   90.88 | ...1259,1729-1798 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   48.38 |    14.28 |   66.66 |   48.38 | ...21-226,239-249 
  cleanup.ts       |   90.25 |    83.14 |   83.33 |   90.25 | ...77-482,484-485 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   95.85 |    91.25 |   93.75 |   95.85 | ...1439,1467-1489 
  fetch-pr.ts      |   74.02 |    53.57 |      50 |   74.02 | ...98,332,402-407 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  parse-args.ts    |   99.27 |       96 |     100 |   99.27 | 345,417           
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   84.44 |    79.38 |   91.66 |   84.44 | ...29-910,939-941 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  run.ts           |   81.14 |    86.17 |    90.9 |   81.14 | ...13,429-477,490 
  script-lint.ts   |   83.67 |    78.41 |   88.88 |   83.67 | ...59-773,775-797 
  submit.ts        |   76.74 |    82.05 |   81.81 |   76.74 | ...03-639,641-642 
  test-efficacy.ts |   80.68 |    69.41 |    92.3 |   80.68 | ...93-594,602-622 
 ...nds/review/lib |   95.77 |    93.13 |   95.74 |   95.77 |                   
  agent-briefs.ts  |   98.68 |      100 |       0 |   98.68 | 520-521           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  coverage.ts      |   95.47 |    94.25 |   95.45 |   95.47 | ...98,335,433-450 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  effort.ts        |     100 |      100 |     100 |     100 |                   
  gh.ts            |    85.6 |    88.37 |   71.42 |    85.6 | ...20,257-258,285 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |    85.71 |     100 |     100 | 70                
  prompt-record.ts |   94.73 |    88.23 |     100 |   94.73 | ...28,151-152,156 
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  report.ts        |   94.38 |    93.75 |     100 |   94.38 | 173-177           
  roster.ts        |     100 |    94.23 |     100 |     100 | 143,161,206       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.27 |    93.18 |     100 |   96.27 | ...83,269-270,294 
  workspaces.ts    |   97.76 |     91.2 |     100 |   97.76 | 186-187,212-213   
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.26 |     88.6 |   95.91 |   94.26 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   88.36 |    87.86 |   84.84 |   88.36 | ...2398,2400-2408 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.04 |    88.28 |     100 |   83.04 | ...39,253,352-353 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   94.33 |    89.61 |   94.73 |   94.33 | ...35-639,655-656 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |   97.38 |       50 |     100 |   97.38 | 234-237           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.96 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   90.99 |     92.3 |      90 |   90.99 | ...1006,1008-1009 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   93.35 |    94.11 |     100 |   93.35 | ...90-391,427-438 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |      80 |    76.31 |   81.35 |      80 |                   
  session.ts       |   84.08 |    75.27 |   93.61 |   84.08 | ...1007,1016-1026 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...24-625,628-629 
 ...active/control |   76.11 |    89.09 |      80 |   76.11 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.79 |    92.45 |   88.88 |   91.79 | ...49-367,387,390 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |   39.78 |    63.24 |   47.22 |   39.78 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   49.11 |    62.96 |   54.54 |   49.11 | ...63-568,570-575 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.07 |    94.07 |   95.23 |   98.07 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1415,1431-1432 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 84-85,125-126     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |   87.28 |    83.38 |   91.16 |   87.28 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |    93.4 |    93.05 |     100 |    93.4 | ...19-320,323-325 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    97.87 |     100 |     100 | 629               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |   93.89 |    86.61 |     100 |   93.89 | ...66-468,475,477 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   85.85 |    91.78 |   95.83 |   85.85 | ...94-206,366-369 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.27 |     85.2 |     100 |   87.27 | ...10,816-820,838 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.41 |    84.44 |    97.1 |   92.41 | ...1460,1514-1518 
  ...e-grouping.ts |     100 |    94.11 |     100 |     100 | 69,132            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |   92.04 |    77.77 |     100 |   92.04 | ...36-445,470,508 
  daemon-logger.ts |    82.2 |    77.26 |   91.76 |    82.2 | ...1720,1747-1753 
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.37 |    90.06 |     100 |   98.37 | ...1041,1043-1044 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |    91.3 |       80 |     100 |    91.3 | ...24-127,205-212 
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.41 |    88.75 |     100 |   94.41 | ...24,702,718,728 
  fast-path.ts     |   90.33 |    80.23 |   95.45 |   90.33 | ...83-492,558-559 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...27-128,139-140 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   82.62 |     79.3 |   73.86 |   82.62 | ...6648,6653-6654 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   95.04 |     89.1 |     100 |   95.04 | ...07,511-512,552 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   93.99 |    93.52 |      75 |   93.99 | ...2061,2082-2086 
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.34 |    76.57 |     100 |   93.34 | ...17,820,833-835 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |    86.66 |     100 |   91.07 | ...79-182,216-219 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   93.89 |     87.5 |     100 |   93.89 | ...17-518,524-525 
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...e-remember.ts |   98.14 |    88.92 |     100 |   98.14 | ...31,335-340,381 
  ...te-runtime.ts |   83.98 |    90.19 |     100 |   83.98 | ...48-156,216-237 
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
  ...lls-status.ts |     100 |    92.85 |     100 |     100 | 127               
  ...reconciler.ts |    91.6 |     83.9 |     100 |    91.6 | ...70-272,305-306 
 ...serve/acp-http |   76.83 |    78.16 |   93.15 |   76.83 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |    98.2 |    88.62 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   71.11 |    73.69 |   95.23 |   71.11 | ...4685,4733-4739 
  index.ts         |   81.78 |    79.64 |   90.56 |   81.78 | ...2273,2343-2344 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |   86.12 |    79.82 |     100 |   86.12 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |     73.6 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.32 |    89.18 |     100 |   90.32 | 141-149           
  ...ile-system.ts |   85.85 |    78.51 |     100 |   85.85 | ...2227,2237-2238 
 src/serve/routes  |    85.8 |    79.37 |   95.64 |    85.8 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   85.22 |       88 |     100 |   85.22 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.45 |    83.33 |     100 |   85.45 | 98-105            
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   94.73 |     86.2 |     100 |   94.73 | 62-66,154         
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   86.78 |     81.9 |   95.65 |   86.78 | ...1195,1238-1239 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   86.27 |    81.47 |      95 |   86.27 | ...4295,4297-4298 
  sse-events.ts    |   84.45 |     87.5 |   77.77 |   84.45 | ...36,453-456,485 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.19 |    77.68 |     100 |   90.19 | ...47-448,467-468 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.41 |    78.89 |      90 |   83.41 | ...1024,1030,1033 
  ...extensions.ts |    87.2 |    72.76 |   94.11 |    87.2 | ...1822,1867-1868 
  ...-file-read.ts |   92.34 |     81.1 |     100 |   92.34 | ...96-597,600-601 
  ...file-write.ts |   84.44 |    64.51 |     100 |   84.44 | ...73-275,355-357 
  ...t-branches.ts |   75.43 |    66.66 |     100 |   75.43 | ...13-618,627-634 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    93.18 |     100 |     100 | 52,77,188         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...management.ts |   88.15 |    85.19 |     100 |   88.15 | ...1537,1557-1562 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   74.81 |    70.31 |     100 |   74.81 | ...47-658,664-665 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |   69.87 |    78.12 |     100 |   69.87 | ...59-284,290-324 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.42 |    64.78 |      80 |   78.42 | ...31-336,344-345 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   90.77 |    89.49 |   95.27 |   90.77 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |   85.45 |    76.57 |     100 |   85.45 | ...93,710,773-782 
  fs-factory.ts    |     100 |    92.59 |     100 |     100 | 34,42,103,159     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.11 |    95.14 |     100 |   95.11 | ...65-167,422-427 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   94.81 |    90.32 |     100 |   94.81 | 175-181           
  ...on-archive.ts |   89.61 |    90.56 |   88.23 |   89.61 | ...36-441,513-523 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   99.01 |    97.43 |     100 |   99.01 | ...13,627,769-771 
 src/serve/voice   |   83.35 |    92.22 |   90.47 |   83.35 |                   
  ...ice-config.ts |   84.61 |       30 |     100 |   84.61 | 90-99,103-104     
  voice-ws.ts      |   77.16 |    94.73 |   83.33 |   77.16 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |    89.4 |    85.59 |      90 |    89.4 |                   
  index.ts         |   88.94 |    85.16 |   88.57 |   88.94 | ...1211-1215,1218 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.23 |     88.5 |   97.82 |   92.23 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 104-117           
  ...killLoader.ts |   97.14 |    87.87 |     100 |   97.14 | 140,151-152       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   79.55 |    88.29 |   83.33 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.36 |    92.68 |     100 |   97.36 | 153,160-161       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.29 |    86.48 |     100 |   88.29 | ...91-196,229-230 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.54 |    90.47 |    87.5 |   93.54 | 201-203,217-223   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.83 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   90.37 |    87.87 |     100 |   90.37 | ...80,287,352-357 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   90.46 |    82.19 |      96 |   90.46 | ...66-668,671-673 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |    86.29 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.24 |   94.73 |   88.28 | ...1352,1356-1363 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   93.26 |       75 |   83.33 |   93.26 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   72.11 |    75.58 |   64.63 |   72.11 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   73.26 |    72.45 |   67.85 |   73.26 | ...4122,4164-4174 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   66.97 |    65.71 |   33.33 |   66.97 | ...77,292,323-328 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   58.53 |    66.18 |   51.06 |   58.53 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.21 |    70.73 |   57.69 |   60.21 | ...90,794,803,806 
  useAuth.ts       |    94.6 |    73.52 |     100 |    94.6 | ...21-222,241-247 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |    81.4 |    82.96 |    89.4 |    81.4 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |   92.46 |    83.63 |     100 |   92.46 | ...4-69,94-99,178 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   68.28 |    70.14 |   84.61 |   68.28 | ...66-599,610-611 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   82.97 |    78.57 |     100 |   82.97 | 47-52,67-70,91-96 
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   91.13 |    83.72 |      90 |   91.13 | ...81-184,196-199 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   93.45 |    89.06 |     100 |   93.45 | ...68-169,196-206 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.27 |    83.01 |     100 |   86.27 | ...22-935,969-974 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   89.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...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 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |   70.64 |    78.44 |   76.29 |   70.64 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   97.29 |     87.5 |   66.66 |   97.29 | 49                
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   88.65 |    90.41 |     100 |   88.65 | ...84-286,300-302 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-72,84,139,153 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-597             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   75.11 |     61.4 |      50 |   75.11 | ...48-253,271-275 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   83.33 |    76.92 |     100 |   83.33 | 24-30             
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   78.51 |     65.3 |     100 |   78.51 | ...99,502,505-511 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   83.08 |    81.73 |      80 |   83.08 | ...2197,2223,2297 
  ...Shortcuts.tsx |   20.65 |      100 |       0 |   20.65 | ...7,50-52,68-126 
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.82 |    92.53 |      50 |   95.82 | ...97,440-444,447 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   83.41 |    71.65 |     100 |   83.41 | ...69,971,976-992 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   92.97 |    83.87 |     100 |   92.97 | ...43,246,273-275 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  ...criptView.tsx |   98.27 |    84.21 |     100 |   98.27 | 45,53             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   53.72 |    70.87 |   42.85 |   53.72 |                   
  ...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  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |    82.2 |    81.36 |    90.9 |    82.2 |                   
  ...sksDialog.tsx |   77.53 |     76.9 |   80.76 |   77.53 | ...1781,1803-1809 
  ...TasksPill.tsx |   67.03 |     86.2 |     100 |   67.03 | ...02-122,130-138 
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.14 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.28 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |   50.97 |    52.38 |   20.83 |   50.97 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.56 |      100 |       0 |    9.56 | 40-67,70-158      
 ...mponents/hooks |   86.99 |    81.37 |   91.89 |   86.99 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.04 |    61.53 |   70.58 |   40.04 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   89.97 |    86.17 |      87 |   89.97 |                   
  ...ionDialog.tsx |   89.23 |    84.27 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   96.71 |    97.77 |   91.66 |   96.71 | 223-233           
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   76.52 |     42.1 |   66.66 |   76.52 | ...00,102,125,156 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   89.75 |     79.1 |     100 |   89.75 | ...33-635,642-644 
  ...upMessage.tsx |   98.32 |    95.16 |     100 |   98.32 | 184-187,414       
  ToolMessage.tsx  |   92.49 |       85 |   93.33 |   92.49 | ...61-966,993-995 
 ...ponents/shared |   85.76 |    82.09 |   94.05 |   85.76 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.86 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   88.51 |    85.11 |   81.81 |   88.51 | ...51-779,792,887 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   69.81 |    72.64 |   61.11 |   69.81 |                   
  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 |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.11 |    81.79 |    86.3 |   84.11 |                   
  ...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 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.92 |    85.15 |     100 |   85.92 | ...1607-1609,1615 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 155-156           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 234-235           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   85.03 |    82.53 |   89.57 |   85.03 |                   
  ...dProcessor.ts |   85.57 |    84.11 |     100 |   85.57 | ...1046,1096-1097 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...86-287,292-293 
  ...dProcessor.ts |   85.21 |     66.4 |   81.81 |   85.21 | ...1407,1428-1432 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      42 |       75 |     100 |      42 | 42-44,53-59,62-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.08 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.73 |    76.59 |     100 |   94.73 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   94.85 |    80.76 |     100 |   94.85 | ...54,229,292-295 
  ...ompletion.tsx |   97.09 |    87.09 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   78.53 |    88.57 |     100 |   78.53 | ...96-104,112-113 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |    85.7 |    81.24 |   96.15 |    85.7 | ...3987,4155-4163 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.01 |    98.36 |     100 |   98.01 | 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 |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.5 |     100 |     100 | 99                
  ...delCommand.ts |     100 |       95 |     100 |     100 | 53                
  ...ouseEvents.ts |   94.38 |    97.36 |   83.33 |   94.38 | 77-81             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   88.95 |    86.95 |     100 |   88.95 | ...37-439,471-481 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   94.67 |    74.28 |     100 |   94.67 | ...19,174,233-238 
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    91.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   86.25 |    85.11 |   95.04 |   86.25 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   79.84 |     75.6 |     100 |   79.84 | ...66,270,328-329 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.38 |    81.91 |   95.23 |   92.38 | ...43-746,799-804 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   52.52 |    73.25 |   91.66 |   52.52 | ...23,626-635,638 
  commandUtils.ts  |   96.17 |    88.88 |     100 |   96.17 | ...77,179-180,323 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |    95.4 |    98.41 |     100 |    95.4 | 123-126           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |      96 |    97.05 |     100 |      96 | 102-105           
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   69.47 |       75 |   66.66 |   69.47 | ...24-129,157-158 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |     97.1 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   71.33 |     79.2 |   93.75 |   71.33 | ...08-530,661-662 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   95.97 |    94.06 |   94.44 |   95.97 | ...29-330,490-491 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   90.42 |    92.85 |     100 |   90.42 | ...06-207,240-241 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |    59.89 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   80.94 |    72.69 |   80.55 |   80.94 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   89.72 |    65.33 |   93.75 |   89.72 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |    68.42 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.37 |    87.04 |   92.49 |   81.37 |                   
  ...p-profiler.ts |   98.39 |    90.56 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       95 |     100 |     100 | 72                
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...59,376-377,422 
  jsonc-editor.ts  |   93.18 |    92.72 |     100 |   93.18 | ...80-381,384-385 
  languageUtils.ts |   98.88 |    97.05 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   89.05 |    76.38 |     100 |   89.05 | ...86,302-303,340 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   74.38 |    69.56 |     100 |   74.38 | ...92-103,105-116 
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.67 |    56.93 |   76.92 |   45.67 | ...1034,1046-1069 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |     87.5 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   91.63 |    91.02 |      95 |   91.63 |                   
  cleanup.ts       |   95.77 |    95.83 |     100 |   95.77 | 70-72             
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   91.91 |    90.47 |    87.5 |   91.91 | 58-62,73,131-135  
  throttledOnce.ts |   86.66 |     86.2 |     100 |   86.66 | ...99,105,137-138 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.42 |    86.05 |   89.01 |   87.42 |                   
 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.87 |    84.13 |   94.08 |   89.87 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...74,582,588-592 
  ...ent-resume.ts |   84.67 |    77.52 |   79.16 |   84.67 | ...1774-1778,1781 
  ...ound-tasks.ts |   96.15 |     90.1 |   98.76 |   96.15 | ...1732,1752-1755 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.65 |    89.28 |     100 |   95.65 | ...12-413,485-489 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   90.24 |    85.52 |   87.34 |   90.24 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   84.35 |    74.69 |   76.92 |   84.35 | ...2172,2218-2220 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    88.09 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.95 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.79 |    87.79 |   82.35 |   91.79 | ...1774,1823-1826 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...ow-sandbox.ts |   96.87 |    94.51 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   81.81 |    83.99 |    87.5 |   81.81 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.38 |    86.71 |   74.28 |   84.38 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   83.68 |    86.39 |   72.59 |   83.68 | ...8131,8135-8136 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.11 |    91.95 |      88 |   94.11 | ...25-426,429-430 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   91.71 |    87.88 |   93.08 |   91.71 |                   
  baseLlmClient.ts |   88.28 |    82.48 |   81.81 |   88.28 | ...47,660,666-668 
  client.ts        |   91.55 |    87.01 |   91.56 |   91.55 | ...3887,3983-3984 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...65-466,511-517 
  ...lScheduler.ts |   90.03 |    85.74 |      96 |   90.03 | ...5621,5649-5660 
  geminiChat.ts    |   92.42 |    89.26 |      96 |   92.42 | ...4429,4477-4478 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 47-48             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   95.19 |    89.47 |     100 |   95.19 | ...44-245,290-291 
  prompts.ts       |   93.57 |    91.42 |   83.33 |   93.57 | ...1187,1390-1391 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |   96.89 |    80.88 |   88.23 |   96.89 | ...10,117-118,123 
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.52 |    91.66 |     100 |   98.52 | ...14,642-643,690 
 ...ntentGenerator |   96.24 |    87.19 |   95.38 |   96.24 |                   
  ...tGenerator.ts |   97.09 |    86.94 |   94.44 |   97.09 | ...1329,1358,1369 
  converter.ts     |   96.16 |    87.32 |     100 |   96.16 | ...,984,1139-1141 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   95.21 |    86.46 |    92.3 |   95.21 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.12 |     85.4 |   91.89 |   95.12 | ...1169-1170,1198 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.53 |    90.25 |   95.23 |   91.53 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   90.92 |    89.38 |   96.87 |   90.92 | ...1960,2129-2144 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   96.63 |    90.94 |     100 |   96.63 | ...1100,1108,1203 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.74 |    89.83 |   98.27 |   96.74 |                   
  dashscope.ts     |    97.5 |    92.02 |      95 |    97.5 | ...92-393,535-536 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   86.12 |    83.14 |   92.19 |   86.12 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   78.32 |    71.83 |     100 |   78.32 | ...1122,1168-1169 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |   80.39 |     87.5 |     100 |   80.39 | 50-59             
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.82 |    86.11 |   97.82 |   90.82 | ...1215-1221,1265 
  ...ionManager.ts |   80.59 |    78.06 |   80.23 |   80.59 | ...2577,2599-2600 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    84.61 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   88.58 |    82.13 |     100 |   88.58 | ...62,952-953,963 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |    91.93 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    83.78 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |    80.61 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |   77.48 |    79.84 |    90.9 |   77.48 |                   
  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   |   65.58 |    62.63 |   71.42 |   65.58 | ...21-622,629-630 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 97                
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   94.17 |    88.82 |   95.93 |   94.17 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  goal-evidence.ts |   87.59 |     85.1 |   95.65 |   87.59 | ...12-613,636-639 
  ...projection.ts |   89.41 |    72.22 |   66.66 |   89.41 | ...28,131,135-137 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |    91.3 |       90 |     100 |    91.3 | 107-108           
  goal-reducer.ts  |   92.21 |    85.48 |     100 |   92.21 | ...67-368,381,436 
  goal-runtime.ts  |   99.01 |    93.44 |     100 |   99.01 | ...83-684,707-708 
  goal-tools.ts    |   98.32 |    93.18 |   95.23 |   98.32 | ...48-149,256-257 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...67-170,183-185 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-27              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   87.97 |    86.18 |   88.42 |   87.97 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.46 |       84 |   94.59 |   95.46 | ...1015-1016,1026 
  hookPlanner.ts   |    87.5 |    85.36 |   86.66 |    87.5 | ...21-225,232-243 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.55 |      100 |   70.21 |   87.55 | ...45-746,752-753 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    87.91 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.24 |    96.12 |   88.88 |   94.24 | ...42-543,628-632 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.17 |    82.78 |   90.29 |   87.17 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.11 |    95.72 |   96.29 |   97.11 | ...85-287,361-362 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    81.81 |     100 |     100 | 126,136           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   91.48 |    75.75 |     100 |   91.48 | ...99,118-121,189 
  ...entPlanner.ts |   91.51 |    76.19 |     100 |   91.51 | ...04,113-116,290 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   82.27 |    77.92 |   83.33 |   82.27 | ...66,285,292-298 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   94.73 |    95.94 |     100 |   94.73 | ...35-336,357-358 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   89.85 |    82.92 |     100 |   89.85 | ...54-155,162-163 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    89.79 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   71.68 |    65.51 |   68.75 |   71.68 | ...90-394,397,403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |     82.6 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |     79.1 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.54 |    88.64 |   91.13 |   92.54 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.13 |     100 |     100 | 177,260           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/omni          |   94.96 |    86.53 |     100 |   94.96 |                   
  download.ts      |   95.61 |     87.7 |     100 |   95.61 | ...92-493,547-551 
  estimation.ts    |   98.36 |       95 |     100 |   98.36 | 108               
  ffmpeg.ts        |   95.85 |    80.64 |     100 |   95.85 | ...,70-72,183-184 
  guard.ts         |     100 |      100 |     100 |     100 |                   
  index.ts         |   89.28 |    85.18 |     100 |   89.28 | ...74-280,301-305 
  recognition.ts   |   98.15 |    95.38 |     100 |   98.15 | 69-70,193         
  storage.ts       |   92.24 |       80 |     100 |   92.24 | ...73-175,177-178 
  ...sult-media.ts |     100 |    86.36 |     100 |     100 | 55,68-77,130-134  
  upload.ts        |    93.2 |    78.26 |     100 |    93.2 | ...47-149,241-246 
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.58 |    91.02 |   70.71 |   83.58 |                   
  autoMode.ts      |   97.65 |    93.13 |     100 |   97.65 | ...79-586,632,709 
  ...transcript.ts |      98 |    84.61 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.54 |    89.63 |      80 |   86.54 | ...1096,1202-1206 
  rule-parser.ts   |   94.18 |    91.89 |     100 |   94.18 | ...1345,1379-1381 
  ...-semantics.ts |   70.36 |    91.02 |   46.66 |   70.36 | ...2237,2300-2303 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.38 |    84.49 |   96.77 |   89.38 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.68 |    85.71 |     100 |   97.68 | ...96,119,490-491 
  ...ionService.ts |   96.71 |    95.79 |     100 |   96.71 | ...83,699,832-840 
  ...ingService.ts |    90.9 |    84.09 |   95.45 |    90.9 | ...2042,2069-2070 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.05 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   93.58 |    86.04 |   93.33 |   93.58 | ...00-301,388-395 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.22 |    97.34 |     100 |   98.22 | ...75-676,723-724 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.47 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |     90.8 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |   98.38 |    93.75 |   88.88 |   98.38 | 63-64             
  ...ipt-reader.ts |   94.41 |    88.65 |      98 |   94.41 | ...1083-1084,1148 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   79.58 |    73.55 |   95.58 |   79.58 | ...1913,1917-1929 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.73 |    83.46 |    97.1 |   88.73 | ...2401,2471-2491 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |   84.35 |    78.37 |   97.14 |   84.35 | ...2472,2478-2483 
  ...pInhibitor.ts |   97.42 |    92.68 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.84 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.58 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.58 |     100 |   99.41 | 244-245,677       
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   88.37 |    87.22 |   90.16 |   88.37 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   83.78 |    82.63 |   82.35 |   83.78 | ...1218,1225-1229 
  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           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.63 |    88.64 |   96.55 |   87.63 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.25 |    85.31 |   94.87 |   84.25 | ...1566,1643-1644 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   80.91 |    83.37 |   84.44 |   80.91 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.07 |    80.95 |     100 |   99.07 | 183,197           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |     100 |    90.47 |     100 |     100 | 49,76             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |    56.1 |    71.15 |   64.15 |    56.1 | ...1376,1393-1413 
  metrics.ts       |   78.44 |    79.62 |   79.66 |   78.44 | ...1079,1082-1093 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,478-479,495 
  sdk.ts           |   79.22 |    89.18 |   63.63 |   79.22 | ...57-161,199-221 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.83 |    90.05 |   96.77 |   90.83 | ...1666,1697-1700 
  ...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         |   82.35 |    87.23 |   86.04 |   82.35 | ...1361,1365-1372 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.11 |    80.35 |      70 |   74.11 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.11 |    80.18 |   69.49 |   74.11 | ...1118,1156-1157 
 src/test-utils    |      94 |    98.24 |   78.94 |      94 |                   
  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     |   92.57 |      100 |   75.75 |   92.57 | ...63,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   85.95 |    84.62 |   88.31 |   85.95 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   81.63 |       79 |   85.41 |   81.63 | ...3221,3223-3224 
  mcp-client.ts    |   79.83 |    85.09 |   89.47 |   79.83 | ...2233,2237-2240 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |    97.2 |    93.47 |     100 |    97.2 | ...00-801,856-857 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.74 |    84.28 |   88.46 |   91.74 | ...93,606,804-809 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    90.24 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   78.78 |    84.06 |   91.91 |   78.78 | ...5019,5082-5083 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.06 |    93.33 |   89.47 |   91.06 | ...71,475,520-542 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   94.36 |    84.61 |   92.85 |   94.36 | ...10-415,437-438 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   92.74 |    91.52 |    91.3 |   92.74 | ...63-564,580-586 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.53 |    83.57 |      80 |   90.53 | ...1007,1065-1068 
  write-file.ts    |    86.7 |    84.92 |   88.88 |    86.7 | ...24-827,864-899 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   85.28 |     85.8 |   86.66 |   85.28 |                   
  agent.ts         |   85.13 |    85.59 |   86.17 |   85.13 | ...4128,4150-4160 
  fork-subagent.ts |   88.32 |       90 |    90.9 |   88.32 | ...05-123,200-201 
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   87.46 |    79.41 |   85.71 |   87.46 |                   
  workflow.ts      |   87.46 |    79.41 |   85.71 |   87.46 | ...51-652,664-667 
 src/utils         |   92.78 |     89.7 |   96.81 |   92.78 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.81 |    93.95 |      95 |   95.81 | ...91-492,504-517 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   82.62 |    94.32 |    61.9 |   82.62 | ...62-378,382-388 
  fetch.ts         |   91.25 |    83.33 |     100 |   91.25 | ...84,495-496,515 
  fileUtils.ts     |   94.85 |    92.65 |   96.15 |   94.85 | ...1951,1976-1977 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |   81.81 |       75 |     100 |   81.81 | 15-16             
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |    93.25 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.95 |    92.79 |     100 |   93.95 | ...78-479,481-483 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   97.16 |    84.69 |     100 |   97.16 | ...67-268,340-341 
  readManyFiles.ts |   96.29 |    87.23 |     100 |   96.29 | 225,276,286-290   
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.02 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   85.29 |     87.5 |   96.29 |   85.29 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |    83.96 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.07 |    88.36 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.16 |    91.91 |     100 |   98.16 | ...1244-1246,1256 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |    90.82 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       64 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.11 |    96.22 |     100 |   96.11 | ...22-327,329-334 
  ...pt-records.ts |   85.85 |    83.63 |     100 |   85.85 | ...86-390,420-435 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.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 |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

The previous fix added a `./omni` subpath export to
@qwen-code/qwen-code-core, but vitest/tsc in this monorepo resolve the
core package through explicit aliases to TS sources rather than the
package exports map — so every suite loading atCommandProcessor or the
ACP Session failed with "Failed to resolve import
'@qwen-code/qwen-code-core/omni'".

Add the subpath alias alongside the existing transcriptRecords/goalWire
precedents in cli/acp-bridge/sdk-typescript vitest configs and the
cli/acp-bridge tsconfig paths.

Part of the omni-experiment S2 slice (#8184).
The self-hosted CI runners export QWEN_RUNTIME_DIR for their own qwen
job tooling. Storage.getRuntimeBaseDir gives that env var top priority,
so logger.test.ts (HOME-derived path expectations) and the ACP Session
runtime-pinning tests (Storage.setRuntimeBaseDir-based expectations)
fail whenever a PR lands on such a runner — independent of the change
under test. Reproduced locally with QWEN_RUNTIME_DIR=/tmp/fake-spool.

Clear the variable inside the affected suites (restored after each
test), making them hermetic on any runner.
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the S2 slice!

Template looks good ✓

Problem: observed, not theoretical. This is the tracked roadmap slice (#8184, roadmap #8197) building on S1 (#8422, merged into omni-experiment on 2026-08-03). The motivation cites real S1 model-testing findings — the token dimension binding before the byte dimension (a 36MB/8.4min video exceeds the 196608 input ceiling while a 424MB/60s clip passes), audio fileData silently textifying after a successful upload, and @https://… refs being silently dropped. Concrete observed gaps, not speculation.

Direction: aligned. Second vertical slice of an established experiment with S1 already merged; everything stays behind the S1 gate and targets the omni-experiment branch, so blast radius is contained. The claude-code CHANGELOG has no direct reference to upload-based audio/video delivery (mostly image-paste fixes), so the direction signal comes from this repo's own roadmap rather than external parity.

Size: core paths touched heavily — 1496 production lines vs 667 test lines (plus 24 schema and 18 build-config lines). The author is a maintainer (admin), so the two-tier core gate doesn't apply; numbers recorded for transparency. Large but coherent: S2 is the "full input surface behind one gate" vertical slice, and splitting it up would fragment that design.

Approach: the scope feels right. The structure mirrors S1 cleanly (recognize → guard → store → upload), reuses the existing isPrivateHost/isPermittedRedirect fetch policy instead of inventing a parallel SSRF stack, and keeps S1 symbols as deprecated aliases so the diff stays focused on new work. The two side-edits (QWEN_RUNTIME_DIR stubs in logger.test.ts / Session.test.ts) are test-env fixes for self-hosted runners and are justified. The pre-sniff fallback (bmp/tiff → baseline inline) and gating on the sniffed modality rather than the declared MIME type are the right calls.

Risk: two changed files match the revert-history high-risk paths — openaiContentGenerator/converter.ts and acp-integration/session/Session.ts. Full-depth review applied (see Stage 2); both edits are small and additive — a new fileData audio branch, and a sibling call inserted before the vision bridge.

Moving on to code review. 🔍

中文说明

感谢 S2 切片!

模板完整 ✓

问题: 已观测到、非理论性问题。这是 roadmap 跟踪的切片(#8184,总纲 #8197),建立在 S1(#8422,2026-08-03 合入 omni-experiment)之上。动机来自 S1 真实模型测试的发现——token 维度先于字节维度触顶(36MB/8.4 分钟视频超出 196608 输入上限,而 424MB/60 秒视频可以通过)、音频 fileData 上传成功后被静默文本化、@https://… 引用被静默丢弃。都是具体观测到的缺口,不是臆测。

方向: 对齐。这是既定实验的第二个垂直切片,S1 已合入;所有行为都在 S1 门控之后、目标是 omni-experiment 分支,爆炸半径可控。claude-code CHANGELOG 中没有基于上传的音频/视频投递的直接参照(多为图片粘贴类修复),方向信号主要来自本仓库自己的 roadmap。

规模: 大量触及核心路径——生产逻辑 1496 行 vs 测试 667 行(另有 24 行 schema、18 行构建配置)。作者是 maintainer(admin 权限),双层核心门禁不适用,数字仅作透明记录。体量大但内聚:S2 是"一个门控后的完整输入面"垂直切片,拆分会打碎该设计。

方案: 范围合理。结构清晰复用 S1(识别 → 守卫 → 存储 → 上传),SSRF/重定向策略复用现有 isPrivateHost/isPermittedRedirect 而非另起炉灶,S1 符号保留为弃用别名使 diff 聚焦新增工作。两处附带改动(logger.test.ts / Session.test.tsQWEN_RUNTIME_DIR stub)是自托管 runner 的测试环境修复,合理。预嗅探回落(bmp/tiff → 基线 inline)与以嗅探模态(而非声明 MIME)作门控是正确选择。

风险: 两个变更文件命中 revert 历史高风险路径——openaiContentGenerator/converter.tsacp-integration/session/Session.ts。已按全深度审查处理(见 Stage 2)。两处改动都小且为增量:新增 fileData 音频分支、在 vision bridge 前插入同级调用。

进入代码审查。🔍

Qwen Code · qwen3.8-max

Reviewed at 3842cb2693aafa0dc9d92cb1400da06a26358897 · re-run with @qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

I wrote my independent proposal before reading the diff (extend the S1 recognizer to three modalities, add per-modality converter branches, intercept @URL before filesystem resolution with an SSRF-safe streaming download, add a second tool-result funnel with budgets, and a versioned estimator with an observe-only default). The PR matches that shape everywhere I had an opinion, and goes beyond it where I hadn't thought it through — the pre-sniff fallback for formats the recognizer doesn't support, modality-mismatch rejection, and the per-result upload budget. No critical blockers found.

What I verified by reading the code, not just the description:

  • Vision-bridge mutual exclusion is real. shouldRunVisionBridge returns true only when the effective image modality is off, and the omni path in fileUtils requires modalities.image — they cannot swallow the same file. Converted fileData parts are invisible to isImagePart, so the bridge skips them; the sibling-of-the-bridge design holds in both funnels (CoreToolScheduler and ACP Session.runTool).
  • SSRF/redirect policy is reused, not reinvented. downloadMediaUrl builds on the existing isPrivateHost (loopback, single-label, .local/.internal/.lan, private ranges incl. IPv4-mapped IPv6) and isPermittedRedirect (same host modulo www., same protocol/port, no credentials) that WebFetch already uses, then adds Content-Length and streamed-byte ceilings, header/idle timeouts, and .part cleanup on every failure path. Cross-origin redirects are refused, so the host check can't be bypassed via redirect.
  • Identity-equality contract preserved in processToolResultOmniMedia — unchanged input returns the same array (tested), which callers rely on for content-length accounting.
  • Sniffed modality gates conversion, not the declared MIME — a tool result declared audio/* whose bytes are an MP4 container cannot slip past a video-disabled config (tested).
  • Guard ordering is cost-aware: byte guard on a cheap stat before hashing, token guard after the probe (needs metadata) but before copy/upload; unavailable estimates never reject; threshold 0 = attach estimates without rejecting until the formula is confirmed with the provider.
  • Gate-off paths stay untouched: fileUtils branches only behind isOmniDeliveryActive + per-modality config + matching pre-sniff; the converter's new audio branch only fires for fileData audio that previously textified.

Non-blocking observations (author's call, none of these gate merge):

  1. sanitizeErrorMessage in omni/index.ts strips POSIX path segments only; Windows-style paths in fs errors would still reach model-visible llmContent. Strictly better than S1 (no scrubbing at all), just not cross-platform yet.
  2. In atCommandProcessor.ts the omni barrel is dynamically imported before the gate check, so an @https://… mention loads the module even with omni disabled — a cheap config.isOmniEnabled?.() pre-check would avoid that. Negligible impact (cached import, URL tokens only).
  3. The six deprecated S1 aliases (isOmniVideoDeliveryActive, processVideoForOmniDelivery, …) keep S1-era imports stable — sensible on the experiment branch; worth sweeping when the experiment graduates.

The main new runtime flow, for orientation:

sequenceDiagram
    participant P1 as User prompt
    participant P2 as at-command processor
    participant P3 as tool-result funnel
    participant P4 as download module
    participant P5 as omni pipeline
    participant P6 as DashScope upload
    participant P7 as Model request
    P1->>P2: mentions media by path or URL
    P2->>P4: stream URL to downloads (SSRF policy, hashing)
    P4-->>P2: temp file with sha256
    P2->>P5: sniff, probe, byte and token guards, store
    P3->>P5: inline tool-result media (budgeted)
    P5->>P6: upload original bytes
    P6-->>P5: oss URL
    P5-->>P7: fileData part (image_url, input_audio or video_url)
Loading
Files changed (30 of 31 shown)
File What changed
packages/core/src/omni/index.ts Generalizes the S1 video pipeline to all modalities, attaches the token estimate to deliveries, scrubs absolute paths out of error messages
packages/core/src/omni/recognition.ts Three-modality magic-byte sniffing, cheap pre-sniff gate for the fallback decision, modality-mismatch rejection
packages/core/src/omni/download.ts New — streams URL media to a .part file with hashing, SSRF refusal, same-origin-only redirects, byte caps, header/idle timeouts
packages/core/src/omni/estimation.ts New — versioned raw-resource-v1 token estimator, missing metadata means unavailable rather than guessed
packages/core/src/omni/guard.ts New — byte ceiling plus token ceiling (0 means observability only), fail-closed error type
packages/core/src/omni/tool-result-media.ts New — converts inline tool-result media to oss fileData with a per-result budget of 8 parts and 128 MiB
packages/core/src/omni/ffmpeg.ts Generalizes the ffprobe wrapper to image/audio metadata (sample rate, channels)
packages/core/src/utils/fileUtils.ts Per-modality omni gate, pre-sniff decides omni vs legacy, image path skips local resize under omni
packages/core/src/core/openaiContentGenerator/converter.ts fileData audio branch emitting the bare oss URL as input_audio, format set widened to flac/ogg/m4a
packages/core/src/core/coreToolScheduler.ts Core funnel — runs omni tool-result conversion before the vision bridge
packages/cli/src/acp-integration/session/Session.ts ACP funnel — same conversion, dynamically imported from the omni subpath
packages/cli/src/ui/hooks/atCommandProcessor.ts Intercepts URL mentions, localization loop, per-URL failure isolation, graceful cancel path
packages/cli/src/config/settingsSchema.ts omni.transport.maxEstimatedTokens and omni.download.maxFileBytes settings
packages/cli/src/config/config.ts Wires the two new settings into loadCliConfig
packages/core/src/config/config.ts Config parameters and accessors for the two new limits
packages/core/src/index.ts Re-exports the omni API from the core barrel
packages/core/package.json Exports-map entry for the omni subpath
packages/vscode-ide-companion/schemas/settings.schema.json JSON schema for the two new settings
packages/core/src/omni/download.test.ts Tests — streaming hash, SSRF refusal, byte caps with and without content-length, redirects, abort
packages/core/src/omni/estimation.test.ts Tests — per-modality formulas plus the unavailable status
packages/core/src/omni/guard.test.ts Tests — defaults, fail-closed threshold, unavailable never rejects
packages/core/src/omni/tool-result-media.test.ts Tests — identity contract, sniffed-modality gate, budgets, per-part failure isolation
packages/core/src/omni/recognition.test.ts Adds sniff tests for image/audio magic bytes and non-media rejection
packages/core/src/core/openaiContentGenerator/converter.test.ts oss audio to input_audio tests, flac/ogg/m4a coverage, legacy audio-textify case repurposed to zip
packages/cli/src/acp-integration/session/Session.test.ts Stubs QWEN_RUNTIME_DIR so runtime-pinning assertions hold on self-hosted runners
packages/core/src/core/logger.test.ts Clears QWEN_RUNTIME_DIR for path-expectation tests on self-hosted runners
packages/cli/tsconfig.json Path alias for the core omni subpath
packages/cli/vitest.config.ts Vitest alias for the core omni subpath
packages/acp-bridge/tsconfig.json Path alias for the core omni subpath
packages/acp-bridge/vitest.config.ts Vitest alias for the core omni subpath
…and 1 more file vitest alias for the omni subpath in sdk-typescript

Test evidence (the PR's own CI)

Unattended run — PR code is never built or executed here; the evidence below is the PR's own CI read through the API at the reviewed commit.

Final CI results for 3842cb2 (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Test (ubuntu-latest, Node 22.x) ❌ failure
Classify PR ✅ success
Post Coverage Comment (ubuntu-latest, 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success

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

The skipped jobs are this repo's normal CI shape — macOS/Windows and the integration suite run only in the merge queue; the ubuntu suite is the PR signal. It was still running at review time (started 11:27 UTC, and this repo's full suite takes ~30 minutes), so there is no green attestation yet — the finalize job rewrites the table above once CI settles. Not verified: real-API behavior (19/19 E2E assertions on qwen3.5-omni-plus, byte-exact object invariant) — that is the author's claim from the PR description, not independently re-run here.

Sandboxed verification would settle the remaining gap: @qwen-code /verify — that the three modalities actually land on the wire as oss fileData (image_url / input_audio / video_url), that the token guard really fails closed before any copy or upload, and that gate-off paths stay byte-identical, cannot be observed from the diff, and this PR's suite mocks the upload channel. @qwen-code /tmux — for the TUI surface: the URL download card, the 404 error card, and Esc during a download.

中文说明

代码审查: 在读 diff 之前我先写了独立方案(把 S1 识别器扩到三模态、converter 按模态分支、在文件系统解析前拦截 @URL 并做 SSRF 安全的流式下载、带预算的第二工具结果漏斗、版本化估算器默认仅观测)。PR 与我的方案一致,且在我没想到的地方更进一步——不可嗅探格式的预嗅探回落、模态不匹配拒绝、单结果上传预算。未发现关键阻塞问题。

已逐行核实(而非只看描述):vision bridge 互斥真实成立(bridge 仅在 image 模态关闭时运行,omni 要求 modalities.image,二者不可能吞掉同一文件);SSRF/重定向策略复用现有 isPrivateHost/isPermittedRedirect,另加 Content-Length 与流式字节双上限、超时、失败必清 .part;identity-equality 契约保留(有测试);以嗅探模态而非声明 MIME 作门(有测试);守卫顺序按成本排布(stat → 哈希/探测 → token 守卫 → 拷贝/上传),unavailable 估算永不拒绝,阈值 0 仅观测;门控关闭路径不受影响。

非阻塞建议:错误信息清洗目前只覆盖 POSIX 路径(Windows 路径仍可能进入模型可见内容,较 S1 已是改进);atCommandProcessor 中 omni 动态导入发生在门控检查之前(影响可忽略);六个 S1 弃用别名建议在实验毕业时清理。

测试证据(本 PR 自己的 CI): 无人值守运行——此处不构建、不执行 PR 代码。ubuntu 套件在审查时仍在运行(约需 30 分钟),macOS/Windows/集成测试按仓库设计仅在合并队列运行。上表由 finalize 任务在 CI 落定后更新。真实 API 行为(19/19 E2E 断言等)为作者在 PR 描述中的声明,未在此独立复跑。

沙箱验证可补齐剩余缺口: @qwen-code /verify —— 三模态是否真的以 oss fileData 上线、token 守卫是否真在拷贝/上传前 fail closed、门控关闭路径是否逐字节一致,这些无法从 diff 看出,且本 PR 的单测 mock 了上传通道。@qwen-code /tmux —— TUI 面:URL 下载卡片、404 错误卡片、下载中按 Esc。

Qwen Code · qwen3.8-max

Reviewed at 3842cb2693aafa0dc9d92cb1400da06a26358897 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean, well-scoped vertical slice with no blockers; the holdouts are the still-running ubuntu suite and real-API behavior that rests on the author's evidence.

Honest reflection: the PR matches my independent proposal everywhere I had one, and beats it where I didn't — I hadn't thought through the pre-sniff fallback for formats the recognizer can't handle, and the sniffed-modality gate on tool results is a stricter call than I would have made. The scope question ("cut 80%?") doesn't bite here: S2's whole point is the full input surface behind one gate, and a single-modality remnant would defeat the slice. Nothing in the diff feels like it's trying too hard — the fail-closed discipline, the versioned estimator slot, and the observe-only default are proportional to a media pipeline whose failure mode is "the model silently didn't see what the user sent". Every change earns its place except the two self-hosted-runner test fixes, and those are justified environment repairs.

The property I cared about most — gate-off paths staying byte-identical — holds by construction: the omni branch in fileUtils is triple-gated (delivery active, modality on, matching pre-sniff), and the converter's new branch only fires for audio fileData that previously textified. Six months from now this reads like a module with boundaries (omni/ owns the pipeline, funnels just call it), not a feature smeared across the tree.

The 1/5 point I'm withholding: CI on the reviewed commit was still in flight when this review finished, and the real-API claims (19/19 E2E assertions, byte-exact object invariant on qwen3.5-omni-plus) are the author's, not independently re-run. So approval is deferred until CI lands green on 3842cb2693aafa0dc9d92cb1400da06a26358897 — if anything lands red, the deferred approval is withheld.

中文说明

置信度:4/5 —— 干净、范围得当的垂直切片,无阻塞项;剩余的是仍在运行的 ubuntu 套件,以及基于作者证据的真实 API 行为。

反思:PR 与我独立写出的方案处处一致,并在我没想到的地方更好——我没有考虑到不可嗅探格式的预嗅探回落,工具结果上以嗅探模态作门也比我自己的选择更严格。"砍掉 80% 会怎样"在这里不成立:S2 的意义就是"一个门控后的完整输入面",只留单一模态会摧毁这个切片。diff 中没有过度设计——fail-closed 纪律、版本化估算器槽位、默认仅观测,与"模型静默没看到用户发送内容"这种失败模式的媒体管线是相称的。除两处自托管 runner 测试环境修复外每个改动都有必要,而这两处是合理的环境修复。

我最看重的性质——门控关闭路径逐字节一致——在构造上成立:fileUtils 的 omni 分支三重门控(投递激活、模态开启、预嗅探匹配),converter 新分支只对先前会被文本化的音频 fileData 生效。六个月后回看,这更像一个有边界的模块(omni/ 拥有管线,漏斗只调用它),而不是涂抹在代码树各处的功能。

扣掉的 1 分:审查结束时该 commit 的 CI 仍在运行;真实 API 证据(19/19 E2E 断言、qwen3.5-omni-plus 上的字节不变式)来自作者声明,未独立复跑。因此批准推迟到 CI 在该 commit 全绿之后——若有检查变红,推迟的批准将被扣留。

Qwen Code · qwen3.8-max

Reviewed at 3842cb2693aafa0dc9d92cb1400da06a26358897 · re-run with @qwen-code /triage

The `await import()` of the omni graph inside processSingleFileContent and
resolveAtCommandQuery performs a real filesystem read under vitest (the SSR
transform writes and reads the module under /tmp/RP_*/ssr/), so mock-fs
based suites — pathReader's image cases — failed with ENOENT on a path they
never mocked.

Gate both call sites on the cheap synchronous config.isOmniEnabled() before
reaching for the import. Sessions without omni configured (every existing
test suite, and every user who has not opted in) now never load the module,
which also avoids the wasted module load on the common path. Delivery
behavior when omni IS enabled is unchanged: isOmniDeliveryActive still
performs the full five-condition gate check afterwards.
@LaZzyMan

LaZzyMan commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /verify

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 170 passed · 0 failed · 170 total

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

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

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

Verification report

PR 8512 verification — feat(omni): S2 input expansion — image/audio/URL sources and token-dimension transport guard

Verdict: merge-ready — 170/170 scripted assertions passed (0 unexpected failures), verified head 88d7e34005082459ea7575d9a93a460f2cf3608a (base dd188b0da625141ddfe4ba8151939b999e561cb6). Central claim proven load-bearing by A/B against a base build; all introduced guards pinned by non-vacuous tests (5/5 mutants killed); targeted gates green including the serve-fast-path bundle-closure check, whose liveness was proven by mutation.

中文摘要
  • 结论: merge-ready。170/170 脚本断言通过,0 个意外失败;验证头 88d7e34
  • A/B 结论(核心主张): omni 门控开启时,head 将 image/audio/video 三种模态全部以字节精确的原始字节经 DashScope 上传通道投递为 oss:// fileData(每个文件恰好 1 次 getPolicy + 1 次 OSS 上传,上传字节 sha256 与源文件一致);base(S1)仅 video 走该通道,image/audio 保持 inline(见下表 "Three-modality delivery A/B" 与截图 01-ab-delivery-base-vs-head.png)。门控关闭及 bmp/tiff 回落路径的 llmContent 在 head 与 base 之间深度相等(逐字节一致主张成立)。
  • 次要主张: token guard 默认 0=仅观测(estimate 随附、不拦截);设正阈值后在 store/upload 之前 fail closed(0 次 getPolicy、0 次上传、0 个对象落盘),错误信息含 estimate/method/阈值/设置键;estimate 公式与 recognized 元数据自洽。URL 下载策略 53 项断言全过(SSRF 拒绝含 169.254.169.254、跨域重定向拒绝、谎报 Content-Length 中途拦截、.part 清理、abort 清理)。tool-result 漏斗 25 项全过(8 件/128MiB 预算、嗅探模态门、identity 契约、失败隔离)。converter 音频 fileData→input_audio(裸 oss:// URL,flac/ogg/m4a 扩展)head 21/21、base 15/15 对照成立。
  • 突变矩阵: 5 个突变全部被其对应测试杀死,对照 289/289 绿;bundle-closure 门在把动态 import 突变为全 barrel 静态 import 后如预期失败(iconv-lite 553KB chunk 进入 acpAgent 静态闭包),证明门与修复均 load-bearing。
  • Findings(均非阻塞): ① PR 称 src/omni/ 77 个测试,实测 72;② URL 媒体路径(含 "URL-only prompt 丢弃投递" 的修复)在仓库内无回归测试——突变掉该修复后 cli 两个 atCommandProcessor 套件仍 69/69 全绿;③ SSRF 门为 URL 字符串判定、不做 DNS 钉扎(镜像既有 fetchWithPolicy 语义,属既有性质);④ logger.test.ts 在本容器内 head/base × 有无 QWEN_RUNTIME_DIR 全部 31F/21P,系环境问题(A/A 等价证明),与 f048f0d 的 hermeticity 修复无关。
  • 未覆盖: 真实模型 E2E、TUI 下载卡片、ACP 端到端、逐 commit 归因(depth-2 shallow,中间 commit 不可达,验证的是聚合 diff)、全仓测试套件。

Central claim + A/B

Central claim: with the omni gate active (omni enabled + trusted workspace + static DashScope key + proxy-matched baseUrl), image/audio/video inputs are delivered to the model as oss:// fileData parts via the DashScope upload channel, uploading the original bytes as-is; the base build only had this path for video.

The A/B drove the real compiled fileUtils.processSingleFileContent (head dist vs a base worktree rebuilt from HEAD^1, provenance-asserted via realpath) against a loopback fake DashScope origin that records getPolicy requests and OSS PostObject multipart uploads. Witness: evidence/01-ab-delivery-base-vs-head.png.

cell (gate on) head (S2) base (S1 control)
photo.png (image) text+oss — 1 getPolicy + 1 upload, uploaded sha256 == source sha256; dimensions+zoom-hint text part; raw-resource-v1 estimate attached text+inline, 0 uploads (A/B control)
tone2s.wav (audio) oss — 1 upload, byte-exact inline, 0 uploads (A/B control)
clip2s.mp4 (video) oss — 1 upload, byte-exact oss — 1 upload, byte-exact (S1 preserved)
gate-off image/video inline, 0 uploads inline, 0 uploads — llmContent deep-equal head vs base
gate-on image.bmp (unsniffable) inline, 0 uploads (pre-sniff fallback) inline — llmContent deep-equal head vs base

Flip count: 2/3 modalities (image, audio) move inline→oss; video and all gate-off/fallback paths unchanged. Every getPolicy carried Bearer sk-fake-static-key and the model param; OSS PostObject field order (policy fields before file) observed on the wire. Assertions: head 18/18, base 8/8, cross-build identity 3/3.

Secondary claim 1 — token-dimension transport guard

cell result
default (unset threshold), video delivers; estimate == ceil(w·h·ceil(dur·fps)/2048) recomputed from recognized.metadata (self-consistent oracle), method raw-resource-v1, status ok
audio default estimate == ceil(seconds·7); image == ceil(px/2048)
maxEstimatedTokens=1 OmniTransportGuardError naming estimate/method/omni.transport.maxEstimatedTokens; 0 getPolicy, 0 uploads, 0 object-store files (rejected before copy/upload)
maxEstimatedTokens=100000 delivers
unavailable estimate + positive threshold returns {status:'unavailable', estimatedTokenCount:0}, never rejects
byte dimension (maxFileBytes=1000) throws before upload on head and base (S1 control, 5/5)

Assertions: guard head 22/22, guard base 5/5.

Secondary claim 2 — URL source policy (downloadMediaUrl)

53/53. Highlights: happy path streams to .part with hash-while-write (sha256(body) == reported == on-disk); 404 → isolated OmniDownloadError + no .part leftover; SSRF refusals for 127.0.0.1, localhost, 10.x, 192.168.x, 172.16.x, 169.254.169.254 (cloud metadata), CGNAT 100.64.x, [::1], single-label and .internal hosts — fetch spy never invoked; same-host (www-strip) redirect followed, cross-origin and redirect-to-loopback refused; redirect loop capped; Content-Length ceiling enforced pre-body and actual-bytes ceiling mid-stream with .part cleanup; user abort rejects and removes .part. Witness: evidence/04-wire-oracle-harnesses.png.

Tool-result funnel (processToolResultOmniMedia)

25/25. Inline image part → oss:// fileData with byte-exact upload; 9 parts → exactly 8 uploads (9th inline); single >128 MiB part never uploads and array identity preserved; part declared audio/mp4 whose bytes sniff as video stays inline when video is disabled (sniffed-modality gate) while the video-declared control converts; non-media bytes → same array identity; gate off → same identity; nested functionResponse.parts converted in place; injected OSS 500 on first upload keeps that part inline while the second still converts.

Converter wire shape (head vs base)

Head 21/21, base 15/15. Head converts oss:// audio fileData to input_audio with the bare URL (no data: wrapper) for mpeg/wav/flac/ogg/m4a; base has no such branch (textified placeholder) — the A/B control. audio/amr stays a placeholder on both; image→image_url and video→video_url parity intact; inline audio keeps its data: URI on both.

Mutation matrix (vacuity)

mutant suite outcome
M1 guard.ts: token throw disabled guard.test.ts killedtoken guard > enabled: rejects above threshold… (1F/6P)
M2 download.ts: SSRF gate disabled download.test.ts killedrefuses private/loopback hosts (SSRF) (1F/6P)
M3 tool-result-media.ts: declared-MIME gate tool-result-media.test.ts killedgates on the SNIFFED modality… (1F/4P)
M3b tool-result-media.ts: budget 8→9 tool-result-media.test.ts killedenforces the per-result upload-count budget (expected "spy" to be called 8 times, but got 9 times)
M4 converter.ts: new audio-fileData branch disabled converter.test.ts killed — exactly the two new tests (2F/215P); clean attribution
control (unmutated) omni + converter 289/289 green

Witnesses: evidence/02-mutation-matrix-m1-m3.png, evidence/03-mutation-matrix-m3b-m4-control.png. No survivors among the guards this PR introduced. (M4's first attempt mutated the wrong — inline — occurrence and killed two pre-existing inline tests; the corrected second-occurrence mutation is the one reported, which also demonstrates the inline and fileData branches are independently pinned.)

Findings (non-blocking)

  1. Suggestion — no in-repo regression test for the URL media path, including the URL-only-prompt fix. atCommandProcessor.ts gained ~120 lines (URL interception, localization loop, and the urlMediaRefs.length === 0 early-return fix from commit 14409cb), but neither atCommandProcessor.test.ts nor atCommandProcessor.session.test.ts mentions URLs. Proof: reverting the early-return condition leaves both suites fully green (69/69). The PR's own E2E round covers this externally, but an in-repo test would pin a defect that already shipped once within this PR's development. House rule classifies missing tests as a Suggestion.
  2. Nit — test count drift. The PR text says npx vitest run src/omni/ is "77 tests"; measured at the verified head: 72 tests in 9 files (all passing).
  3. Note (pre-existing semantics, mirrored by design) — SSRF gate is URL-string based. isPrivateHost never resolves DNS, so a public hostname A-recording to a private IP would bypass the gate. download.ts deliberately mirrors fetchWithPolicy (same property), so this is a pre-existing platform limitation, not a regression; worth a platform-level look eventually (DNS pinning / post-resolution re-check).
  4. Note (environmental) — logger.test.ts fails identically in every arm here. 31F/21P across head/base × {no env, QWEN_RUNTIME_DIR missing dir, existing dir} — six identical cells, so the failure is this container's environment (A/A parity), not the PR and not the hermeticity fix of commit f048f0d. The fix is neither credited nor blamed by this round; its target scenario (a runner exporting QWEN_RUNTIME_DIR) could not be distinguished here because the suite fails for another environmental reason regardless.

Not covered

  • Real-model E2E (no DashScope credential in this sandbox), TUI download cards / Esc-during-download UX, ACP Session.runTool end-to-end, Qwen OAuth behavior beyond the gate predicate, download consent UX (deferred by design).
  • Per-commit attribution: the checkout is depth-2 (git rev-list HEAD^1..HEAD^2 returns 1 while the metadata lists 8 commits — the shallow-boundary trap); all intermediate commits are unreachable, so the aggregate HEAD^1..HEAD diff was verified instead.
  • Repo-wide test suite and repo-wide typecheck; targeted gates only: core src/omni/ (72/72) + converter (217/217 incl. new), cli atCommandProcessor* + settingsSchema (105/105), Session.test.ts (460/460), config.test.ts (315/315), typecheck core + cli (exit 0), check:serve-fast-path-bundle (pass; liveness proven — mutating the ACP dynamic import to a full-barrel import fails the gate with iconv-lite … chunk-… (553070 bytes) … static path: acpAgent → chunk, witness evidence/05-closure-gate-pass-and-liveness.png).
  • The verify container ships no ffmpeg/ffprobe; I installed static builds (ffmpeg 7.0.2 / ffprobe 4.0.2) into a scratch dir on PATH — the omni pipeline's hard prerequisite.
  • URL success-path cells use an injected fetchFn encoding real HTTP semantics, because loopback hosts are — correctly — refused by the SSRF gate and the container has no public egress; the SSRF/refusal cells run against the real URL parser with a fetch spy asserting zero calls.

Methodology

Environment: CI merge-ref checkout (HEAD = merge, HEAD^1 = base tip, HEAD^2 = verified head), npm ci + npm run build pre-run at head; base control built in a scratch worktree at HEAD^1 (tsc --build of packages/core only, reusing the root node_modules — the PR leaves the lockfile untouched; harnesses import base/head dist by absolute path and assert realpath provenance before running). The gate was made active against the loopback fake origin via the real DASHSCOPE_PROXY_BASE_URL proxy-match seam plus a static-key stub Config (configuration seam only — the pipeline, uploader, recognizer, store, and converter are the real compiled dist code). The fake DashScope origin emulates getPolicy + OSS PostObject and records both sides of the wire; byte-exactness asserted by sha256 of the multipart file part vs the source. Assertions: 170 pass / 0 fail / 170 total (per-suite counts in logs/*.log [COUNTS] lines). Raw logs, harness .mjs files, cell-result JSONs, and the five evidence PNGs live in this artifact directory; mutation and gate liveness runs restore every mutated file (verified by empty git status afterwards).

Evidence images

01-ab-delivery-base-vs-head

02-mutation-matrix-m1-m3

03-mutation-matrix-m3b-m4-control

04-wire-oracle-harnesses

05-closure-gate-pass-and-liveness

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

Qwen Code · sandboxed verification

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ This run could not certify that any of this diff was reviewed. Suggestions are inline. Not reviewed: the entire diff, the linked-issue fidelity pass, the whole-diff test-coverage check, the removed-behavior audit — its prompt was built, but no agent on record was launched with it. Not reviewed: reverse audit — its prompt was built, but no agent was launched with it — the pass that hunts what the rest of the review missed ran, if at all, without the method its brief carries, and cannot be certified.

中文说明

⚠️ 本次运行无法证明这个 diff 的任何部分经过了审查。 建议见行内评论。 未审查:整个 diff、关联 issue 一致性检查、全 diff 测试覆盖检查、删除行为审计——它的 prompt 已构建,但没有任何 agent 有记录用它启动过。 未审查:反向审计——它的 prompt 已构建,但没有 agent 用它启动——负责搜寻评审其余部分遗漏问题的这道工序,即便运行过,也缺失了 brief 承载的方法,无法作证。

— claude-opus-4-6 via Qwen Code /review (v0.21.5)

Comment thread packages/cli/src/ui/hooks/atCommandProcessor.ts
Comment thread packages/core/src/omni/index.ts
Comment thread packages/core/src/omni/ffmpeg.ts
Comment thread packages/core/src/omni/recognition.ts

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ This run could not certify that any of this diff was reviewed. Suggestions are inline. 4 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Not reviewed: the entire diff — no agent reported covering it; nobody read it. Not reviewed: every dimension — none of the 15 required agents is on record as launched with a prompt this skill built, so this diff was reviewed, if at all, from prompts the run wrote for itself: no record shows the severity bar, the finding format or this project's own rules reaching an agent. Not reviewed: verification and reverse audit — neither the verifier nor the reverse auditor was launched with a prompt this skill builds — the posted findings were ruled on, and the misses the rest of the review left were hunted, if at all, without the briefs this skill certifies against.

中文说明

⚠️ 本次运行无法证明这个 diff 的任何部分经过了审查。 建议见行内评论。 4 条建议级发现无法锚定到改动行,已丢弃;此处无需进一步处理。 未审查:整个 diff——没有 agent 报告覆盖过这部分,也没有人读过它。 未审查:所有维度——15 个必需 agent 中没有任何一个有记录表明是用本 skill 构建的 prompt 启动的,这个 diff 即便被审查过,也是基于这次 run 自行编写的 prompt:没有记录表明严重级别标准、发现格式或本项目自己的规则到达过任何 agent。 未审查:验证与反向审计——验证 agent 与反向审计 agent 都没有用本 skill 构建的 prompt 启动——发布的发现即便被裁定过、评审其余部分遗漏的问题即便被搜寻过,也都缺失了本 skill 用以认证的 brief。

— claude-opus-4-6 via Qwen Code /review (v0.21.5)

Comment thread packages/core/src/omni/recognition.ts Outdated
Comment thread packages/core/src/omni/download.ts Outdated
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Qwen Code review timed out. Qwen review timed out after 21600 seconds (of the 360-minute budget). This run already used the maximum 360 minute timeout. See workflow logs.

@qqqys qqqys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] The new URL-media path's SSRF gate at packages/core/src/omni/download.ts:79 only calls isPrivateHost(url), which classifies the hostname text and literal IPs but never resolves a hostname. A dotted public-looking hostname is therefore accepted even when its A/AAAA record resolves to 127.0.0.1, 169.254.169.254, or a private RFC1918 address (including DNS-rebinding and split-horizon cases); the global fetch at line 109 then connects to that address. With a media-producing internal endpoint, the response is also promoted and uploaded, so this defeats the new path's stated private and loopback SSRF protection and can disclose local or cloud-internal data.

Resolve and validate every target hostname to globally routable addresses immediately before each outbound fetch, including accepted redirect hops, rejecting the request if any candidate is private, loopback, link-local, or otherwise non-public. Please add a regression test using a hostname that appears public syntactically but resolves to a private address.

SSRF (review-blocking): downloadMediaUrl's gate called only isPrivateHost,
which classifies hostname text and IP literals but never resolves. A
syntactically public name whose A/AAAA record points at 127.0.0.1,
169.254.169.254 or an RFC1918 address was therefore accepted, and because
this path uploads the fetched bytes to DashScope, an internal endpoint's
response would be exfiltrated.

Add findNonPublicAddress() to utils/fetch.ts: it resolves the hostname via
dns.lookup({all: true}) and rejects if ANY returned address is non-public,
since the connect may pick any of them. IP literals short-circuit without a
lookup. Extract isPrivateAddress() as the shared bare-address classifier so
isPrivateIp keeps one implementation.

download.ts calls it inside the redirect loop, immediately before each
connect, so every accepted hop is re-validated — a permitted same-host
redirect can still re-resolve to a private address between hops.

Two deliberate choices, both recorded in the doc comment: the helper is NOT
wired into fetchWithPolicy, because WebFetch intentionally supports intranet
FQDNs resolving to private addresses, so applying it there would be a silent
breaking change; and DNS failure returns null rather than failing closed,
because the connect that follows reports the real error and failing closed
would turn a resolver blip into something the user cannot act on. The
residual check-then-connect race is documented too: fetch resolves again, so
closing it fully needs an agent that pins the connect to a vetted address,
which undici does not expose portably.

Also fixed: sniffMediaType classified any file starting with 0xFF 0xFE (the
UTF-16 LE BOM) as audio/mpeg, because 0xFE passes the frame-sync mask. Real
MPEG frames never use 0xFE — the layer bits would be 11, reserved — so
excluding it costs no genuine detection and keeps the "null for non-media"
contract honest for callers without a secondary modality gate.

Tests for the previously uncovered branches reviewers flagged:
- download: public-looking host resolving to 127.0.0.1/169.254.169.254/
  10.1.2.3; mixed A records where only one is private; per-hop re-check
  asserting the redirect is refused before the second fetch; DNS failure;
  the ?? fetch fallback via a globalThis spy; and the production DNS path
  asserting dns.lookup receives {all: true, verbatim: true}
- readMediaViaOmniDelivery: image gets the resolution + zoom_image hint
  parts, audio gets a bare fileData, failure yields an error result and
  never inline base64
- probeMediaMetadata: the audio branch reads the audio stream (proven with a
  file carrying both h264 and aac), the image branch reports no duration
- sniffFileModality: recognized headers, non-media, and an absent path
- atCommandProcessor URL pipeline: a URL with omni active becomes a fileData
  part, the same URL with omni disabled falls through as text without
  downloading, and a URL-only prompt does not hit the no-content early
  return
@LaZzyMan

LaZzyMan commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

Superseded. The approach described below (preflight findNonPublicAddress validation) was correctly rejected in review: validating without binding the connection is check-then-connect, and the claim that undici cannot pin a connection portably was factually wrong. The actual fix — resolve-and-pin via resolveNetworkTarget + Agent({connect: {lookup}}), failing closed — is in the follow-up: #8512 (comment)

Thanks — all findings are addressed in the latest push.

Critical (SSRF, @qqqys)

You're right that isPrivateHost only classifies hostname text and IP literals, so a public-looking name whose A/AAAA record points at loopback / link-local / RFC1918 got through, and the fetched bytes are then uploaded to a third party. Fixed:

  • utils/fetch.ts — extracted isPrivateAddress (bare-address classifier, shared with the existing isPrivateIp) and added findNonPublicAddress(url, resolver?). It resolves the hostname via dns.lookup(h, {all: true}) and rejects if any returned address is non-public, since the connect may pick any of them. IP literals short-circuit without a lookup.
  • omni/download.ts — called inside the redirect loop, immediately before each connect, so every accepted hop is re-validated (a permitted same-host redirect can still re-resolve elsewhere between hops).

Two deliberate choices worth flagging for review:

  1. Not wired into fetchWithPolicy. WebFetch intentionally supports intranet FQDNs that resolve to private addresses — that's documented behavior in CONNECTION_LEVEL_ERROR_CODES. Applying the resolving gate there would be a silent breaking change for existing users, so the helper lives in the shared module (for testability and reuse) but is called only from the omni download path, where the bytes leave the machine.
  2. DNS failure returns null (fail-open). The connect that follows fails anyway, and failing closed would turn a transient resolver blip into an error the user can't act on.

The residual check-then-connect race is documented in the helper's doc comment: fetch resolves again, so a record flipping between the two lookups isn't caught. Closing it fully needs an agent that pins the connect to a vetted address, which undici doesn't expose portably. Resolving immediately before each connect narrows the window to one syscall pair and blocks the practical attack (a low-TTL record answering public once, then private).

Regression tests (omni/download.test.ts, +7, 14 total) — including the case you asked for: a syntactically public host resolving to a private address, covering 127.0.0.1, 169.254.169.254, and 10.1.2.3; a mixed-A-record case where only the second address is private; a public-resolving host that proceeds; a per-hop test asserting the redirect target is refused before fetchFn is called a second time; a DNS-failure case; and one that injects no resolver at all, asserting the production path calls dns.lookup with {all: true, verbatim: true} (the resolver seam is test-only, so without this the real wiring — and the all option the multi-address check depends on — would be unexercised). The suite mocks node:dns/promises so tests that don't inject a resolver never touch real DNS.

Suggestions (@doudouOUC)

ID Finding Status
R1-1 URL media pipeline untested Fixed — 3 tests in atCommandProcessor.test.ts: URL with omni active → fileData part (+ URL kept verbatim in the prompt text, success card asserted); same URL with omni disabled → no download, falls through as text; URL-only prompt → doesn't hit the no-content early return
R1-2 readMediaViaOmniDelivery image branch untested Fixed — 3 tests in index.test.ts: image → 2 parts with 1920x1080 + zoom_image; audio → bare fileData, no hint; failure → error result, never inline base64
R1-3 probeMediaMetadata audio/image branches untested Fixed — 3 tests in ffmpeg.test.ts. The audio test probes a file carrying both h264 and aac streams, so reading videoStream?.codec_name (the copy-paste slip you described) would fail it
R1-4 sniffFileModality untested Fixed — 3 tests in recognition.test.ts: recognized headers → video/audio/image; non-media + empty file → null; absent path → null without throwing
R1-5 MPEG frame-sync false-positives on UTF-16 LE BOM Fixed as suggested — added header[1] !== 0xfe. A real MPEG frame never uses 0xFE (layer bits would be 11, reserved), so this costs no genuine detection. Test asserts the BOM returns null while 0xFB/0xF3 syncs still detect
R1-6 ?? fetch fallback untested Fixed — a test omits fetchFn and asserts globalThis.fetch was called via vi.spyOn

On the review-pr check

review-pr is red because the review bot's own run timed out after its full 360-minute budget, and both review comments self-report that no agent was launched with the built prompt ("no agent on record was launched with it"). That's the review harness failing, not a signal about this diff — every actual build/lint/test job on the PR is green.

@LaZzyMan

LaZzyMan commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /verify

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 188 passed · 0 failed · 188 total

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

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

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

Verification report

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

Sandboxed verification: ✅ passed — merge-ready (agent verdict) - follow-up round at new head fa3528317

Ran the PR in an isolated, token-free container: A/B against the base build and the previous verified head, mock-free harness assertions (including an LD_PRELOAD getaddrinfo DNS seam), mutation matrix, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check.

Scripted assertions: 188 passed · 0 failed · 188 total

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

本轮在隔离、无凭证容器中对新头 fa35283(上一轮为 88d7e34)重新执行全部测量,并针对增量提交 "fix(omni): resolve DNS before each media fetch and close review gaps" 做深度探针。188/188 脚本断言通过,0 意外失败。

  • 上轮发现状态:① URL 媒体路径(含 URL-only prompt 修复)无仓库内回归测试 → 已修复(新增 3 个 atCommandProcessor 测试;突变 M7 还原修复即杀死其中 2 个,认同);② 测试计数漂移(PR 称 77)→ 仍成立(nit),实测 89/9 文件;③ SSRF 门仅按 URL 字符串判定 → 已修复(DNS 解析门 A/B:head 22/22 vs 前头 9/9,5 个洞单元翻转,逐跳复查经 shim 日志物理证实);④ logger.test.ts 环境性失败 → 仍成立(环境性),head/base A/A 同签名 31F/21P。
  • 核心主张(复测):门控开启时 image/audio/video 三模态以字节精确原始字节经 DashScope 通道投递 oss://(head 34/34 vs base 8/8,翻转 2/3 模态;gate-off 与 bmp 回落 llmContent 跨构建深度相等 3/3)。
  • 增量主张(新证)findNonPublicAddress 在每次连接前(含每个重定向跳)解析 DNS,任一解析地址非公开即拒(混合 A 记录亦拒);IP 字面量短路不解析;DNS 失败按设计 fail-open;UTF-16 LE BOM 不再误判为 MPEG 同步(head 12/12 vs 前头 12/12 复现旧 bug)。
  • 突变矩阵:10 个突变全部被杀(含新增 DNS 门 M5、BOM 排除 M6、URL-only 修复 M7、fail-closed 错误路径 M9),0 幸存。
  • 未覆盖:真实模型 E2E、TUI 下载卡片、ACP 端到端、逐 commit 归因(shallow)、仓库级套件、下载 header/idle 超时实时单元。
Verification report

PR 8512 verification (follow-up round) — feat(omni): S2 input expansion — image/audio/URL sources and token-dimension transport guard

Verdict: merge-ready — 188/188 scripted assertions passed (0 unexpected failures), verified head fa3528317c31b4e8501193370a5672b695dec536 (base dd188b0da625141ddfe4ba8151939b999e561cb6; delta control = previous verified head 88d7e34005082459ea7575d9a93a460f2cf3608a, reachable locally). This is a follow-up round: every carried-forward measurement was re-run at the new head; new probes target the delta commit fa35283 (DNS-before-fetch SSRF gate, UTF-16 BOM sniff fix, new regression tests).

Previous-finding status

# finding (prev round) severity status at fa35283
1 no in-repo regression test for the URL media path incl. the URL-only-prompt fix Suggestion fixedfa35283 adds 3 URL tests to atCommandProcessor.test.ts; reverting the urlMediaRefs.length === 0 early-return fix (mutant M7) now kills 2 of them (localizes a media URL into a fileData part…, does not hit the no-content early return for a URL-only prompt). Agree.
2 test-count drift: PR text says 77 omni tests Nit stands (nit) — measured at new head: 89 tests in 9 files (all passing; the delta added tests). PR body still says 77.
3 SSRF gate URL-string based, no DNS resolution Note fixed by the delta — see "Delta claim 1" below: 5 hole cells flip between prev-head and head; per-hop re-check physically observed. Residual check-then-connect race and the deliberate non-wiring into fetchWithPolicy are documented in the code; agree with the documented rationale.
4 logger.test.ts fails identically in every arm (environmental) Note stands (environmental) — re-measured: 31F/21P at new head; base tree A/A cell identical 31F/21P (same failure names). Not the PR, not the f048f0d hermeticity fix.

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

Central claim (unchanged): with the omni gate active, image/audio/video inputs are delivered as oss:// fileData via the DashScope upload channel with original bytes as-is; base (S1) had this path only for video. Re-driven against the real compiled fileUtils.processSingleFileContent (head dist vs base worktree rebuilt from HEAD^1; provenance asserted via realpath, zero internal @qwen-code imports in the loaded dists). Witness: evidence/01-ab-delivery-base-vs-head.png (live re-run).

cell (gate on) head (S2) base (S1 control)
photo.png (image) text+oss — 1 getPolicy + 1 upload, uploaded sha256 == source; 8x8 dimensions + zoom-hint text part; estimate 1 (raw-resource-v1) text+inline, 0 uploads
tone2s.wav (audio) oss — 1 upload byte-exact; estimate 14 == ceil(2.0s×7) inline, 0 uploads
clip2s.mp4 (video) oss — 1 upload byte-exact; estimate 40 == ceil(64·64·ceil(2·10)/2048) oss — 1 upload byte-exact (S1 preserved)
gate-off image/video inline, 0 uploads inline — llmContent deep-equal head vs base
gate-on image.bmp inline, 0 uploads (pre-sniff fallback) inline — llmContent deep-equal

Flip: 2/3 modalities (image, audio) inline→oss; video + all gate-off/fallback paths unchanged. Object store holds byte-exact objects for all three modalities; OSS multipart field order policy-fields-before-file; every getPolicy carries Bearer sk-fake-static-key + model. Counts: head 34/34, base 8/8, cross-build identity 3/3.

Token guard (head): maxEstimatedTokens=1 rejects with estimate/method/setting in the message and 0 getPolicy / 0 uploads / 0 objects (fail closed before copy/upload); 100000 delivers; unavailable estimate never rejects. Byte dimension rejects pre-upload on head and base.

Delta claim 1 — DNS-before-fetch SSRF gate (the load-bearing fix)

Method: an LD_PRELOAD getaddrinfo shim (compiled with gcc, harness/dns_shim.c) answers controlled A records for *.verify-ssrf.test names and delegates everything else — the production resolver path (findNonPublicAddressdns.lookup({all:true,verbatim:true}) → libc) runs unmodified; the injected fetchFn is a recording spy so no real connect ever happens. Witness: evidence/02-dns-ssrf-ab-head-vs-prevhead.png.

cell head fa35283 prev-head 88d7e34 (control)
public-looking name → 127.0.0.1 refused pre-fetch, 0 fetches, "resolves to 127.0.0.1", no .part accepted, 1 fetch (hole)
name → 169.254.169.254 (metadata) refused accepted (hole)
name → 10.1.2.3 (RFC1918) refused accepted (hole)
mixed A records (public+private) refused (ANY-private) accepted (hole)
same-host redirect re-resolving to 127.0.0.1 refused at hop 2 after exactly 1 fetch follows rebind, 2 fetches (hole)
name → all-public downloads, sha256-match (symmetric control) downloads (control)
public IP literal accepted with zero resolver lookups (short-circuit) n/a
private IP literal / text-gate set (18 hosts incl. CGNAT, [::1], .internal, single-label) refused by pre-existing text gate, 0 fetches same (unchanged surface)
DNS failure gate passes (fail-open by design), fetch proceeds same

5/5 hole cells flip. The shim's lookup log is the physical witness: head resolves each refused name once (twice for the rebind: 93.184.216.34 then 127.0.0.1); prev-head's log is empty — it never resolves. Counts: head 22/22, prev-head 9/9.

Delta claim 2 — UTF-16 BOM no longer mis-sniffed as MPEG

[FF FE …]null at head vs audio/mpeg at prev-head (byte-level and file-level sniffFileModality); five genuine sync headers (FF FB/E0/E2/FF/FA) + ID3 still detect on both arms; png/wav/mp4 fixtures still classify. 12/12 per arm.

Delta claim 3 — new regression tests are load-bearing

Mutant M7 (revert urlMediaRefs.length === 0 in the early return) kills the two new atCommandProcessor tests; M8 (image zoom-hint part removed) kills adds a resolution + zoom_image hint part for images; M9 (fail-closed catch mutated to emit inline base64) kills fails closed with an error result (never inline base64) on failure; M5 (per-hop DNS gate disabled) kills exactly the four new download tests, with behavioral mismatches (missing resolves to error, dns.lookup spy never called with the host, rebind loop instead of refusal) — not import/compile breakage.

Secondary claims (re-measured)

  • Download policy 38/38: hash-while-write, 404 isolation + .part cleanup, 18 SSRF text-gate refusals with zero fetches, www-strip same-host redirect followed, cross-origin / loopback / credentialed redirects refused, loop capped at 6 fetches, Content-Length ceiling pre-body, lying-CL mid-stream ceiling with .part cleanup, user abort rejects and removes .part.
  • Tool-result funnel (head 12/12): byte-exact conversion; 9 parts → exactly 8 uploads; 64MiB converts then 65MiB > remaining stays inline (byte budget); declared-audio/video-bytes stays inline under video-disabled while video-declared control converts (sniffed gate); identity preserved for non-media and gate-off; nested functionResponse.parts converted; injected OSS 500 isolates one part.
  • Converter head 10/10 vs base 8/8: oss:// audio fileData → input_audio with bare URL for mpeg/wav/flac/ogg/m4a (base: placeholder, A/B control); audio/amr placeholder on both; audio-disabled placeholder; image/video parity; inline audio keeps data: URI on both.

Mutation matrix (10 mutants, 0 survivors)

mutant suite outcome
M1 guard token-throw disabled guard.test.ts killed (1F/6P)
M2 download SSRF text gate off download.test.ts killed (1F/13P)
M3 funnel sniffed→declared gate tool-result-media.test.ts killed (1F/4P)
M3b funnel budget 8→9 tool-result-media.test.ts killed (1F/4P)
M4 converter audio-fileData branch off converter.test.ts killed (2F/215P, the two new tests)
M5 download per-hop DNS gate off download.test.ts killed (4F/10P, the four new DNS tests)
M6 BOM exclusion removed recognition.test.ts killed (1F/14P)
M7 URL-only early-return reverted atCommandProcessor.test.ts killed (2F/62P, the two new URL tests)
M8 image zoom-hint part removed index.test.ts killed (1F/11P)
M9 fail-closed catch → inline fallback index.test.ts killed (1F/11P)

Witness: evidence/03-mutation-matrix-summary-and-m5-live.png (summary + live M5 re-run). Unmutated controls green: core omni+converter 306/306, cli atCommandProcessor 72/72. All mutated files restored (empty git status afterwards).

Findings (non-blocking)

  1. Nit (carried) — test-count drift. PR body says src/omni/ is "77 tests"; measured at fa35283: 89 tests in 9 files, all passing.
  2. Note (carried, environmental) — logger.test.ts 31F/21P in every arm here. Head and base A/A parity re-confirmed with identical failing-test names; unrelated to the PR.
  3. Note (reviewed, not a defect) — documented residual DNS risk. findNonPublicAddress returns null on resolver failure (fail-open; the connect then reports the real error) and a check-then-connect TOCTOU window remains; both are documented in the code with rationale, and the helper is deliberately NOT wired into fetchWithPolicy (WebFetch supports intranet FQDNs). The per-hop re-check shrinks the practical rebinding window as claimed.

Not covered

  • Real-model E2E (no DashScope credential), TUI download cards / Esc-during-download UX, ACP Session.runTool end-to-end over the wire (suite-level only: 460/460), Qwen OAuth beyond the gate predicate, download consent UX (deferred by design).
  • Per-commit attribution: checkout is depth-2 (shallow-boundary trap: rev-list HEAD^1..HEAD^2 = 1 vs 9 commits in metadata); the aggregate diff was verified; the delta commit was additionally isolated because the previous verified head is reachable locally.
  • Repo-wide test suite/typecheck; targeted gates only: core omni (89/89) + converter (217/217) + config (474/474), cli atCommandProcessor (72/72) + settingsSchema (36/36) + Session (460/460), typecheck core+cli exit 0, check:serve-fast-path-bundle pass.
  • Download header/idle timeouts (30s/60s) not exercised in real time.
  • The verify container ships no ffmpeg/ffprobe; static builds (ffmpeg/ffprobe 7.0.2) were installed to a scratch PATH dir — the omni pipeline's hard prerequisite.

Methodology

Environment: CI merge-ref checkout (HEAD merge, HEAD^1 base tip, HEAD^2 verified head; previous verified head reachable as a commit object), npm ci + npm run build pre-run at head. Base control rebuilt from HEAD^1 and delta control from 88d7e34 in scratch worktrees (tsc --build of packages/core, root node_modules symlinked — lockfile untouched; the eight nested packages/core/node_modules deps symlinked too after the first build attempt proved they are package-local installs); provenance asserted by realpath and by grepping loaded dists for internal @qwen-code imports (none). Harnesses import compiled dist by absolute path and drive the real pipeline against a loopback fake DashScope origin recording both sides of the wire (getPolicy + OSS PostObject multipart parsed for field order and file-part sha256); the DNS seam is an LD_PRELOAD getaddrinfo shim, not a code mock. Gate activated via the DASHSCOPE_PROXY_BASE_URL proxy-match seam + static-key stub Config. Bundle-gate and typecheck liveness proven by planted violations (full-barrel import → gate fails with iconv-lite … 553070 bytes … static path: acpAgent → chunk; planted type error → tsc fails). Raw logs, harness .mjs/.c sources, cell JSONs, and evidence PNGs live in this artifact directory; witness evidence/04-wire-oracle-harnesses.png shows the policy/funnel/converter harnesses' live re-run.

Evidence images

01-ab-delivery-base-vs-head

02-dns-ssrf-ab-head-vs-prevhead

03-mutation-matrix-summary-and-m5-live

04-wire-oracle-harnesses

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

Qwen Code · sandboxed verification

@LaZzyMan

LaZzyMan commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 155 passed · 0 failed · 155 total

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

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

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

Verification report

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

Sandboxed verification: ✅ passed — merge-ready (agent verdict) - follow-up round at head fa3528317 (identical OID to the previous verified head; all measurements re-run fresh)

Ran the PR in an isolated, token-free container: A/B against the base build and the previous verified head, mock-free harness assertions (including an LD_PRELOAD getaddrinfo DNS seam), mutation matrix, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check.

Scripted assertions: 155 passed · 0 failed · 155 total

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

本轮在隔离、无凭证容器中重新执行全部测量。新头 fa35283 与上一轮验证头 OID 完全相同(增量为零),因此无新探针,全部沿用测量均在新运行中复测:155/155 脚本断言通过,0 意外失败。

  • 上轮发现状态:① URL 媒体路径无仓库内回归测试 → 已修复(复测:突变 M7 还原修复即杀死 2 个新 URL 测试,认同);② 测试计数漂移(PR 称 77)→ 仍成立(nit),复测 89 测试/9 文件;③ SSRF 门仅按 URL 字符串判定 → 已修复(复测:5 个洞单元在 head 与前头 88d7e34 之间翻转,逐跳 DNS 复查由 shim 日志物理证实);④ logger.test.ts 环境性失败 → 仍成立(环境性),head/base A/A 同签名 31F/21P、失败名集合逐字节相同。
  • 核心主张(复测):门控开启时 image/audio/video 三模态以原始字节经 DashScope 通道投递 oss://(head 25/25 vs base 9/9;2/3 模态翻转;gate-off 与 bmp 回落 llmContent 跨构建深度相等 3/3)。
  • 增量主张(复测)findNonPublicAddress 每次连接前解析 DNS(含重定向逐跳),任一地址非公开即拒;IP 字面量短路;DNS 失败按设计 fail-open;UTF-16 LE BOM 不再误判为 MPEG(head 12/12 vs 前头 12/12 复现旧 bug)。
  • 突变矩阵:10/10 全杀,0 幸存,全部文件恢复干净。
  • 未覆盖:真实模型 E2E、TUI 下载卡片、ACP 端到端(仅套件级)、逐 commit 归因(shallow)、仓库级套件、下载 header/idle 超时实时单元。
Verification report

PR 8512 verification (follow-up round) — feat(omni): S2 input expansion — image/audio/URL sources and token-dimension transport guard

Verdict: merge-ready — 155/155 scripted assertions passed (0 unexpected failures), verified head fa3528317c31b4e8501193370a5672b695dec536 (base dd188b0da625141ddfe4ba8151939b999e561cb6; delta control = previous verified head 88d7e34005082459ea7575d9a93a460f2cf3608a, reachable locally). This round's verified head OID is identical to the previous round's, so the delta since that round is zero: there are no new probes; every carried-forward measurement below was rebuilt and re-run fresh in this container (base and prev-head control dists rebuilt from scratch worktrees; all harnesses re-executed).

Previous-finding status

# finding (prev round) severity status at fa35283 (re-measured)
1 no in-repo regression test for the URL media path incl. the URL-only-prompt fix Suggestion fixed — re-verified: mutant M7 (revert urlMediaRefs.length === 0 early-return clause) kills exactly the two new URL tests in atCommandProcessor.test.ts (2F/62P) with behavioral mismatches. Agree.
2 test-count drift: PR body says 77 omni tests Nit stands (nit) — re-measured at this head: 89 tests in 9 files under src/omni/, all passing (7+4+10+13+15+9+5+14+12). PR body still says 77.
3 SSRF gate URL-string based, no DNS resolution Note fixed — re-measured: 5/5 hole cells flip between prev-head and head; per-hop re-check physically observed via the shim's lookup log (public then private on the rebind cell). Residual check-then-connect race and the deliberate non-wiring into fetchWithPolicy are documented in the code; agree with the documented rationale.
4 logger.test.ts fails identically in every arm (environmental) Note stands (environmental) — re-measured: 31F/21P at head; base-tree A/A cell identical 31F/21P with a byte-identical failing-test-name set (25 unique names; diffs only in timing suffixes). Not the PR.

Central claim + A/B (re-run)

Central claim: with the omni gate active, image/audio/video inputs are delivered as oss:// fileData via the DashScope upload channel with original bytes as-is; base (S1) had this path only for video. Re-driven against the real compiled fileUtils.processSingleFileContent (head dist vs base worktree rebuilt from HEAD^1; provenance asserted by realpath, by zero internal @qwen-code imports in the loaded dists, and by differential markers — base dist lacks sniffFileModality, prev-head dist lacks findNonPublicAddress). Witness: evidence/01-ab-delivery-base-vs-head.png (live re-run this round).

cell (gate on) head (S2) base (S1 control)
photo.png (image) text+oss — 1 getPolicy + 1 upload, uploaded sha256 == source; 8x8 dimensions + zoom-hint text part; estimate 1 (raw-resource-v1) text+inline legacy overview, 0 uploads
tone2s.wav (audio) oss — 1 upload byte-exact; estimate 14 == ceil(2.0s×7) inline, 0 uploads
clip2s.mp4 (video) oss — 1 upload byte-exact; estimate 40 == ceil(64·64·ceil(2·10)/2048) oss — 1 upload byte-exact (S1 preserved)
gate-off image / video inline, 0 uploads — llmContent deep-equal head vs base (3/3) inline
gate-on image.bmp inline, 0 uploads (pre-sniff fallback) — deep-equal inline

Flip: 2/3 modalities (image, audio) inline→oss; video and all gate-off/fallback paths unchanged. Every getPolicy carries Bearer sk-fake-static-key + model; OSS multipart field order is policy-fields-before-file. Counts: head 25/25, base 9/9 (control reds encoded as assertions expecting red), cross-build identity 3/3.

Token guard (head): maxEstimatedTokens=1 rejects with estimate/method/threshold/setting in the message and 0 getPolicy / 0 uploads / 0 objects (fail closed before copy/upload); 100000 delivers; byte dimension rejects pre-upload on head and base.

Delta claims (re-run; delta control = prev-head 88d7e34)

DNS-before-fetch SSRF gate. LD_PRELOAD getaddrinfo shim (harness/dns_shim.c, compiled with gcc) answers controlled A records for *.verify-ssrf.test and delegates everything else — the production resolver path runs unmodified; the fetchFn seam is a recording spy so no real connect happens. Witness: evidence/02-dns-ssrf-ab-head-vs-prevhead.png.

cell head prev-head (control)
public-looking name → 127.0.0.1 refused pre-fetch, 0 fetches, "resolves to 127.0.0.1", no .part accepted, 1 fetch (hole)
name → 169.254.169.254 (metadata) refused accepted (hole)
name → 10.1.2.3 (RFC1918) refused accepted (hole)
mixed A records (public+private) refused (ANY-private) accepted (hole)
same-host redirect re-resolving to 127.0.0.1 refused at hop 2 after exactly 1 fetch follows rebind, 2 fetches (hole)
name → all-public downloads, sha256-match (symmetric control) downloads (control)
public IP literal accepted with zero resolver lookups (short-circuit) n/a
18 text-gate hosts (loopback, CGNAT, [::1], ULA, .internal, single-label, …) refused by pre-existing text gate, 0 fetches, no .part same (unchanged surface)
DNS failure gate passes (fail-open by design), fetch proceeds same

5/5 hole cells flip. The shim's lookup log is the physical witness: head resolves each refused name once (twice for the rebind: 93.184.216.34 then 127.0.0.1); prev-head's log is empty — it never resolves. Counts: 23/23 assertions.

UTF-16 BOM no longer mis-sniffed as MPEG. [FF FE …]null at head vs audio/mpeg at prev-head (byte-level and file-level sniffFileModality); five genuine sync headers (FF FB/E0/E2/FF/FA) + ID3 still detect on both arms; png/wav/mp4 fixtures still classify. 12/12 per arm.

Secondary claims (re-run)

  • Download policy 22/22: hash-while-write, 404 isolation + .part cleanup, 18 SSRF text-gate refusals with zero fetches, www-strip same-host redirect followed, cross-origin / loopback / credentialed redirects refused, loop capped at exactly 6 fetches, Content-Length ceiling pre-body, lying-CL mid-stream ceiling with .part cleanup, user abort rejects and removes .part. (The SSRF policy structurally excludes loopback origins from the production path — that is the feature — so the socket layer is the injected fetchFn seam with real Response objects; everything above it runs in production code. SSRF cells run fully in production.)
  • Tool-result funnel 13/13 + 3/3: byte-exact conversion; 9 parts → exactly 8 uploads; 64MiB converts then 65MiB (> remaining of 128MiB) stays inline; declared-audio with video BYTES stays inline under video-disabled while the video-declared control converts (sniffed gate); identity preserved for non-media and gate-off; nested functionResponse.parts converted; injected OSS 500 isolates one part (sibling converts).
  • Converter head 10/10 vs base 10/10 (control reds encoded as assertions): oss:// audio fileData → input_audio with bare URL for mpeg/wav/flac/ogg/m4a (base: no input_audio — the textify-after-upload bug); audio/amr placeholder on both; audio-disabled placeholder; image/video parity; inline audio keeps data: URI on both.

Mutation matrix (10 mutants, 0 survivors)

mutant suite outcome
M1 guard token-throw disabled guard.test.ts killed (1F/6P) — "expected function to throw an error, but it didn't"
M2 download SSRF text gate off download.test.ts killed (1F/13P) — intended SSRF assertion fails
M3 funnel sniffed→declared gate tool-result-media.test.ts killed (1F/4P)
M3b funnel budget 8→9 tool-result-media.test.ts killed (1F/4P) — "expected spy to be called 8 times, but got 9"
M4 converter audio-fileData branch off converter.test.ts killed (2F/215P, the two oss-audio tests)
M5 download per-hop DNS gate off download.test.ts killed (4F/10P, the four DNS tests)
M6 BOM exclusion removed recognition.test.ts killed (1F/14P) — "expected { audio/mpeg } to be null"
M7 URL-only early-return reverted atCommandProcessor.test.ts killed (2F/62P, the two new URL tests)
M8 image zoom-hint part removed index.test.ts killed (1F/11P)
M9 fail-closed catch loses error fields index.test.ts killed (1F/11P)

Witness: evidence/03-mutation-matrix-summary-and-m5-live.png (summary + live M5 re-run). Every kill is a behavioral assertion mismatch at the intended test — no import/compile breakage. Unmutated controls green (core omni+converter 306/306; cli atCommandProcessor 64/64). All mutated files restored (git status empty afterwards).

Findings (non-blocking)

  1. Nit (carried) — test-count drift. PR body says src/omni/ is "77 tests"; measured at fa35283: 89 tests in 9 files, all passing.
  2. Note (carried, environmental) — logger.test.ts 31F/21P in every arm here. Head and base A/A parity re-confirmed with byte-identical failing-test names; unrelated to the PR.
  3. Note (reviewed, not a defect) — documented residual DNS risk. findNonPublicAddress returns null on resolver failure (fail-open; the connect then reports the real error) and a check-then-connect TOCTOU window remains; both are documented in the code with rationale, and the helper is deliberately NOT wired into fetchWithPolicy (WebFetch supports intranet FQDNs). The per-hop re-check shrinks the practical rebinding window as claimed.

Not covered

  • Real-model E2E (no DashScope credential), TUI download cards / Esc-during-download UX, ACP Session.runTool end-to-end over the wire (suite-level only: 460/460), Qwen OAuth beyond the gate predicate, download consent UX (deferred by design).
  • Per-commit attribution: checkout is depth-2 (shallow-boundary trap: rev-list HEAD^1..HEAD^2 = 1 vs 9 commits in metadata); the aggregate diff was verified; the delta commit was additionally isolated because the previous verified head is reachable locally.
  • Repo-wide test suite/typecheck; targeted gates only: core omni (89/89) + converter (217/217) + config (config.test.ts 474/474, storage 64/64, safe-mode 24/24, session-env 9/9, workflows 4/4, workflow-registration 5/5), cli atCommandProcessor (64/64) + settingsSchema (36/36) + Session (460/460), typecheck core+cli exit 0, check:serve-fast-path-bundle pass.
  • Download header/idle timeouts (30s/60s) not exercised in real time.
  • The verify container ships no ffmpeg/ffprobe; static builds (7.0.2) were installed to a scratch PATH dir — the omni pipeline's hard prerequisite (same as the previous round).

Methodology

Environment: CI merge-ref checkout (HEAD merge, HEAD^1 base tip, HEAD^2 verified head; previous verified head reachable as a commit object), npm ci + npm run build pre-run at head. Base control rebuilt from HEAD^1 and delta control from 88d7e34 in scratch worktrees (tsc --build of packages/core, root node_modules symlinked — lockfile untouched; the eight nested packages/core/node_modules deps symlinked too). Provenance asserted three ways: realpath of the internal workspace links (they point at the head tree, so the harnesses never import through them — they load each control's own dist by absolute file URL), a grep proving the loaded dists contain zero internal @qwen-code imports, and differential markers (base dist lacks sniffFileModality; prev-head dist lacks findNonPublicAddress). Harnesses drive the real compiled pipeline against a loopback fake DashScope origin recording both sides of the wire (getPolicy auth/model + OSS PostObject multipart parsed for field order and file-part sha256); the DNS seam is an LD_PRELOAD getaddrinfo shim, not a code mock; the gate is activated via the DASHSCOPE_PROXY_BASE_URL proxy-match seam + static-key stub Config (env captured at module load, so multi-origin cells run in separate processes). Bundle-gate and typecheck liveness proven by planted violations (full-barrel import → gate fails with iconv-lite encoding tables … static path: acpAgent; planted type error → tsc TS2322, exit 2), then restored and re-run green. Raw logs, harness .mjs/.c sources, cell JSONs, and evidence PNGs live in this artifact directory; witnesses 01-ab-delivery-base-vs-head.png, 02-dns-ssrf-ab-head-vs-prevhead.png, 03-mutation-matrix-summary-and-m5-live.png, 04-wire-oracle-harnesses.png are live re-runs captured this round via terminal-capture.

Evidence images

01-ab-delivery-base-vs-head

02-dns-ssrf-ab-head-vs-prevhead

03-mutation-matrix-summary-and-m5-live

04-wire-oracle-harnesses

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

Qwen Code · sandboxed verification

qqqys
qqqys previously requested changes Aug 5, 2026

@qqqys qqqys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] The DNS preflight is still not bound to the connection. downloadMediaUrl resolves currentUrl at packages/core/src/omni/download.ts:109, then the global fetchFn(currentUrl) at line 126 independently resolves the hostname again; packages/core/src/utils/fetch.ts:177 explicitly confirms this race. An attacker controlling DNS for a public-looking media hostname can answer with a public address during the validation lookup and with loopback, link-local, or RFC1918 space during the fetch lookup. The request then passes the new gate, reads the internal response, and the omni path promotes/uploads those bytes to DashScope — the SSRF/data-exfiltration boundary remains bypassable.\n\nPlease bind the outbound connection lookup to the address set that was validated (and fail closed when that validation cannot resolve), for example with an HTTP dispatcher/agent whose lookup returns only vetted public addresses. If the client cannot pin the connection, this URL-media path must reject hostnames that cannot be safely bound rather than claiming DNS-rebinding protection.

Validating the resolved address and then letting fetch re-resolve is
check-then-connect: a low-TTL record answering public once and private
the second time would still be connected to, and the fetched bytes are
uploaded to a third party. Each hop now resolves via
resolveNetworkTarget('public') — which vets every returned address and
returns a lookup pinned to the vetted one — and installs that lookup as
the request dispatcher, so the name is never resolved a second time.

- fail closed: unresolvable/unvettable hosts and targets without a
  pinned lookup are refused instead of fetched unpinned
- re-validated and re-pinned at every redirect hop; the previous hop's
  agent is replaced and closed
- fetch defaults to undici's own fetch so dispatcher and fetch come
  from one undici version (mixing majors rejects the agent)
- Node-only: Bun accepts dispatcher and silently ignores it (verified
  on 1.3.11), so non-Node runtimes are refused with a clear message
- https and credential-free URLs enforced with named errors
- utils/fetch.ts: remove findNonPublicAddress/HostResolver (a weaker
  duplicate of resolveNetworkTarget) and the doc paragraph wrongly
  claiming undici cannot pin connections
The @-path terminator set treats '?', '&', ',' and ';' as sentence
punctuation, which is right for filesystem paths but wrong for URL refs:
a presigned OSS/S3 link carries its signature in the query string, so
'@https://…/a.mkv?x-oss-signature=…' was silently cut at the '?' and the
download failed with HTTP 403 naming only the host.

URL refs now run to the first character RFC 3986 does not permit
unencoded (covering whitespace and unspaced CJK prose), with trailing
sentence punctuation trimmed afterwards so it can never cut a URL short
mid-query. Filesystem path parsing is unchanged.
@LaZzyMan

LaZzyMan commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

You're right, and my previous reply was wrong on two counts. Thanks for pushing back instead of accepting it.

Correcting my previous reply

I wrote that pinning the connect to a vetted address "needs a custom agent … which undici doesn't expose portably," and treated narrowing the race as an acceptable endpoint. Both parts were wrong:

  • Factually wrong. undici is a direct dependency of packages/core (^7.28.0), Agent({connect: {lookup}}) is exactly the hook needed, and this repo already uses that pattern for the same threat model — services/image-generation-service.ts:258-261 pins downloads of model-returned image URLs. I asserted an API limit without checking it. I've since verified pinning end to end (Node 22.23.1 / undici 7.28.0): a request for https://<name> with a pinned lookup connects to the pinned address under both the global fetch and undici's own.
  • Wrong in judgment. A documented race in a path that uploads the fetched bytes to a third party is an open vulnerability, not a footnote. Documenting it just handed you the roadmap to it. The doc comment you cited (fetch.ts:177) is deleted.

The fix

The preflight is now bound to the connection, and it reuses existing infrastructure rather than the parallel helper I'd added:

  • omni/download.ts — each hop calls resolveNetworkTarget(url, 'public', signal) (extension/network-policy.ts), which resolves, rejects if any returned address is blocked, and returns a LookupFunction pinned to the vetted address. That lookup is installed as new Agent({connect: {lookup}}) and passed as the request's dispatcher, so the name is never resolved a second time — there is no longer a check and a separate connect to race.
  • Fails closed. A host that cannot be resolved or vetted is refused (reversing the fail-open you correctly objected to), and if a target ever came back without a pinned lookup the request is refused rather than sent unpinned — per your instruction not to claim rebinding protection we can't keep.
  • Re-validated and re-pinned at every redirect hop, before that hop's connect; the previous hop's agent is replaced and closed.
  • Node-only, enforced. While testing the pin I found Bun accepts dispatcher and silently ignores it — its fetch is native, and it shims the undici module too, so neither the global nor undici.fetch routes through the agent (verified on Bun 1.3.11: pinned lookup never called, connection reached the unpinned address). This repo does run under Bun (utils/getPty.ts:22, serve/env-snapshot.ts:165), where the same runtime fact is only a missed optimization for utils/apiPreconnect.ts:166. For this path it would be a silently unenforceable pin, so downloadMediaUrl now refuses on any non-Node runtime and tells the user to use a local file path. The gate is an allowlist (detectRuntime() !== 'node'), so an unrecognized future runtime is refused rather than fetched unpinned. This is your "must reject hostnames that cannot be safely bound" applied at the runtime level.
  • https only. resolveNetworkTarget('public') requires it, and I made the check explicit so the error says why. Plaintext media can be swapped in flight and these bytes are uploaded under the user's account. parseHttpUrlRef still matches http:// on purpose — that yields a clear "must be https" error instead of falling through to filesystem resolution, where the ENOENT skip would drop the ref silently.

Net effect on the diff: findNonPublicAddress/HostResolver are deleted from utils/fetch.ts (-64 lines). They were a weaker reimplementation of resolveNetworkTarget — which already had the BlockList, the fail-closed behavior, the address pinning, and its own tests. I should have found it before writing a second one; the asymmetry note from my earlier reply (this gate must not apply to fetchWithPolicy, which intentionally supports intranet FQDNs) is preserved by resolveNetworkTarget being opt-in per call site.

Tests (omni/download.test.ts, 21)

The one that matters for your finding: pins the connection to the vetted address (real socket) — no injected fetchFn, real undici agent, real TCP listener, and a pinned.invalid hostname (RFC 6761: never resolves). A connection arriving at the listener can therefore only have come from the pin; without the dispatcher this is ENOTFOUND with zero connections.

I verified the tests are load-bearing rather than decorative by removing the dispatcher from the fetch call — reproducing the exact pre-fix check-then-connect state. Result: pins the connection to the vetted address and pins each hop to its own vetted address both fail, the others stay green. I did the same for the runtime gate (forcing its condition false): exactly the one new test fails.

Also: fails-closed-on-unresolvable, refuses-unpinnable-target, refuses-plaintext-http, refuses-credentialed-URLs (without echoing the credentials), refuses-on-non-Node-runtime, mixed A records where only the second address is private, per-hop re-pinning asserted by interrogating each hop's dispatcher lookup (two hops vetted to different addresses must pin to different addresses), redirect downgrade/credential injection refused, a version-skew guard asserting the global fetch is never used, and one with no seam injected asserting production reaches dns.lookup with {all: true, verbatim: true}.

Found while dogfooding this path: the @-parser was truncating URLs

End-to-end testing with a presigned OSS URL surfaced a bug upstream of this diff: the @-path parser's punctuation terminators include ?, so @https://…/movie.mkv?x-oss-signature=… was silently cut at the ? — the signature never reached the server and OSS answered 403 naming only the host. Fixed in the second commit: a URL ref now runs to the first character RFC 3986 does not permit unencoded (which also handles unspaced CJK prose after the URL), with trailing sentence punctuation trimmed afterwards. Filesystem path parsing is byte-for-byte unchanged, and the pre-existing punctuation-termination suite still passes.

With both commits, the full pipeline is verified against real endpoints: presigned-URL download (986 MB, correct signature preserved), re-recognition, content-addressed store, DashScope upload, and a model answer on a 5-minute clip. (The 986 MB feature film itself was rejected server-side with InternalError.Algo.InvalidParameter: The video file is too long — that duration ceiling is exactly what the S4 degradation slice is scoped to handle.)

packages/core omni + utils/fetch + extension/network-policy + runtimeFetchOptions + atCommandProcessor: 312/312. Typecheck and lint clean.

wangyuenlp
wangyuenlp previously approved these changes Aug 5, 2026

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not reviewed: drift commits f63a764/ba9ff593 (855 delta lines, SSRF pinning fix + @-path parser fix) verified by orchestrator delta-read only — no agent-level re-review of the delta.

Not reviewed: build-and-test — cross-repo lightweight mode: no local checkout of QwenLM/qwen-code exists, so no build or test suite was executed.

中文说明

未审查:drift commits f63a764/ba9ff593 (855 delta lines, SSRF pinning fix + @-path parser fix) verified by orchestrator delta-read only — no agent-level re-review of the delta。

未审查:build-and-test — cross-repo lightweight mode: no local checkout of QwenLM/qwen-code exists, so no build or test suite was executed。

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

Comment thread packages/core/src/omni/tool-result-media.ts Outdated
Comment thread packages/core/src/omni/index.ts Outdated
Comment thread packages/core/src/omni/index.ts Outdated
Comment thread packages/core/src/utils/fileUtils.ts
Comment thread packages/core/src/omni/download.ts Outdated
Comment thread packages/core/src/omni/tool-result-media.ts
Comment thread packages/cli/src/ui/hooks/atCommandProcessor.ts
Comment thread packages/core/src/omni/download.ts Outdated
Comment thread packages/core/src/omni/estimation.ts
Comment thread packages/core/src/omni/download.test.ts
The input-box highlighter had its own @-ref charset that excluded '%',
'?', '&' and '=', so a presigned URL was painted file-colored only up to
the first percent-escape and looked truncated even after the parser was
fixed to consume it whole. URL refs now use the same RFC 3986 charset
and trailing-punctuation trim as parseAllAtCommands, keeping the painted
span identical to what the parser consumes.
Criticals:
- tool-result-media: staging-dir setup moved inside convertPart's try —
  a mkdir failure (ENOSPC, EACCES, ~/.qwen/omni as a regular file) now
  degrades that part to inline instead of rejecting the whole tool
  result and reporting a succeeded tool as failed
- sanitizeErrorMessage: exact split/join replacement of the known
  filePath before the pattern pass (immune to CJK segments, ~-prefixed
  and special-character basenames), with separator-based — not
  ASCII-word-based — fallback classes and a Windows-path pass
- the fail-closed delivery result now sanitizes BOTH llmContent and the
  error field (the scheduler sends 'error', not llmContent, to the model
  on READ_CONTENT_FAILURE) and names the file by displayName
- the 100 MB image-source cap only applies when the overview decoder
  will actually run: it protects the decoder, and the omni path uploads
  original bytes under its own 1 GiB ceiling without decoding

Suggestions:
- malformed redirect Location surfaces as a named OmniDownloadError
  instead of a raw TypeError (header value kept out of the message)
- header/idle watchdog timeouts are now identifiable in the surfaced
  error instead of a generic 'This operation was aborted'
- effectiveMaxDownloadFileBytes is clamped to the upload cap even when
  omni.download.maxFileBytes is configured higher
- estimation rejects degenerate present values (0/negative/non-finite)
  as 'unavailable' instead of emitting a 0-token 'ok' estimate
- corrected the 0xFE sniff comment: 0xFF 0xFE is a valid MPEG-1 Layer I
  header (reserved encodings are version 01 / layer 00); the exclusion
  is a deliberate trade against UTF-16 LE false positives
- SSRF tests now cover private IPv6 (loopback, link-local, ULA,
  IPv4-mapped) plus a public-IPv6 acceptance case

Regression tests are mutation-verified: reverting the mkdir placement
or the error-field sanitization makes exactly the new tests fail.
@LaZzyMan

LaZzyMan commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

Round-2 findings triaged: all 16 verified against HEAD before acting — every one was real. 10 fixed in eca83f3d2e, 6 deferred with reasons below.

Fixed (4 Critical + 6 Suggestions)

R1-1 (Critical, tool-result-media.ts) — staging-dir setup moved inside convertPart's try. Regression test makes ~/.qwen/omni a regular file (mkdir → ENOTDIR) and asserts the part stays inline with no upload attempted. Mutation-verified: moving the mkdir back out fails exactly that test.

R1-2 (Critical, sanitizeErrorMessage) — you were right on all three mechanisms, and the fix follows your suggestion: the known filePath is now replaced exactly (split/join) before any pattern runs, which is immune to every path shape by construction; the pattern pass (for paths we don't know, e.g. store destinations) now uses separator-based segment classes instead of ASCII \w, plus a Windows-drive pass. Regression tests cover /Users/张三/视频/, videos/~draft.mp4, it's (v2)+final@x, and C:\Users\björn\ — asserting the parent directory never reaches error OR llmContent.

R1-3 (Critical, fail-closed error field) — applied, and one step further than the suggestion: llmContent had the same unsanitized message, so both fields now share one sanitized message, and the error field names the file by displayName instead of interpolating filePath at all. Mutation-verified against the CJK-path test.

R1-4 (Critical, 100 MB image cap) — the cap now applies only when omniModule === undefined, same pattern as the adjacent 10 MB gate. Your asymmetry framing (150 MB PNG rejected / 500 MB GIF delivered) is what made the right fix obvious: the constant protects the overview decoder, and the omni path never decodes.

R1-5 — malformed Location now surfaces as OmniDownloadError('Redirect with a malformed Location header from <host>'); the header value itself is deliberately kept out (server-controlled, reaches the UI). Test with Location: http://[.

R1-7 — comment corrected per your spec reading (version bits 11 = MPEG-1, layer 11 = Layer I; reserved are version 01 / layer 00). The exclusion is kept and now documented as a deliberate trade: a CRC-protected Layer I frame is rare, UTF-16 LE text files are not.

R1-11effectiveMaxDownloadFileBytes is clamped to the upload cap via Math.min even when explicitly configured higher. Unit test covers higher/lower/unset/zero.

R1-14 — both watchdogs are now identifiable: the catch blocks check headerAbort.signal.aborted / idleAbort.signal.aborted and throw named errors (timed out waiting for response headers (30s) / stalled: no data for 60s) instead of surfacing the generic AbortError message.

R1-15 — added a usable() guard (positive, finite) on every present field; duration 0, width 0, negative height, and NaN frameRate all yield unavailable instead of a 0-token 'ok'. Tests for each shape.

R1-16 — SSRF corpus now probes ::1, fe80::1, fd00::2, and ::ffff:10.0.0.5 (refusals) plus 2606:4700:4700::1111 (acceptance, restoring the case the pinning refactor dropped and proving the refusals come from classification rather than wholesale IPv6 rejection).

Deferred (6), with reasons

  • R1-9 (URL funnel count/byte budget) and R1-10 (min-rate floor / slowloris) — real, and both are budgeting policy decisions (how many URLs per turn, what minimum transfer rate) that belong with the S4 degradation/limits slice where the token-estimation thresholds are also being calibrated; a number picked casually here would be a guess we'd immediately revisit. The per-URL byte cap, per-hop pinning, and idle watchdog bound each individual download today.
  • R1-13 (URL funnel runs before file validation) — agreed the ordering wastes a doomed turn's downloads; moving the funnel after mention/file validation touches the resolver's control flow well beyond this PR's scope, so it goes in as a follow-up rather than a rider.
  • R1-8 (root-barrel eager omni exports) — the omni graph is intentionally reachable via the /omni subpath for lazy consumers (that's what the CLI uses); trimming the root barrel is a public-API change for embedders and belongs in the startup-cost workstream (Cold-start follow-ups: remaining lazy-loading candidates from the ACP eager-closure audit #7264 family), not a review rider.
  • R1-12 (base64 decode before gates) — the sniff needs decoded bytes, but the count/byte budget could indeed check (data.length * 3) / 4 first; deferred as a memory optimization, noting the funnel is already capped at 8 parts / 128 MiB per result.
  • R1-6 (zoom_image hint) — the hint is only attached on the image path where the tool is registered; if there's a config where zoom_image is absent while omni images are active, I'd rather fix it with that repro in hand.

Also in this push (found dogfooding the URL path end-to-end)

  • ba9ff593d2 — the @-path parser truncated URL refs at ? (the terminator set treats it as sentence punctuation), so a presigned OSS URL lost its signature and failed with 403 naming only the host. URL refs now run to the first character RFC 3986 does not permit unencoded, with trailing sentence punctuation trimmed after the scan; filesystem path parsing unchanged, and the pre-existing punctuation-termination suite still passes.
  • e7154f6001 — the input-box highlighter had a third copy of the @-charset (no %?&=), painting a presigned URL half-colored; now shares the parser's charset and trim so the painted span is exactly what the parser consumes.

Verified end-to-end after the parser fix: presigned OSS URL (986 MB) → full-signature download → re-recognition → store → DashScope upload → model inference. The full-length film was rejected server-side with InternalError.Algo.InvalidParameter: The video file is too long (the S4 input, as expected); a 5-minute clip completes the whole chain with a correct model answer.

Core omni + fetch + network-policy + fileUtils: 353/353. atCommandProcessor 68/68, highlight 20/20. Typecheck (core+cli), eslint, prettier all clean. The three new regression tests with a plausible silent-pass risk (mkdir placement, error-field sanitization, pin-per-hop) were each mutation-verified.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

Not reviewed: reverse audit — stopped before round 3 by the review time budget.

中文说明

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

未审查:反向审计——评审时间预算不足,未能开始第 3 轮。

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

Comment thread packages/core/src/omni/index.ts
Comment thread packages/cli/src/ui/utils/highlight.ts Outdated
Comment thread packages/cli/src/ui/hooks/atCommandProcessor.ts
Comment thread packages/core/src/core/openaiContentGenerator/converter.ts
Comment thread packages/core/src/omni/download.ts Outdated
Comment thread packages/core/src/omni/index.ts Outdated
Comment thread packages/core/src/omni/recognition.ts Outdated
Comment thread packages/core/src/omni/recognition.ts Outdated
Comment thread packages/acp-bridge/vitest.config.ts Outdated
Comment thread packages/acp-bridge/tsconfig.json Outdated

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

Not reviewed: reverse audit — stopped before round 3 by the review time budget.

中文说明

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

未审查:反向审计——评审时间预算不足,未能开始第 3 轮。

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

Comment thread packages/cli/src/ui/hooks/atCommandProcessor.ts
Comment thread packages/core/src/omni/tool-result-media.ts
Comment thread packages/cli/src/ui/hooks/atCommandProcessor.ts
Comment thread packages/core/src/omni/recognition.ts Outdated
Comment thread packages/core/src/omni/download.ts Outdated
Comment thread packages/core/src/omni/download.ts
Comment thread packages/core/src/omni/ffmpeg.ts Outdated
Comment thread packages/core/src/omni/ffmpeg.ts Outdated
Comment thread packages/core/src/omni/download.test.ts
Comment thread packages/core/src/omni/recognition.ts
- sanitizeErrorMessage: a path segment containing a space defeats the
  pattern pass (segment classes break at whitespace), so 'john doe'
  survived scrubbing. Call sites now pass every path they know about:
  the store wrap adds the store root (covers putFile throwing before
  objectPath is assigned), and the upload wrap - previously passing
  err.message through verbatim - sanitizes with the object path and
  store root. Function exported for direct shape tests.
- estimation: animated images (GIF/APNG/animated WebP) no longer
  estimate as a single frame. The image probe branch retains ffprobe's
  nb_frames as frameCount, and the estimator applies the design 6.4
  visual formula with the real count - a 480x480 300-frame GIF now
  estimates ~33,750 tokens instead of 113, so an enabled token guard
  actually engages. Static images and containers that do not report a
  frame count keep frameCount 1.
- tool-result media: a transport-guard rejection is a policy verdict,
  not a transfer failure - the part is now withheld with a text
  placeholder instead of being delivered inline as base64, which
  silently bypassed an enabled guard at greater request cost than the
  upload it was rejecting. Transfer failures keep the inline
  degradation; the batch never fails for one part.
- mid-turn URL media: resolveAtCommandQuery runs under a fixed 10s
  mid-turn budget that structurally killed every mid-turn @https
  reference (the download alone can exceed it, and inside the resolver
  the timeout abort is indistinguishable from a user cancel). URL-media
  turns are now exempt from that timer - the download path carries its
  own 30s header and 60s idle watchdogs - while filesystem resolution
  keeps the 10s cap unchanged.
- input-box highlighter: match the URL scheme case-insensitively, like
  the parser it mirrors; an uppercase @https ref no longer half-paints.
- download: resolve-phase watchdog, malformed-URL and proxy refusal,
  resolver-error translation, path scrubbing, cause-chain surfacing,
  DownloadedMedia slimmed to partPath; mutation-proven tests for
  redirect cap, both watchdogs, byte-cap streaming, abort wiring
- recognition: direct recognizeMediaFile tests, GIF 6-byte signature,
  guarded probe-handle close; sha256 moved out of RecognizedMedia
- pipeline: hash after guards (stat -> byte guard -> probe -> token
  guard -> hash); displayName override so URL-funnel errors name the
  remote file, not the staging path
- fileUtils: omni gating suite incl. 100 MB image-cap bypass pin
- dead S1 shims deleted (video-only probe/delivery/read wrappers)
- URL funnel: post-download modality gate mirroring the local-file gate

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed at experimental standard (base omni-experiment, not main). The new download.ts is unusually well-hardened for any bar: https-only, SSRF refused by hostname AND resolved address with DNS pinning (connect.lookup returns only the vetted address) re-applied at every redirect hop, refusal on Bun and behind proxies where the pin is unenforceable, same-host bounded redirects, maxBytes enforced against both Content-Length and written bytes, three-timer watchdogs, .part cleanup on failure, and error messages scrubbed of local paths/credentials. Identity is re-derived from the file on disk (hash/sniff/size), never from server Content-Type/final URL. No P0/P1. Light nits for later (non-blocking, experimental): consider a whole-body content-type sniff before promotion, and document the proxy refusal in user docs since it changes behavior for proxied users.

@LaZzyMan
LaZzyMan dismissed stale reviews from qwen-code-ci-bot and qqqys August 6, 2026 06:49

fixed

@LaZzyMan
LaZzyMan merged commit 604a84f into omni-experiment Aug 6, 2026
1193 of 1245 checks passed
@qqqys

qqqys commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Round-4 review — passing. Re-reviewed the full diff at e4daca6 (base omni-experiment, not main).

The round-1–3 threads hold up against the code as it stands, not just against the anchored lines: the dead probe/sniff fields (sampleRateHz, channels, SniffedType.extension, the four unread DownloadedMedia fields) are gone; sanitizeErrorMessage now does exact knownPaths replacement before the pattern pass, which is the right fix for the space-in-path leak; the transport-guard rejection in the tool-result funnel is withheld with a placeholder instead of degrading to inline; the GIF sniff is the full 6-byte signature; sniffFileModality's close() is guarded. download.ts remains the strongest part of the diff — three-timer model, resolve-and-pin re-applied per redirect hop, refusal on Bun and behind a proxy rather than an unenforceable claim.

Five things I still found. None of them should block this PR — all are contained by the S1 gate and none changes gate-off behavior — so I'd suggest they land as a follow-up issue against the S3 slice rather than churning this branch.


1. HEIF/AVIF containers sniff as video/mp4. packages/core/src/omni/recognition.ts:34-43bmffBrandType maps every ftyp brand that is not qt/M4A/M4B to video/mp4, but heic/heix/mif1/msf1 (HEIC) and avif/avis (AVIF) are ISO-BMFF image brands. Verified at this commit by calling sniffMediaType on a synthetic ftyp avif box: returns { mimeType: 'video/mp4', modality: 'video' }.

Failure scenario: @https://cdn.example/photo.avif. The URL funnel calls processMediaForOmniDelivery with no expectedModality (atCommandProcessor.ts, { signal, displayName: urlBase }), so nothing cross-checks the sniff — the image is probed as video, stored as .mp4, uploaded, and delivered as a video_url part with mimeType: video/mp4. The tool-result funnel takes the same path, since tool-result-media.ts:76-78 makes the sniffed modality the authoritative gate. The local-file path escapes only because fileUtils.ts:1282 requires sniffedModality === fileType — so @photo.heic does fall back to inline as the PR description claims, but as a side effect of the modality-mismatch check rather than because the pre-sniff classified it correctly.

The same coarse brand table also delivers an .m4a whose major brand is isom/mp42 as video. Suggested fix: map the HEIF brand set to image/heic / image/avif, or return null so those formats fall back inline as intended.

2. download.ts path scrubbing did not get the hardening its sibling did. packages/core/src/omni/download.ts:80-85scrubPathsFromMessage is still pattern-only, with segment classes that exclude \s. That is exactly the shape sanitizeErrorMessage (omni/index.ts:85-100) was changed away from this round, and its own comment explains why a regex can never cover every path shape. Both wrap sites here have the concrete path in scope (downloadsDir at :305, partPath at :547) and could use the same exact-replacement pass.

Verified: ENOTDIR: not a directory, mkdir '/Users/My Name/.qwen/omni/downloads' scrubs to mkdir 'My Namedownloads' — the home-directory segment survives into a message that reaches the UI and the debug log.

3. Neither tool-result funnel pre-gates the dynamic import. coreToolScheduler.ts:1397-1400 and Session.ts:8273-8275 await import(...) unconditionally for every tool result, and only then does processToolResultOmniMedia early-return at tool-result-media.ts:53. fileUtils.ts:1271-1274 in this same PR deliberately puts config.isOmniEnabled?.() before its dynamic import, with the rationale that the import touches the filesystem (vitest SSR transforms), breaks mock-fs suites, and wastes a module load for every non-omni user. The same rationale applies at both funnels: with omni off, the first tool call of every session now pulls in the omni graph (storage / upload / ffmpeg / download / the DashScope provider).

4. The mid-turn @-resolve timeout exemption is per-message, not per-ref. useGeminiStream.ts:2473-2482hasUrlMediaRef matches @https?:// anywhere in the message and drops the timer for the entire resolveAtCommandQuery call. A mixed message such as @https://host/a.mp4 @src/**/*.ts therefore loses the 10s cap on its filesystem half too, which the block comment's "Filesystem resolution keeps the cap unchanged" says it should keep.

5. Two S1-compat shims are still dead, with a justification comment that no longer holds. recognition.ts:130 sniffVideoMimeType (also re-exported at omni/index.ts:44) and recognition.ts:156 extensionForVideoMime, whose comment reads @deprecated S1 name kept for existing imports. Grep across packages/ finds zero production importers for either; the only references are in recognition.test.ts. Round 3 removed six of the eight shims in this pattern — these two were missed, and the comment now asserts an import that does not exist.

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

Labels

omni-experiment Omni multimodal experiment (omni-experiment branch)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants