Skip to content

fix(web-shell): keep workspace picker suggestions closed - #8844

Merged
wenshao merged 11 commits into
mainfrom
codex/fix-web-shell-workspace-registration
Aug 12, 2026
Merged

fix(web-shell): keep workspace picker suggestions closed#8844
wenshao merged 11 commits into
mainfrom
codex/fix-web-shell-workspace-registration

Conversation

@ytahdn

@ytahdn ytahdn commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Closes workspace path suggestions whenever the path input loses focus. Directory suggestions are allowed to open only while the input is still active, so a delayed lookup cannot reopen the list after the user clicks elsewhere. The Browse action now releases input focus before opening the native directory picker and keeps the list closed after filling the selected path.

Why it's needed

After a user typed a workspace path, the suggestion popover could remain visible even after the user clicked outside the input. The Browse button also prevented focus from leaving the path input, so selecting a directory could leave the popover visible or allow a delayed lookup to reopen it with the selected directory as a redundant option. The UI therefore looked as if the user still needed to choose another directory after already entering or selecting the intended path.

Reviewer Test Plan

How to verify

Open Add Workspace, type an absolute path prefix, and wait for directory suggestions to appear. Click outside the path input and confirm the input loses focus and the list closes; it must remain closed if a pending lookup completes afterward. Then click Browse…, select a directory, and confirm the selected absolute path is filled while the input remains unfocused and no suggestion list opens.

Evidence (Before & After)

Before: clicking Browse kept the path input focused, and a delayed autocomplete result could reopen the list with the selected directory. A lookup completing after an ordinary blur could also reopen the list.

After: blur closes the list, delayed results cannot open it while the input is inactive, and Browse fills the selected path with focus outside the input.

Tested on

OS Status
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

Environment (optional)

macOS; focused Web Shell tests (23/23), Web Shell production build, TypeScript typecheck, ESLint, and Prettier.

Risk & Scope

  • Main risk or tradeoff: Suggestions continue to be fetched and updated while unfocused, but they cannot become visible until the existing input interactions open them again.
  • Not validated / out of scope: Workspace registration bearer-token behavior and non-macOS native picker behavior.
  • Breaking changes / migration notes: None.

Linked Issues

N/A

中文说明

本 PR 的改动

工作区路径输入框失去焦点时关闭目录建议。只有输入框仍处于激活状态时,目录建议才允许打开,因此延迟返回的查询不会在用户点击其他位置后重新打开列表。“浏览”操作现在会在打开系统目录选择器前释放输入框焦点,并在填入所选路径后保持列表关闭。

为什么需要

用户输入工作区路径后,即使点击输入框外部,目录建议浮窗仍可能持续显示。“浏览”按钮还会阻止焦点离开路径输入框,因此选择目录后,浮窗可能继续显示,或者被延迟返回的查询重新打开,并把已经选中的目录再次显示成一个多余选项。这会让界面看起来像是用户已经输入或选择目标路径后,仍然需要再选择一次目录。

Reviewer 测试计划

验证方式

打开“添加工作区”,输入绝对路径前缀并等待目录建议出现。点击路径输入框外部,确认输入框失去焦点且列表关闭;即使仍在等待的查询随后完成,列表也必须保持关闭。然后点击“浏览…”,选择目录,并确认所选绝对路径已填入、输入框保持失焦且建议列表没有打开。

证据(修改前后)

修改前:点击“浏览”后路径输入框仍保持焦点,延迟返回的自动补全结果可能重新打开列表并显示已选择的目录。普通失焦后的查询也可能重新打开列表。

修改后:失焦会关闭列表;输入框未激活时,延迟结果不能打开列表;“浏览”填入路径后,焦点位于输入框之外。

测试平台

系统 状态
🍏 macOS
🪟 Windows N/A
🐧 Linux N/A

环境(可选)

macOS;Web Shell 定向测试(23/23)、Web Shell 生产构建、TypeScript 类型检查、ESLint 和 Prettier。

风险与范围

  • 主要风险或权衡:输入框失焦后仍会获取并更新建议数据,但在既有输入交互再次打开列表前,这些建议不会显示。
  • 未验证或范围外:工作区注册的 bearer-token 行为以及非 macOS 原生选择器行为。
  • 破坏性变更或迁移说明:无。

关联 Issue

@ytahdn

ytahdn commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

E2E Test Report

Scope: Add Workspace native folder selection and directory autocomplete interaction on macOS.

Baseline: With the existing Web Shell, selecting a complete directory updated the input and the debounced lookup subsequently reopened the suggestions with that directory as another choice.

Post-fix verification: The focused Web Shell behavioral suite passed 23/23. It verifies that the list remains closed after advancing beyond the debounce interval following picker selection, and that selecting the current input path does not disable autocomplete on the next manual edit. Web Shell TypeScript typecheck also passed.

Not covered: A post-fix live-browser run of the native macOS picker, non-macOS native pickers, and workspace registration authentication. The bearer-token behavior is intentionally outside this PR.

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@ytahdn ytahdn closed this Aug 10, 2026
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-running the full gate on the current head ff555e0 — five autofix rounds have landed since the last triage pass (which reviewed 67c0e3d and requested changes on the stale-suppress-flag finding), so every stage is re-evaluated from scratch.

Template looks good ✓

Problem: observed bug with solid evidence. The suggestion list reopening after blur/Browse was visible directly in the base code (the path-change effect ran with openOnResult = true after a pick; a lookup still in flight at blur could reopen the popover), and a maintainer has since reproduced it against a real daemon + real browser with a before/after comparison — including the list spontaneously reopening ~0.6 s after blur on the un-fixed code.

Direction: aligned. Web Shell is an actively maintained surface — the CHANGELOG carries a steady stream of recent Web Shell UX fixes (#8930, #8915, #8914, #8924, #8891) — and a double-selection papercut in Add Workspace is squarely in scope.

Size: not applicable — no core paths; packages/web-shell/client/** only. 90 production lines across three files (App.tsx 14, AddWorkspaceDialog.tsx 64, utils/dom.ts 12) plus 466 test lines.

Approach: the scope is right and matches what this race class needs — an arrival gate (only open the list if the input is still focused when a result lands), blur dismissal that invalidates in-flight lookups through the sequence counter instead of the one-shot suppress flag, a Browse flow that resets that flag on every non-path-change outcome, and the duplicate-fetch root cause fixed by passing the memoized workspace action directly instead of a per-render closure. No unrelated changes spotted.

Risk: no elevated risk signals — no changed file matches a revert-correlated path.

Moving on to code review. 🔍

中文说明

在当前 head ff555e0 上重跑完整准入门槛——自上次 triage(审查 67c0e3d 并就"残留抑制标志"问题请求修改)以来已过去五轮 autofix,因此所有阶段从头重新评估。

模板完整 ✓

问题:已观测到的 bug,证据充分。失焦/浏览后建议列表重新打开的问题在基线代码中直接可见(选择后 path-change effect 以 openOnResult = true 运行;失焦时仍在途的查询可能重新打开浮层),且维护者已在真实 daemon + 真实浏览器上做出 before/after 复现——未修复代码上失焦约 0.6 秒后列表会自行重新弹出。

方向:对齐。Web Shell 是活跃维护的界面——CHANGELOG 中有持续的近期 Web Shell UX 修复(#8930#8915#8914#8924#8891)——Add Workspace 中的重复选择问题完全在范围内。

规模:不适用——未触及核心路径,仅 packages/web-shell/client/**。三个文件共 90 行生产代码(App.tsx 14 行、AddWorkspaceDialog.tsx 64 行、utils/dom.ts 12 行),另有 466 行测试。

方案:范围恰当,与这类竞态所需的修复一致——到达门控(结果到达时仅当输入框仍聚焦才打开列表)、失焦关闭通过序号计数器作废在途查询(而非依赖一次性抑制标志)、"浏览"流程在所有未产生路径变化的结局上重置该标志,以及通过直接传递 memoize 的 workspace action(而非逐 render 闭包)修复重复查询的根因。未发现无关改动。

风险:无升级风险信号——变更文件均未命中与回滚相关的高风险路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

My independent proposal before reading the diff: gate the open decision in the fetch callback on "is the input still focused when the result arrives" (reading focus from the input's own root node — document.activeElement retargets to the shadow host in Web Shell's portal mode); invalidate in-flight lookups on blur via the existing sequence counter rather than leaning on the one-shot suppress flag; blur the input before opening the native picker and reset the suppress bookkeeping on every picker outcome (cancelled, same-path, error) so the first edit afterwards still opens the list; and stop the fetch effect from re-running on every App render by passing the memoized action instead of a per-render closure.

The PR does all four, and goes one step further on two of them. I verified the previously blocking findings against the head code myself rather than taking the review thread's word:

  • R2-1 (stale suppressNextFetchOpenRef after Browse) — fixed. The flag is now reset on every non-path-change outcome of pickDirectory (cancelled pick, same-value pick, picker error), and the fetch effect consumes and clears it unconditionally at the start of every run, so no path leaves it stale. The regression tests the previous pass asked for are all present: first edit after a cancelled picker, after a same-value pick, after a picker error, and a same-value pick racing an in-flight lookup.
  • The round-2 timer race (an uncancelled blur timer re-setting state after pickDirectory completes) — fixed. The blur dismiss is tracked in blurTimeoutRef; pickDirectory cancels it synchronously right after blur(), onFocus cancels it on quick refocus, and unmount cleans it up. A dedicated test pins that a second blur cancels the pending timer instead of stacking one.
  • Blur dismissal no longer touches the suppress flag — it bumps the sequence counter and drops the stale suggestions, which also kills the ArrowDown-reopens-stale-entries path (covered by its own test). The arrival gate (getShadowAwareActiveElement(input) === input) is a second, independent backstop: a delayed result cannot open the list while the input is unfocused no matter what the flag says, in both embedding modes (shadow-DOM portal test included).
  • The duplicate-fetch root cause is fixed at the source: App.tsx now passes workspaceActions.suggestWorkspacePaths directly. I confirmed the actions object is memoized upstream ([baseUrl, token] deps in the workspace provider), so its identity is stable across ordinary re-renders, and the new App test pins the reference across a re-render.
  • The earlier non-blocking note (R2-2, three inline copies of the shadow-DOM active-element read) is resolved as part of this diff: the new getShadowAwareActiveElement in utils/dom.ts replaces both App.tsx copies and serves the dialog — reuse, not a third copy. Minimal and in the right place.

Non-blocking, for the record: pickDirectory's dependency array now includes path (needed for the same-value comparison), so the callback is recreated per keystroke; it is only consumed by an inline onClick, so there is no effect — not worth changing.

No Critical findings remain.

Testing

Unattended CI run — I did not build or execute any PR code; the evidence below is the PR's own CI at the reviewed commit, read through the API. Everything green, no failures:

Check Conclusion
Test (ubuntu-latest, Node 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Classify PR / label / authorize / route ✅ success
Test (macos-latest / windows-latest, Node 22.x), Integration Tests (CLI, No Sandbox) ⏭️ skipped (merge_group only, per ci.yml)

Since the last pass this PR also carries a maintainer verification report (@wenshao posted it in this thread — his verification, run on this same head): a real qwen serve daemon plus two Vite frontends (PR head vs the same tree with the PR reverted) driven by the identical scripted Playwright interaction, against real filesystem suggestions. The before arm reproduces both symptoms (list spontaneously reopens after blur; the redundant picked entry reappears after a pick); the after arm stays closed in both scenarios. Most importantly for the previous review's concern, a mutation check shows 9 of the new tests fail when only the implementation is reverted — the suite pins the fix this time instead of passing vacuously. The same report observes duplicate daemon queries dropping from 12 to 3 for the identical interaction, matching the memoization fix in code.

Not verified: native directory-picker behavior on Windows/Linux — OS file dialogs are not scriptable in CI, the PR declares them out of scope, and no sandboxed lane can exercise a native GUI picker, so this remains reported for macOS only. This is the one residual gap, and no /verify or /tmux run would close it.

Real-scenario testing: not driven here (CI path); the live-behavior signal comes from the maintainer verification above plus the green web-shell E2E Smoke check.

中文说明

代码审查

读 diff 之前我独立的方案是:在 fetch 回调处以"结果到达时输入框是否仍聚焦"门控打开决策(焦点需从输入框自身的根节点读取——Web Shell portal 模式下 document.activeElement 会重定向到 shadow host);失焦时通过既有序号计数器作废在途查询,而不是依赖一次性抑制标志;打开原生选择器前让输入框失焦,并在选择器的每种结局(取消、同路径、出错)上重置抑制记账,保证之后的第一次编辑仍能打开列表;以及通过传递 memoize 的 action(而非逐 render 闭包)阻止 fetch effect 在 App 每次渲染时重跑。

PR 四点全部做到,其中两点还更进一步。此前阻塞合并的两个发现,我没有采信评审线程的结论,而是对照 head 代码逐一独立验证:

  • R2-1("浏览"后残留过期的 suppressNextFetchOpenRef)——已修复。 该标志现在在 pickDirectory 所有未产生路径变化的结局(取消选择、同值选择、选择器出错)上都会被重置,且 fetch effect 每次运行开始时无条件消费并清零它,因此没有任何路径会让它残留。上次审查要求的回归测试也全部就位:取消选择后首次编辑、同值选择后首次编辑、选择器出错后首次编辑、以及同值选择与在途查询竞态。
  • round-2 的定时器竞态(未取消的 blur 定时器在 pickDirectory 完成后重新置位状态)——已修复。 blur 关闭现由 blurTimeoutRef 跟踪;pickDirectoryblur() 之后同步取消它,onFocus 在快速回焦时取消它,卸载时清理。有专门测试钉住"第二次 blur 取消挂起定时器而非叠加"。
  • 失焦关闭不再触碰抑制标志——改为递增序号计数器并清除陈旧建议,同时也消除了 ArrowDown 重新打开陈旧条目的路径(有对应测试)。到达门控(getShadowAwareActiveElement(input) === input)是第二道独立保险:输入框失焦时,无论标志状态如何,延迟结果都无法打开列表,且在两种嵌入模式下都成立(含 shadow-DOM portal 测试)。
  • 重复查询的根因在源头修复App.tsx 现在直接传递 workspaceActions.suggestWorkspacePaths。我确认该 actions 对象在上游已 memoize(workspace provider 中依赖为 [baseUrl, token]),普通重渲染下引用稳定,且新的 App 测试跨重渲染钉住了该引用。
  • 早前的非阻塞记录项(R2-2,三处内联的 shadow-DOM activeElement 读取)已在本 diff 内解决:utils/dom.ts 中新增的 getShadowAwareActiveElement 替换了 App.tsx 的两处拷贝并供对话框使用——是复用,不是第三份拷贝。最小化且位置恰当。

非阻塞,仅记录在案:pickDirectory 的依赖数组现在包含 path(同值比较所需),因此回调每次按键都会重建;但它仅被内联 onClick 消费,没有实际影响——不值得改。

已无 Critical 发现。

测试

无人值守 CI 运行——我没有构建或执行任何 PR 代码;以下证据是在被审查提交上通过 API 读取的 PR 自身 CI。全部通过,无失败(上方表格;macOS/Windows 单测与 CLI 集成为 merge_group 专用任务,按 ci.yml 设计跳过)。

自上次审查以来,本 PR 还附带了一份维护者验证报告(@wenshao 在本线程发布——是他的验证,针对同一 head 运行):真实 qwen serve daemon + 两个 Vite 前端(PR head 对比回退 PR 后的相同代码树),由完全相同的脚本化 Playwright 交互驱动,建议查询打真实文件系统。before arm 复现了两个症状(失焦后列表自行重开;选择完成后冗余条目重新弹出),after arm 两个场景均保持关闭。对上次审查的关注点最关键的是:变异测试显示只回退实现时 9 个新测试失败——这次的套件真正钉住了修复,而非空转通过。该报告还观察到相同交互序列下重复 daemon 查询从 12 次降到 3 次,与代码中的 memoize 修复吻合。

未验证:Windows/Linux 上的原生目录选择器行为——操作系统文件对话框在 CI 中无法脚本化,PR 声明其为范围外,且没有任何沙箱通道能驱动原生 GUI 选择器,因此该部分仍仅为 macOS 上的报告。这是唯一遗留的缺口,/verify/tmux 运行也无法补上。

真实场景测试:本次未驱动(CI 路径);实机行为信号来自上述维护者验证与通过的 web-shell E2E Smoke 检查。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — every prior blocking finding is fixed and independently verified against the head code; the two reservations are non-blocking caveats, not code issues (native picker behavior on Windows/Linux remains untested anywhere, and the PR's before-state wording about Browse holding focus turned out slightly imprecise under the maintainer's reproduction — the symptom that actually reproduces, the list staying open and reopening, is the one that got fixed).

Stepping back: this is the pass I wanted to write last time. The focus-gate plus sequence-invalidation shape is exactly what I would have proposed independently, and the PR lands all four pieces — the arrival gate, blur invalidation, Browse flag hygiene on every outcome, and the memoized-callback root cause. What moved this from "looks right" to "verified": I re-read every state path in the head code (cancelled / same-value / error picks, timer stacking, refocus before the dismiss fires, stale-sequence drops) and each one lands correctly; and the maintainer's real-stack before/after with the mutation check answers the question CI alone could not — the green suite now fails without the fix, so it pins the behavior instead of passing vacuously. The diff is 90 production lines with no drive-bys, and it retires the earlier duplication note properly instead of leaving it as debt. CI fully green on the reviewed commit, nothing pending.

Approving, pinned to the reviewed commit. The standing CHANGES_REQUESTED reviews on this PR are from earlier commits and earlier review rounds; every finding in them is addressed above, and dismissal of stale reviews is a maintainer call, so I'm leaving them untouched.

中文说明

置信度:4/5 —— 此前所有阻塞性发现均已修复,并已对照 head 代码独立验证;两点保留意见是非阻塞的注意事项,而非代码问题(Windows/Linux 上的原生选择器行为在任何环境下都仍未实测;PR 对修改前状态的描述中"Browse 会让输入框保持焦点"在维护者的复现下略有不精确——真正可复现的症状,即列表保持打开及重新弹出,正是本次修复掉的行为)。

退一步看:这正是我上次想给出的结论。焦点门控 + 序号作废的形态与我独立提出的方案完全一致,且 PR 四部分全部落地——到达门控、失焦作废、"浏览"在所有结局上的标志卫生、以及 memoize 回调这一根因修复。从"看起来对"到"已验证"的关键在于:我把 head 代码中的每条状态路径重新读了一遍(取消/同值/出错选择、定时器叠加、关闭触发前回焦、陈旧序号丢弃),每条都正确收敛;而维护者在真实栈上的 before/after 加变异测试,回答了单靠 CI 无法回答的问题——现在的绿色套件在去掉修复后会失败,因此它钉住了行为,而不是空转通过。diff 只有 90 行生产代码、无顺手改动,并且把早前的重复代码记录项妥善解决而非留成债务。CI 在被审查提交上全面通过,无待决任务。

批准,并钉在被审查的提交上。本 PR 上现存的 CHANGES_REQUESTED 评审来自更早的提交与更早的评审轮次;其中的发现均已在上方说明中解决,撤销陈旧评审属于维护者职权,故不作处理。

Qwen Code · qwen3.8-max

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

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.88% 83.88% 89.82% 83.09%
Core 87.86% 87.86% 89.39% 86.37%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.88 |    83.09 |   89.82 |   83.88 |                   
 src               |   84.97 |    81.29 |   88.49 |   84.97 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |    72.8 |    77.39 |   80.76 |    72.8 | ...1299-1303,1424 
  ...ractiveCli.ts |   86.74 |    81.15 |   88.13 |   86.74 | ...2955,2961,3026 
  ...liCommands.ts |   89.33 |     85.6 |      90 |   89.33 | ...01,518,552,674 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   71.19 |    73.65 |   90.84 |   71.19 |                   
  acpAgent.ts      |   70.59 |    73.45 |   90.37 |   70.59 | ...29,12234-12236 
  ...k-reporter.ts |     100 |    80.95 |     100 |     100 | 77,80,115,135     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...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.1 |    95.83 |   93.33 |    97.1 |                   
  filesystem.ts    |    97.1 |    95.83 |   93.33 |    97.1 | ...22-123,246-247 
 ...ration/session |   91.49 |    86.99 |   96.71 |   91.49 |                   
  Session.ts       |   90.51 |    85.18 |   95.94 |   90.51 | ...90,10717-10721 
  ...entTracker.ts |    96.8 |    89.36 |      90 |    96.8 | 137-143,221       
  ...projection.ts |   98.57 |    93.29 |     100 |   98.57 | ...76,333,344,356 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   93.44 |    91.74 |     100 |   93.44 | 74,85-88,115-125  
  ...y-replayer.ts |   98.54 |    95.65 |     100 |   98.54 | 241-243           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...lure-guard.ts |   98.32 |    97.75 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   96.01 |    94.15 |   96.66 |   96.01 |                   
  ...ageEmitter.ts |   95.95 |       96 |     100 |   95.95 | 52-59             
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  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.18 |    96.47 |     100 |   99.18 | 355-356           
 ...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/agent-view    |   89.03 |    81.31 |   89.09 |   89.03 |                   
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  ...sor-client.ts |   80.38 |    72.27 |   76.66 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    88.88 |   84.61 |   96.61 | 129-130,150-151   
  ...sor-runner.ts |    84.9 |     75.6 |      85 |    84.9 | ...44,468,471-481 
  ...sor-server.ts |   85.71 |    83.06 |   95.45 |   85.71 | ...67-468,471-488 
  ...isor-store.ts |   97.73 |    81.29 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |     91.3 |   83.33 |   93.98 | 228-238           
 src/commands      |   90.81 |    79.71 |   66.66 |   90.81 |                   
  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.66 |      100 |      50 |   98.66 | 86                
  serve.ts         |   89.84 |    77.45 |     100 |   89.84 | ...52,855-858,870 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   88.91 |    88.49 |   90.54 |   88.91 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   95.21 |    96.73 |   88.88 |   95.21 | ...18-221,266-269 
  ...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.96 |    85.39 |   94.23 |   93.96 | ...1229,1236-1237 
  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       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    85.8 |    82.17 |      88 |    85.8 | ...85,591-594,606 
  ...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.64 |   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 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   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 |    53.84 |     100 |      75 | ...27-131,133-137 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.31 |    84.61 |   83.33 |   90.31 |                   
  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          |   93.15 |    84.84 |      80 |   93.15 | ...78-180,198-199 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   87.56 |    88.09 |   88.42 |   87.56 |                   
  agent-prompt.ts  |   93.64 |    91.71 |   97.22 |   93.64 | ...2465,2589-2669 
  base-tree.ts     |   76.16 |    80.76 |   77.77 |   76.16 | ...50-371,373-386 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   89.12 |    82.22 |   83.33 |   89.12 | ...99-504,506-507 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   96.87 |    92.53 |   96.55 |   96.87 | ...2126,2154-2176 
  cost-ledger.ts   |   94.67 |    95.86 |   78.57 |   94.67 | ...04-505,545-555 
  drive.ts         |   76.07 |    85.71 |   81.81 |   76.07 | ...90-492,497-499 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-pr.ts      |    76.7 |    68.75 |   63.63 |    76.7 | ...95,417,450-455 
  findings.ts      |   89.35 |    89.13 |   95.45 |   89.35 | ...15-918,927-928 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.54 |     92.3 |   66.66 |   85.54 | 67-72,131-136     
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.66 |    96.55 |     100 |   99.66 | 404               
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   81.77 |    80.86 |   92.85 |   81.77 | ...1043,1072-1074 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ish-assets.ts |   77.18 |    82.14 |   71.42 |   77.18 | ...85-531,533-544 
  repo-context.ts  |   94.92 |    90.82 |     100 |   94.92 | ...67-368,376-377 
  ...ve-anchors.ts |   77.77 |    88.88 |      75 |   77.77 | ...77-182,194-211 
  run.ts           |   82.16 |    87.12 |   91.66 |   82.16 | ...52,468-516,529 
  save-artifact.ts |    89.9 |    81.81 |   94.11 |    89.9 | ...08-311,404-407 
  script-lint.ts   |   81.14 |    79.23 |   88.88 |   81.14 | ...59-773,775-797 
  submit.ts        |   83.77 |    83.95 |      90 |   83.77 | ...55,544,571-607 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  test-efficacy.ts |   88.04 |    84.12 |   95.45 |   88.04 | ...2602,2610-2630 
  test-plan.ts     |   91.44 |    91.39 |   89.47 |   91.44 | ...38-839,903-920 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |      97 |    94.84 |   97.77 |      97 |                   
  agent-briefs.ts  |   98.96 |      100 |      50 |   98.96 | 719-720           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  authorization.ts |    92.4 |    92.59 |     100 |    92.4 | 127-133           
  budget.ts        |     100 |    97.14 |     100 |     100 | 510,550           
  coverage.ts      |   94.48 |    94.59 |      96 |   94.48 | ...72-489,526-537 
  deadline.ts      |   98.03 |     92.1 |     100 |   98.03 | ...71,220,531,561 
  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            |   87.07 |    92.45 |   76.47 |   87.07 | ...72,309-310,337 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  ...ry-context.ts |   96.19 |    94.93 |     100 |   96.19 | ...90-491,496-499 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |     87.5 |     100 |     100 | 92                
  prompt-record.ts |   97.88 |    93.87 |     100 |   97.88 | 260-261,267       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   97.26 |    91.42 |     100 |   97.26 | 49-50             
  report.ts        |   94.68 |    93.75 |     100 |   94.68 | 189-193           
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 184               
  retirement.ts    |     100 |    92.39 |     100 |     100 | ...28,308-309,449 
  review-footer.ts |     100 |      100 |     100 |     100 |                   
  roster.ts        |     100 |    95.71 |     100 |     100 | 145,163,208       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.11 |    94.04 |     100 |   98.11 | 416,457,497-498   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.59 |    94.56 |     100 |   96.59 | ...08,297-298,323 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 172               
  workspaces.ts    |     100 |     95.9 |     100 |     100 | ...27,452,499,512 
  worktree.ts      |     100 |      100 |     100 |     100 |                   
 ...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.9 |    89.83 |   96.27 |    94.9 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  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.93 |    88.59 |   83.33 |   88.93 | ...2451,2453-2461 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |    96.5 |    93.51 |      95 |    96.5 | ...85-586,640-641 
  ...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.43 |       50 |     100 |   97.43 | 236-239           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.87 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   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 |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.27 |    92.64 |      90 |   91.27 | ...1030,1032-1033 
  ...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 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |     93.4 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    76.47 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |    85.71 |     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/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.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.98 |    77.27 |   84.12 |   80.98 |                   
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...31-632,635-636 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |    44.9 |    66.19 |   55.26 |    44.9 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   55.01 |    67.14 |   58.33 |   55.01 | ...15-624,639-644 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...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.1 |    94.13 |   95.23 |    98.1 |                   
  ...putAdapter.ts |   97.98 |     93.2 |   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.49 |      100 |   90.47 |   98.49 | 85-86,126-127     
  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/runtime       |   99.61 |    95.04 |     100 |   99.61 |                   
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   87.53 |    83.79 |   90.47 |   87.53 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.43 |    93.05 |     100 |   93.43 | ...20-321,324-326 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 672               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.89 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   88.59 |    93.68 |   96.29 |   88.59 | ...95-207,451-454 
  ...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.42 |    84.44 |    97.1 |   92.42 | ...1466,1520-1524 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.1 |    77.83 |   94.73 |    90.1 | ...1014,1021-1026 
  daemon-logger.ts |    82.2 |    77.42 |   91.76 |    82.2 | ...1720,1747-1753 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.57 |     90.8 |     100 |   98.57 | ...1411,1413-1414 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    86.95 |     100 |   92.06 | ...72,287-293,316 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.94 |    90.41 |     100 |   94.94 | ...30,708,724,734 
  fast-path.ts     |   90.99 |    81.38 |   95.45 |   90.99 | ...33-542,608-609 
  ...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-144             
  ...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 | ...30-131,142-143 
  ...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.68 |    88.29 |     100 |   92.68 | ...89-291,303-305 
  ...qwen-serve.ts |   84.01 |    80.02 |   75.43 |   84.01 | ...7461,7467-7468 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.22 |    87.96 |     100 |   94.22 | ...27,531-532,572 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   90.59 |    91.18 |   71.81 |   90.59 | ...2719,2733-2737 
  ...-admission.ts |   98.24 |    94.73 |     100 |   98.24 | 79-80,303-304     
  ...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 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |    93.3 |    76.83 |     100 |    93.3 | ...20,823,836-838 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   92.18 |    88.37 |     100 |   92.18 | ...21-224,267-270 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.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 | ...18-519,525-526 
  ...e-remember.ts |   98.23 |    92.51 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   83.98 |    90.29 |     100 |   83.98 | ...48-156,216-237 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.26 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   77.89 |    79.56 |   93.03 |   77.89 |                   
  ...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.55 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   73.19 |    76.77 |      94 |   73.19 | ...5165,5213-5219 
  index.ts         |   82.23 |    80.11 |   91.07 |   82.23 | ...2341,2425-2426 
  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 |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 src/serve/fs      |   86.46 |    81.42 |     100 |   86.46 |                   
  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 |    74.21 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.42 |    89.18 |     100 |   90.42 | 161-169           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   86.27 |    80.56 |     100 |   86.27 | ...2699,2709-2710 
 src/serve/live    |   78.04 |    69.38 |   90.56 |   78.04 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  ...-workspace.ts |   88.63 |    82.53 |     100 |   88.63 | ...40-241,253-254 
  discovery.ts     |   85.77 |    76.92 |      90 |   85.77 | ...49-250,255-256 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.75 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |   76.17 |     64.4 |   85.36 |   76.17 | ...1858,1949-1950 
  ...controller.ts |   67.82 |    79.31 |   72.72 |   67.82 | ...66-278,287-295 
  ...ak-to-user.ts |   96.66 |      100 |   83.33 |   96.66 | 37-38             
  ...sk-service.ts |   86.22 |    59.64 |   93.33 |   86.22 | ...1152,1175-1182 
  ...task-tools.ts |      99 |      100 |   85.71 |      99 | 205-206           
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.83 |    77.58 |     100 |   94.83 | ...18,327-330,350 
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/serve/routes  |   85.53 |    80.02 |   94.71 |   85.53 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   86.45 |       88 |     100 |   86.45 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health.ts        |   99.09 |    91.17 |     100 |   99.09 | 147               
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |    82.4 |    71.42 |     100 |    82.4 | ...-94,96-101,121 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.29 |    82.94 |   92.59 |   87.29 | ...1275,1318-1319 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.41 |    81.82 |   91.04 |   85.41 | ...4730,4732-4733 
  sse-events.ts    |   86.82 |    85.71 |   94.11 |   86.82 | ...16-927,930,937 
  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.92 |    79.69 |     100 |   90.92 | ...81-482,501-502 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.15 |    75.19 |   92.98 |   88.15 | ...2027,2072-2073 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...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 |   87.41 |    84.13 |     100 |   87.41 | ...1660,1680-1685 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.04 |    72.99 |     100 |   75.04 | ...79-690,696-697 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.9 |    87.15 |     100 |    76.9 | ...29-354,360-394 
  ...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.92 |    66.21 |      80 |   78.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |    90.8 |    88.48 |   96.57 |    90.8 |                   
  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 |    86.5 |    72.34 |     100 |    86.5 | ...47,764,827-836 
  fs-factory.ts    |     100 |    94.54 |     100 |     100 | 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.13 |    95.09 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |      95 |     87.5 |     100 |      95 | 182-188           
  ...on-archive.ts |   89.55 |    87.83 |   97.14 |   89.55 | ...32-836,888-889 
  ...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.02 |    97.44 |     100 |   99.02 | ...25,639,781-783 
 src/serve/voice   |    92.7 |    91.48 |   97.67 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   90.65 |    87.73 |   91.11 |   90.65 |                   
  index.ts         |   90.13 |    87.04 |   89.74 |   90.13 | ...1464-1468,1471 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.48 |    89.31 |      98 |   92.48 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 105-118           
  ...killLoader.ts |   97.19 |    85.29 |     100 |   97.19 | 142,153-154       
  ...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.77 |    92.15 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.23 |    86.48 |     100 |   88.23 | ...94-199,232-233 
  ...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.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |     86.8 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.77 |   94.73 |   88.28 | ...1362,1366-1373 
  ...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 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.09 |    79.16 |   77.77 |   94.09 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   73.08 |    75.43 |   67.41 |   73.08 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   74.29 |    72.05 |   68.57 |   74.29 | ...4112,4228-4234 
  ...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 |   70.08 |    71.73 |   66.66 |   70.08 | ...01,324,377-382 
  ...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   |   82.67 |    83.11 |   89.15 |   82.67 |                   
  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.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...28-129,137-146 
  ...essCommand.ts |   68.06 |    54.05 |      75 |   68.06 | ...96-197,211-214 
  ...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 |   69.07 |     72.6 |   84.61 |   69.07 | ...78-611,622-623 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   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   |   72.81 |    86.84 |   66.66 |   72.81 | ...63-168,277-280 
  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 |   94.44 |    90.14 |     100 |   94.44 | ...13-214,241-251 
  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  |   84.78 |    82.47 |     100 |   84.78 | ...1071,1105-1110 
  ...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.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.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 |   92.92 |       85 |   66.66 |   92.92 | ...72-177,276-281 
 src/ui/components |   71.52 |    79.07 |   79.85 |   71.52 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   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-598             
  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       |   76.99 |    66.66 |      50 |   76.99 | ...96,233,255-260 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.28 |    66.99 |     100 |   79.28 | ...08,511,514-520 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   83.26 |    82.23 |      80 |   83.26 | ...2231,2257,2331 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   96.28 |     94.8 |      50 |   96.28 | ...01,459-463,466 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   81.95 |    71.27 |     100 |   81.95 | ...1045,1050-1066 
  ...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 |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...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 |   95.67 |    87.09 |     100 |   95.67 | ...24-125,275-277 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       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 |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...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 |   85.34 |    84.91 |   92.98 |   85.34 |                   
  ...sksDialog.tsx |   81.87 |    82.77 |   85.71 |   81.87 | ...1853,1965-1971 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |   50.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 |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.26 |    86.89 |   85.57 |   90.26 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.11 |    95.91 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.63 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.06 |    86.32 |   93.75 |   93.06 | ...1037,1082-1084 
 ...ponents/shared |   86.29 |    82.41 |   94.17 |   86.29 |                   
  ...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.95 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  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 |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  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 |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.16 |    81.83 |   85.13 |   84.16 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 235-236           
  ...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.51 |    83.02 |   88.04 |   85.51 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...87-288,293-294 
  ...dProcessor.ts |   85.75 |     68.4 |   81.81 |   85.75 | ...1464,1485-1489 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...ng-enabled.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.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.53 |    83.01 |     100 |   95.53 | ...64-165,289-292 
  ...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 |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       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 |   86.08 |    81.23 |   76.92 |   86.08 | ...5198-5200,5202 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.38 |    98.85 |     100 |   98.38 | 141-144           
  ...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 |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.4 |     100 |     100 | 175,262           
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    89.9 |    81.57 |     100 |    89.9 | ...79,352-362,442 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.48 |    88.88 |     100 |   89.48 | ...54-456,489-499 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.34 |    77.14 |     100 |   95.34 | 124-125,227-232   
  ...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      |   87.24 |    85.49 |   95.64 |   87.24 |                   
  ...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.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.38 |    92.38 |     100 |   98.38 | 108,136-137,343   
  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    |   94.87 |    98.24 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.42 |       95 |     100 |   91.42 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |   96.03 |     97.1 |     100 |   96.03 | 103-106           
  ...mage-parts.ts |   97.75 |    94.87 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   82.73 |    79.48 |     100 |   82.73 | ...84-606,737-738 
  ...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 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.94 |    95.49 |   94.11 |   97.94 | ...82-283,443-444 
  ...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 |     60.3 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    66.38 |      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      |   81.27 |    79.92 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.51 |    87.08 |   92.57 |   81.51 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     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 |    89.65 |     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.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...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 | ...64,381-382,427 
  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.31 |    77.33 |     100 |   89.31 | ...87,303-304,344 
  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 |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  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.52 |    57.35 |   76.92 |   45.52 | ...1040,1052-1075 
  ...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 |       90 |     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       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...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 |   92.87 |     92.8 |   95.83 |   92.87 |                   
  cleanup.ts       |   91.86 |    92.85 |     100 |   91.86 | ...83-186,190-192 
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   95.49 |       96 |    90.9 |   95.49 | 62-66,207-211     
  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.86 |    86.37 |   89.39 |   87.86 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.38 |    84.54 |   94.85 |   90.38 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.59 |    77.55 |   83.33 |   85.59 | ...1793-1797,1800 
  ...ound-tasks.ts |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
 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 |    91.1 |    86.68 |   89.23 |    91.1 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   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.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |    92.4 |       90 |   83.78 |    92.4 | ...1862,1911-1914 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1705,1711-1712 
  ...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   |   82.04 |    84.17 |   88.97 |   82.04 |                   
  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       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  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.98 |    87.13 |   75.37 |   84.98 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.29 |    86.85 |   73.79 |   84.29 | ...8350,8354-8355 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...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          |   92.34 |    88.04 |   93.26 |   92.34 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   91.95 |    87.18 |   91.56 |   91.95 | ...3928,4026-4027 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6215,6243-6259 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  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 | 49-50             
  ...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 |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 68-72             
  ...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.67 |    93.12 |     100 |   98.67 | ...79,707-708,755 
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.33 |    88.12 |   96.15 |   96.33 |                   
  ...tGenerator.ts |   97.24 |    86.72 |   94.87 |   97.24 | ...1429,1458,1469 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1329,1550-1552 
  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.6 |    88.74 |    92.3 |    95.6 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.52 |    87.88 |   91.89 |   95.52 | ...1195-1196,1224 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.63 |    90.43 |   95.61 |   91.63 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.45 |    91.18 |     100 |   95.45 | ...1301,1309,1408 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.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 |   97.19 |    90.44 |   98.36 |   97.19 |                   
  dashscope.ts     |   98.36 |    92.99 |   95.65 |   98.36 | ...93-494,636-637 
  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     |   87.27 |    84.01 |   92.52 |   87.27 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.85 |    86.38 |   97.87 |   90.85 | ...1218-1224,1268 
  ...ionManager.ts |   82.24 |    80.14 |   81.52 |   82.24 | ...2730,2752-2753 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.36 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.42 |    82.66 |     100 |   90.42 | ...0,990-991,1001 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     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       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |    79.9 |    78.92 |    90.9 |    79.9 |                   
  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   |   71.76 |    64.76 |   71.42 |   71.76 | ...53-654,661-662 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...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         |    93.3 |    89.05 |    94.6 |    93.3 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.79 |     88.5 |   96.42 |   88.79 | ...04-805,828-831 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...83,186,190-192 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |   95.74 |    93.33 |     100 |   95.74 | 154-155           
  goal-reducer.ts  |    93.4 |    90.65 |   96.96 |    93.4 | ...27,501,519-520 
  goal-runtime.ts  |   97.62 |     89.9 |     100 |   97.62 | ...1049,1169-1170 
  goal-tools.ts    |   98.22 |    93.02 |      95 |   98.22 | ...46-147,248-249 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.34 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   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 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.12 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/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.83 |    83.94 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  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 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...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 |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...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       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  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 |    81.53 |   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.55 |    88.97 |   91.13 |   92.55 |                   
  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 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.17 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.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.63 |    89.01 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |     92.7 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.09 |   46.66 |   70.44 | ...2237,2311-2314 
  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.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   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.77 |    84.63 |   96.92 |   89.77 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |    98.5 |     87.5 |     100 |    98.5 | 81-82,105,476-477 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   91.41 |    85.15 |   95.65 |   91.41 | ...2116,2143-2144 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    93.93 |     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 |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    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.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |    90.85 |     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.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.79 |    83.72 |   97.18 |   88.79 | ...2477,2553-2573 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...pInhibitor.ts |   97.42 |    92.77 |     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 
  ...ite-origin.ts |     100 |    93.33 |     100 |     100 | 32                
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.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.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...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        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     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.72 |    89.01 |   96.55 |   87.72 |                   
  ...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.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.73 |    83.97 |   84.83 |   81.73 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...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 |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-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.1 |    95.72 |      95 |    99.1 | 145,369-370       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.03 |    76.51 |   66.07 |   60.03 | ...1484,1501-1521 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,482-483,499 
  sdk.ts           |   82.12 |    90.47 |   66.66 |   82.12 | ...90-194,232-254 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |    91.1 |    88.68 |   96.77 |    91.1 | ...1737,1768-1771 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |      83 |    94.32 |   86.36 |      83 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.02 |    98.41 |   82.92 |   96.02 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.24 |    84.99 |   88.72 |   86.24 |                   
  ...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 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.77 |   81.25 |   82.76 | ...45-746,865-915 
  ...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 |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   79.87 |    85.58 |   89.47 |   79.87 | ...2259,2263-2266 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...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.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.71 |    77.08 |   81.25 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.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 |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5036,5099-5100 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...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     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  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         |   93.11 |    92.53 |   91.66 |   93.11 | ...69-570,586-592 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   86.72 |    84.92 |   88.88 |   86.72 | ...25-828,865-900 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.22 |    87.68 |   88.69 |   87.22 |                   
  agent.ts         |   85.84 |    86.59 |   86.31 |   85.84 | ...4315,4337-4347 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.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 |   86.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.89 |    89.61 |   96.88 |   92.89 |                   
  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 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...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        |   83.01 |    95.03 |    61.9 |   83.01 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.95 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  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.1 |     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.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  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 |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...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 |   84.87 |    86.71 |   96.29 |   84.87 | ...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.34 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...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.9 |     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 |    60.86 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |    87.5 |    86.02 |     100 |    87.5 | ...76-480,510-525 
  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 |   96.74 |    91.04 |     100 |   96.74 | ...69,196,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.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.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.

@ytahdn ytahdn reopened this Aug 10, 2026
@ytahdn
ytahdn force-pushed the codex/fix-web-shell-workspace-registration branch from 46e44d4 to b3d4802 Compare August 10, 2026 07:49
@github-actions

Copy link
Copy Markdown
Contributor

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

中文

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

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

Screenshots · before / after

ℹ️ No screenshot changed against the PR base — but this PR edits 2 render-shaping files:

  • packages/web-shell/client/App.tsx
  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx

Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to packages/web-shell/client/e2e/visuals/screenshots.spec.ts that seeds whatever state the UI is gated on; it then appears here as a head-only (NEW) capture.

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

Qwen Code · web-shell visuals

@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 explored to full depth (tool budget reached): This PR fixes the web-shell AddWorkspaceDialog: it closes...: (none); This PR fixes the web-shell AddWorkspaceDialog: it closes...: (none).

中文说明

未探索到全部深度(达到工具调用预算):This PR fixes the web-shell AddWorkspaceDialog: it closes...:(none);This PR fixes the web-shell AddWorkspaceDialog: it closes...:(none)

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

Comment on lines +107 to +110
if (
inputRef.current === document.activeElement &&
(openOnResult || listOpenRef.current)
) {

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] R1-1: The new focus gate compares inputRef.current against document.activeElement, but when this dialog is portaled into the Web Shell shadow-DOM root (embedders with shadowDom: true or { portals: true }), document.activeElement retargets to the shadow host — the focused input never matches, so suggestions can never auto-open in that entire embedding mode. The codebase already documents this retargeting gotcha and uses the getRootNode() pattern for it (see the comment at App.tsx ~L3862-3865). — Failure scenario: an embedder mounts Web Shell with shadow-DOM portals → the user focuses the path input and types an absolute prefix → the lookup succeeds, but document.activeElement is the host element while shadowRoot.activeElement is the input → the gate is always false → setListOpen is never called → directory suggestions never appear for the whole shadow-DOM mode. Verified by probe in both jsdom and real Chromium (gate false, listbox never rendered); the getRootNode() fix below makes the same probe render the listbox, and all 23 existing tests still pass with it.

Suggested change
if (
inputRef.current === document.activeElement &&
(openOnResult || listOpenRef.current)
) {
if (
(inputRef.current?.getRootNode() as
| Document
| ShadowRoot
| undefined)?.activeElement === inputRef.current &&
(openOnResult || listOpenRef.current)
) {
中文说明

新的焦点门控把 inputRef.currentdocument.activeElement 比较,但当该对话框被 portal 到 Web Shell 的 shadow-DOM 根时(即嵌入方启用 shadowDom: true{ portals: true }),document.activeElement 会被重定向(retarget)到 shadow host——聚焦的输入框永远无法匹配,因此在整个该嵌入模式下建议列表永远不会自动打开。代码库中已经记录了这个 retarget 陷阱,并使用了 getRootNode() 模式(见 App.tsx ~L3862-3865 处的注释)。— 失败场景:嵌入方以 shadow-DOM portals 挂载 Web Shell → 用户聚焦路径输入框并输入绝对路径前缀 → 查询成功,但 document.activeElement 是宿主元素,而 shadowRoot.activeElement 才是输入框 → 门控恒为 false → setListOpen 永远不会被调用 → 整个 shadow-DOM 模式下目录建议都不会出现。已在 jsdom 和真实 Chromium 中通过探针验证(门控为 false,listbox 从未渲染);应用下方的 getRootNode() 修复后,同一探针可以渲染出 listbox,且全部 23 个现有测试仍然通过。

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

@ytahdn ytahdn added the autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+) label Aug 10, 2026
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。移除 autofix/takeover 标签(或评论 @qwen-code /takeover stop)即可释放。

@qwen-code-dev-bot

qwen-code-dev-bot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

AutoFix round 6 finishedview run. See this round's report below.

中文说明

AutoFix 第 6 轮已完成 —— 查看运行。本轮报告见下方。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 1/100 轮)。改动内容与我反驳保留之处如下:

Review feedback round — PR #8844

Feedback triage

  1. [Critical] R1-1 (inline comment 3747972195) — the new focus gate compares inputRef.current against document.activeElement, but when the dialog is portaled into the Web Shell shadow-DOM root (embedders with shadowDom: true or { portals: true }), document.activeElement retargets to the shadow host, so the gate never matches and directory suggestions never auto-open in that embedding mode. — Fixed. Verified against the code before changing anything: the dialog is portaled through useWebShellPortalRoot() (client/components/ui/dialog.tsx), which lives inside the shadow root in that mode, and the codebase already documents this exact retargeting gotcha with the getRootNode() workaround (client/App.tsx, the fullscreen-surface focus effect).
  2. Issue-level comment (@ytahdn, E2E test report) — informational, no action required.
  3. Issue-level comment (web-shell visual preview) — informational. The preview correctly shows no changed screenshot: this PR's change is focus-timing logic (which root's activeElement gates the suggestion list), which the seeded screenshot scenarios do not exercise. No review finding asks for a new visual scenario, so none was added.

Changes

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx — the suggestion-open gate now reads activeElement from the input's own root (inputRef.current?.getRootNode() cast to Document | ShadowRoot | undefined) instead of always using document, following the pattern already established and commented in App.tsx. Behavior in normal document mode is unchanged (getRootNode() returns document there); the blur and picker cases keep the list closed because focus is no longer on the input in any root.
  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx — added one regression test that renders the dialog into a shadow-DOM portal root (via WebShellPortalRootContext), asserts the retargeting premise (shadowRoot.activeElement is the input while document.activeElement is the host), and asserts the suggestion list opens while the input is focused. The test fails against the old document.activeElement gate and passes with the fix.

No conflicts: --conflict false, no merge performed.

Verification

  • npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx (packages/web-shell, touched) before the fix — 23 passed, 1 failed: the new shadow-DOM test reproduced the reported defect (listbox never rendered).
  • npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx (packages/web-shell, touched) after the fix — 24/24 passed.
  • npm run build — passed. (The first full web-shell suite run below was attempted before this build and failed 63 files solely on missing sibling-package build artifacts such as @qwen-code/sdk/daemon; those are environment/build-order failures, not test failures, and all cleared once the build produced the dist outputs.)
  • npx vitest run --config vitest.config.ts (full packages/web-shell unit suite, run after the build) — 177 files / 3071 tests, all passed.
  • npm run typecheck — passed.
  • npm run lint — passed.
  • npx prettier --experimental-cli --check on the two touched files — passed (the source fix was normalized with prettier --write before committing).
  • Integration tests after npm run bundle — not applicable: the changed behavior is Web Shell UI logic exercised by the package's unit tests, not by the bundled CLI or integration harness. No settings source changed, so no settings-schema regeneration was needed.

Commit: 67c0e3db67 fix(web-shell): read suggestion focus gate from the input root (#8844)

中文说明

评审反馈轮次 — PR #8844

反馈分类

  1. [Critical] R1-1(行内评论 3747972195) — 新的焦点门控把 inputRef.currentdocument.activeElement 比较,但当对话框被 portal 到 Web Shell 的 shadow-DOM 根时(即嵌入方启用 shadowDom: true{ portals: true }),document.activeElement 会被重定向(retarget)到 shadow host,因此门控永远无法匹配,整个该嵌入模式下目录建议永远不会自动打开。— 已修复。 修改前先在代码中核实:该对话框通过 useWebShellPortalRoot() 做 portal(client/components/ui/dialog.tsx),在该模式下 portal 根位于 shadow root 内部;而且代码库中已经记录了同一个 retarget 陷阱及其 getRootNode() 解决方案(client/App.tsx 中全屏 surface 的焦点处理 effect)。
  2. Issue 级评论(@ytahdn 的 E2E 测试报告)— 信息性内容,无需处理。
  3. Issue 级评论(web-shell 可视化预览)— 信息性内容。预览未显示截图变化是正确的:本 PR 的改动是焦点时序逻辑(用哪个根的 activeElement 来控制建议列表的开关),种子截图场景不会执行到该行为。没有任何评审发现要求新增可视化场景,因此未添加。

变更内容

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx — 建议列表的打开门控现在从输入框自身的根节点(inputRef.current?.getRootNode(),转换为 Document | ShadowRoot | undefined)读取 activeElement,而不是始终使用 document,沿用 App.tsx 中已有并附注释的模式。普通 document 模式下行为不变(此时 getRootNode() 返回 document);blur 和系统选择器场景下列表仍保持关闭,因为在任何根中焦点都不再位于输入框上。
  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx — 新增一个回归测试:把对话框渲染进 shadow-DOM portal 根(通过 WebShellPortalRootContext),断言 retarget 前提成立(shadowRoot.activeElement 是输入框,而 document.activeElement 是宿主元素),并断言输入框保持聚焦时建议列表会打开。该测试在旧的 document.activeElement 门控下失败,在修复后通过。

无冲突:--conflict false,未执行任何合并。

验证

  • npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx(packages/web-shell,被改动包)修复前 — 23 通过、1 失败:新增的 shadow-DOM 测试复现了报告中的缺陷(listbox 始终未渲染)。
  • npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx(packages/web-shell,被改动包)修复后 — 24/24 全部通过。
  • npm run build — 通过。(下面第一次完整 web-shell 套件运行在该构建之前执行,63 个文件的失败全部源于缺少兄弟包的构建产物,例如 @qwen-code/sdk/daemon;这些是环境/构建顺序问题而非测试失败,构建产出 dist 后全部消失。)
  • npx vitest run --config vitest.config.ts(packages/web-shell 完整单测套件,构建后运行)— 177 个文件 / 3071 个测试,全部通过。
  • npm run typecheck — 通过。
  • npm run lint — 通过。
  • 对两个被改动文件执行 npx prettier --experimental-cli --check — 通过(源码修复在提交前已用 prettier --write 规范化)。
  • npm run bundle 之后的集成测试 — 不适用:被改动的行为是 Web Shell UI 逻辑,由该包的单元测试覆盖,不经过打包后的 CLI 或集成测试框架。未改动任何 settings 源,因此无需重新生成 settings schema。

提交:67c0e3db67 fix(web-shell): read suggestion focus gate from the input root (#8844)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

Comment on lines 161 to 163
if (!onPick) return;
inputRef.current?.blur();
setBrowsing(true);

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] R2-1: Browse leaves a stale suppressNextFetchOpenRef, so the first keystroke after a cancelled (or same-path) pick never opens the suggestion list.

The inputRef.current?.blur() added here routes Browse through the input's onBlur, whose 100 ms timer sets suppressNextFetchOpenRef.current = true. That flag is consumed only by the path-change effect's absolute-like branch (openOnResult = !suppressNextFetchOpenRef.current; suppressNextFetchOpenRef.current = false;, lines 98-99). When the picker is cancelled (onPick resolves undefined -> no setPath) or the user selects the already-typed path (React state bail-out -> the effect does not re-run), nothing consumes the flag.

  • Failure scenario: open Add Workspace -> click Browse (the blur schedules the 100 ms timer, flag is set) -> cancel the native picker -> click back into the input and type an absolute prefix such as /h: the lookup resolves with the input focused, but openOnResult is false and listOpenRef.current is false, so the gate skips setListOpen and the listbox stays closed; suggestions appear only from the second keystroke. Reproduced deterministically by probe in jsdom (listbox null on keystroke 1, open on keystroke 2, for both the cancel and same-path variants); pre-diff, the removed onMouseDown preventDefault kept focus in the input, so this path never fired onBlur in the test harness. This also contradicts the PR's own E2E evidence ("selecting the current input path does not disable autocomplete on the next manual edit"); the earlier iteration carried a same-path regression test that this iteration dropped.

Suggested fix - reset the flag once the picker outcome is known (a few lines below in pickDirectory), and add a regression test for typing after a cancelled picker:

    try {
      const selectedPath = await onPick();
      suppressNextFetchOpenRef.current = false;
      if (selectedPath) {

The result-arrival focus gate above already keeps the list closed for a delayed lookup while the input is unfocused, so this reset does not re-open the race this PR fixes.

中文说明

"浏览"会留下一个过期的 suppressNextFetchOpenRef 标志,导致取消选择器(或选择了相同路径)之后,第一次按键不会打开建议列表。

此处新增的 inputRef.current?.blur() 使"浏览"流程经过输入框的 onBlur,其 100 ms 定时器会设置 suppressNextFetchOpenRef.current = true。该标志只在路径变化 effect 的绝对路径分支中被消费(openOnResult = !suppressNextFetchOpenRef.current; suppressNextFetchOpenRef.current = false;,第 98-99 行)。当用户取消系统选择器(onPick 返回 undefined → 没有 setPath)或选择了与已输入内容相同的目录(React 状态未变化 → effect 不会重新运行)时,没有任何逻辑消费该标志。

  • 失败场景:打开"添加工作区" → 点击"浏览"(blur 触发 100 ms 定时器,标志被置位)→ 取消系统目录选择器 → 重新点击输入框并输入绝对路径前缀(如 /h):查询在输入框聚焦时返回结果,但 openOnResultfalselistOpenRef.currentfalse,门控跳过 setListOpen,列表保持关闭;建议要到第二次按键才出现。已在 jsdom 中通过探针确定性复现(取消和相同路径两种变体均为:第一次按键 listbox 为 null,第二次按键才打开)。修改前,被移除的 onMouseDown preventDefault 会让输入框保持聚焦,该路径在测试框架中从未触发 onBlur。这也与本 PR 自己的 E2E 证据相矛盾("选择当前输入路径不会禁用下一次手动编辑时的自动补全");之前的迭代版本带有相同路径的回归测试,本次迭代删除了它。

建议修复 —— 在选择器结果确定后重置该标志(位于下方 pickDirectory 中,代码见上),并补充"取消选择后继续输入"的回归测试。上方的结果到达焦点门控已经保证:输入框失焦时延迟返回的查询不会打开列表,因此该重置不会重新引入本 PR 要修复的竞争。

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

Comment on lines +115 to +116
)?.activeElement === inputRef.current &&
(openOnResult || listOpenRef.current)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-2: The shadow-DOM-aware focus query is now hand-inlined a third time - extract a shared helper.

The getRootNode()-based activeElement read added here is the third copy: App.tsx:3864-3865 and App.tsx:3925-3927 already carry the same cast with a near-identical retargeting comment, and no shared helper exists (utils/dom.ts has only isEditableTarget, portalRoot.ts only the context). The copies have already diverged on null handling - the App.tsx sites cast without undefined and dereference directly, while this site adds | undefined and optional chaining.

  • Concrete cost: a fix to the focus-resolution rule (nested shadow trees, a new root kind) must be applied to three sites found only by grepping a comment; a fix landing in one copy but not the others yields different focus behaviour between the fullscreen-surface focus trap, the Tab trap, and this dialog's autocomplete. The divergence already bites elsewhere: AtMentionPanel.tsx:75 still uses the naive document.activeElement === searchInputRef.current form (never true in shadow-DOM portal mode, so its "already focused" guard is dead there), and DialogShell.tsx:84 records the retargeted document.activeElement as the focus-restore target.

Suggested fix:

// e.g. in client/utils/dom.ts or portalRoot.ts
export function getRootActiveElement(
  node: Node | null | undefined,
): Element | null {
  const root = node?.getRootNode();
  return root instanceof Document || root instanceof ShadowRoot
    ? root.activeElement
    : null;
}

and route this site plus the two App.tsx sites through it.

中文说明

shadow-DOM 感知的焦点查询现在是第三处手写内联 —— 建议抽取共享辅助函数。

此处新增的基于 getRootNode()activeElement 读取是第三份拷贝:App.tsx:3864-3865App.tsx:3925-3927 已经有相同的类型转换和几乎一致的 retarget 注释,且目前不存在共享辅助函数(utils/dom.ts 只有 isEditableTargetportalRoot.ts 只有 context)。这些拷贝在空值处理上已经出现分歧 —— App.tsx 处的转换不含 undefined 且直接解引用,而本处增加了 | undefined 和可选链。

  • 具体代价:一旦焦点解析规则需要修复(嵌套 shadow 树、新的根类型),就必须把修复应用到三处只能通过 grep 注释才能找到的位置;如果修复只落在其中一份拷贝上,全屏 surface 焦点陷阱、Tab 陷阱和本对话框的自动补全将表现出不同的焦点行为。这种分歧已经在其他地方造成问题:AtMentionPanel.tsx:75 仍在使用朴素的 document.activeElement === searchInputRef.current 形式(在 shadow-DOM portal 模式下永远不为真,其"已聚焦"守卫在那里是死代码),DialogShell.tsx:84 则把 retarget 后的 document.activeElement 记录为焦点还原目标。

建议修复(代码见上):在 client/utils/dom.tsportalRoot.ts 中抽取类似 getRootActiveElement 的辅助函数,并让本处与 App.tsx 的两处都改用它。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix ran out of time before finishing (idle-timeout (no output for 1200000ms — the sandbox likely hung at startup)) (attempt 2/100) — it will retry on the next scan.

What I found before stopping:
Qwen failed during address-review: idle-timeout (no output for 1200000ms — the sandbox likely hung at startup).

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31381560750


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix ran out of time before finishing (idle-timeout (no output for 1200000ms — the sandbox likely hung at startup)) (attempt 3/100) — it will retry on the next scan.

⚠️ This change was NOT pushed — any commit referenced below was made only in the runner workspace and has been discarded. What the agent reported:
Qwen failed during address-review: idle-timeout (no output for 1200000ms — the sandbox likely hung at startup).

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31383566918


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@ytahdn

ytahdn commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 10, 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: 86 passed · 0 failed · 86 total

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

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

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

Verification report

PR 8844 deep verification — fix(web-shell): keep workspace picker suggestions closed

Verdict: merge-ready — 86/86 scripted assertions passed (0 unexpected failures).
Verified head: 67c0e3db67ec8f63332eea507a0d6cc1c016e8f3 (git rev-parse HEAD^2 of merge commit 7a6eba6c), base 0d56e50b64 (HEAD^1).
Note: the metadata snapshot's baseRefOid (feea8064…) predates the checked-out merge-ref base; per the CI contract the effective diff HEAD^1..HEAD was measured.

中文摘要
  • 结论: merge-ready。86/86 脚本化断言全部通过,无阻塞性发现。
  • A/B 结论: 中心声明成立且被证明是 load-bearing。同一 jsdom 场景在三个构建上运行(base 0d56e50b / commit 1 b3d4802e / head 67c0e3db),每个构建 23 个检查点:
    • base 复现全部症状:blur 后延迟返回的查询会重新打开建议列表;点击 Browse 后输入框保持焦点、弹窗在选择器打开期间持续可见、填入路径后列表带着已选目录重新出现;
    • commit 1(焦点门控 + picker 前 blur() + 移除按钮 mousedown preventDefault)修复了全部 document 模式症状,但其 document.activeElement 门控在 shadow-DOM portal 模式下导致建议列表无法打开(新回归);
    • commit 2(改从 inputRef.current.getRootNode().activeElement 读取焦点)修复 shadow-DOM 回归且保留全部既有修复。两个 commit 均被证明不可或缺(见下表与图 01-ab-base-inter-head-cells.png)。
  • 测试非空洞: 对 PR 自带测试做变异矩阵(图 02-mutation-matrix-live.png):还原门控、改回 document.activeElement、删除 blur() 三个单点变异分别被恰好对应的测试以行为断言(expected <ul …> to be null 等)杀死;恢复 onMouseDown preventDefault 存活(jsdom 的 .click() 不触发 mousedown,已分类说明,非修复路径缺口)。
  • 门槛: web-shell 单测 177 文件 3071/3071 通过;typecheck 与 eslint 干净(两者均先以植入错误验证门槛是活的)。
  • 发现(均为信息级): ① 预先存在、本 PR 未改变的小毛病:blur 超过 100ms 后重新聚焦输入的第一个字符不会弹出建议(A/A 证据:三个构建行为完全一致);② PR 描述写 “23/23”,head 上实际为 24 个测试(第 24 个由 commit 2 新增)——仅为描述更正。
  • 未覆盖: 真实系统目录选择器(onPick 在 prop 边界被 mock);真实浏览器指针语义(jsdom 不模拟 mousedown 焦点转移);仓库级门槛;Playwright e2e。

1. Central claim and A/B proof

Central claim. Once the workspace-path input loses focus, the directory-suggestion list closes and stays closed — a delayed lookup completing after blur must not reopen it, and the Browse flow must fill the selected path with the input unfocused and no list.

Mechanism under test. The suggestion-result handler now opens the list only when the input is the active element of its own root (inputRef.current.getRootNode().activeElement === inputRef.current), pickDirectory() blurs the input before opening the native picker, and the Browse button's focus-retaining onMouseDown preventDefault was removed. (The 100 ms-delayed closeList() on blur and suppressNextFetchOpenRef already existed on base.)

The PR bundles two commits, and both objects were available despite the shallow checkout (b3d4802e is present in the object store; 67c0e3db's parent pointer confirms the chain), so the A/B was run as a three-build table — base, commit 1's tree as a faithful worktree, and head. The same 23-check harness (harness/pr8844-verify-ab.test.tsx, driven with fake timers, controlled onSuggest/onPick promises at the prop seam) ran in each tree with per-variant expectations encoded, so every bug cell is an assertion that the build misbehaves as predicted — predicted base reds count as passing assertions.

cell oracle base 0d56e50b commit 1 b3d4802e head 67c0e3db
C0 focused input opens suggestions listbox present opens opens opens
C1d lookup resolves after blur listbox present reopens (bug) closed closed
C2b/d focus retained during/after Browse activeElement === input retained (bug) released released
C2Bb list visible 100 ms into open picker listbox present visible (bug) closed closed
C2e/f list reopens after fill, offers the already-selected dir listbox + code/ option reopens (bug) closed closed
C3c shadow-DOM portal root, focused input listbox inside shadow root opens never opens (bug) opens
C4a–d refocus-after-blur A/A controls 4 checks identical identical identical

Result: 23/23 checks matched prediction in all three builds (69 assertions) — base reproduces every symptom the PR describes (including the "redundant option": the reopened list offers /Users/me/code right after the user selected it); commit 1 flips all five document-mode cells but breaks shadow-DOM mode (document.activeElement retargets to the shadow host — control C3b proves the retargeting in the same cell); commit 2 flips exactly that cell back while keeping every commit-1 fix. Both commits are load-bearing. jsdom semantics that make the focus cells discriminating were measured directly first (disabling a focused input neither moves focus nor fires blur in jsdom 26, so on base nothing ever blurs the input through Browse).

Witness: evidence/01-ab-base-inter-head-cells.png (live re-run of all three arms printing the full CHECK grid).

2. Corrections to the PR description

  • The description's evidence line says "focused Web Shell tests (23/23)". At head the file contains 24 tests: commit 1's file had 23, and the follow-up commit 2 added the shadow-DOM test. All 24 pass (measured, M0 below). This is a description correction only — no code change implied.

3. Vacuity check and mutation matrix (PR's own tests)

Unmutated control is green (M0: 24/24). Single-point mutants of the production file, run against the PR's unmodified test file (swap-and-restore with git restore, verified clean; junit scored programmatically):

mutant change killed by failure message (behavioural)
M1 gate reverted to if (openOnResult || listOpenRef.current) exactly 2 tests: keeps suggestions closed when a lookup finishes after blur, opens the system picker and fills the selected absolute path expected <ul …(4)>…(2)</ul> to be null (both)
M2 gate reads document.activeElement (recreates commit 1) exactly 1 test: opens suggestions for a focused input in a shadow-DOM portal root expected null not to be null
M3 inputRef.current?.blur() removed from pickDirectory exactly 1 test: opens the system picker… expected <input …> not to be <input …>
M4 onMouseDown={(e) => e.preventDefault()} restored on Browse survives (24/24 still green)

Every revert fails the intended behavioural assertion (list visibility / focus), not an import or fixture break, and each new guard is pinned by exactly the test the commit says it strengthens. M2's kill is the positive control proving commit 2's one-line change is what the shadow-DOM test pins.

M4 survivor classification — redundant-clause removal, not a coverage gap on the fix path: jsdom's HTMLElement.click() fires no mousedown, so no jsdom test can express the clause's production effect (preventing focus loss on pointer-down). In production the removal is redundant next to the new explicit blur() — the input is blurred before the picker either way — so the surviving mutant confirms an unpinnable-in-jsdom clause, not an untested fix.

Witness: evidence/02-mutation-matrix-live.png (live M0–M4 run + encoded scoring, 11/11).

4. Findings

  1. Pre-existing quirk, not caused or worsened by this PR (informational). After the list closes on blur, the first keystroke once the input is refocused (>100 ms later) fetches suggestions but does not show them; the second keystroke does. Cause: the pre-existing blur handler sets suppressNextFetchOpenRef = true at +100 ms and the next path-change effect consumes it. Measured A/A: cells C4a–d are byte-identical across base, commit 1 and head, so the PR neither introduced nor changed it; the PR's risk note ("cannot become visible until existing input interactions open them again") is slightly optimistic about the very first interaction. Worth a separate issue if maintainers care; not a merge condition.
  2. M4 survivor (informational) — classified above; no action needed.

5. Not covered

  • Real native directory picker on any OS: onPick is a host-provided callback and was driven with controlled promises at the prop seam. Picker UX was verified only by the author on macOS.
  • Real-browser pointer semantics (mousedown-driven focus movement, click-outside targeting): jsdom does not simulate them; cells drive .click()/.blur() directly. This is why M4 survives and is also the reason the Reviewer Test Plan's "click outside" step was exercised as a blur() event — the wire shape is reproduced, the pointer mechanism is not.
  • Repo-wide gates were not run — the effective diff touches only packages/web-shell, so gates were scoped to that workspace (3071-test suite, tsc -p tsconfig.json --noEmit, eslint packages/web-shell), each proven live with a planted violation first (evidence/03-gates-and-liveness.png).
  • Playwright e2e suites (test:e2e*) not run — unit-level A/B was chosen instead.
  • Commit 1's own diff vs its parent (2e3d297e, not fetchable at depth 2) was not measured; commit 1 was verified as its faithful tree state. The aggregate HEAD^1..HEAD diff is fully covered.
  • Dialog closed mid-flight: if the dialog unmounts while a lookup is pending, React nulls the ref and the gate evaluates undefined === null → false (fail-closed), and the state setters are no-ops on an unmounted component — static analysis only, no cell.

6. Methodology

Environment: CI verify container (node:22-bookworm), Node 22.23.2, vitest 3.2.4, jsdom 26.1.0; repo pre-installed and pre-built at the merge commit. A/B arms ran in git worktrees (HEAD^1 and b3d4802e) reusing the root node_modules (lockfile untouched by the PR; AddWorkspaceDialog's import closure contains no @qwen-code/* packages — grep-verified — so no internal symlink could leak head code into a control arm). The harness renders the real component through real react-dom into jsdom (plain document and shadow-root portal modes), drives it with fake timers and controlled prop promises, and records every check as CHECK|variant|id|PASS/FAIL|… lines plus a JSON tally per arm. Mutations were applied by swapping the single production file and restoring via git restore (clean status verified after each run); scoring parses the junit XML written by the repo's own vitest config. Gates were scored the same way. Raw per-cell logs, harness sources, mutants, junit files and tallies live under logs/ and harness/ in this artifact directory.

Evidence images

01-ab-base-inter-head-cells

02-mutation-matrix-live

03-gates-and-liveness

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

The bot already has a review of its own on 67c0e3db67ec8f63332eea507a0d6cc1c016e8f3, which still stands.

机器人在 67c0e3db67ec8f63332eea507a0d6cc1c016e8f3 上已有自己的评审,且仍然有效。

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

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run.

中文说明

🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind main, so it merged current main in via update-branch and will retry on the next scan. A stale base (a dependency or symbol main already changed) can fail the build without being the fix's fault; if it still fails once current, it hands off to a human.

What I found before stopping:
Qwen failed during address-review: status 125.

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31394772225


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix stopped: this counting window now contains 3 time-budget exhaustions (pushed rounds in between included; this round itself may have failed differently). That is 3 full agent runs that pushed nothing. 3 of those were silent-sandbox (idle) timeouts that no budget increase can cure — investigate the sandbox image and runner docker daemon for those. A human should investigate the sandbox image and runner docker daemon, then comment @qwen-code /retry to re-arm. Until then future scans will skip this PR.

What I found before stopping:
Qwen failed during address-review: idle-timeout (no output for 1200000ms — the sandbox likely hung at startup).

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31399630023


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

…og (#8844)

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

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下:

Autofix review round — PR #8844

Feedback dispositions

  • [Suggestion] onBlur re-blur timer cancellation is untested (AddWorkspaceDialog.tsx:310, rc:3755220628) — Addressed. The finding is valid: no test blurs the input twice, and nothing pinned the clearTimeout guard. Added a regression test 'opens suggestions on the first edit after a re-blur within the blur window' following the suggested scenario: blur @t=0, refocus, blur again @t=60 while the first 100 ms timer is still pending, refocus, cross the first timer's original deadline, type an absolute prefix, settle, and assert listbox() is not null after the first edit. Verified the test pins the guard via a mutation probe: removing the clearTimeout makes exactly this test fail (1 failed | 27 passed), restoring the guard returns the file to 28/28. Without the guard, the stale first timer fires after the refocus and sets suppressNextFetchOpenRef, so the path-change effect captures openOnResult = false and the focused first edit's lookup stays closed until the second keystroke — the one-edit-delay regression the finding describes.
  • Review-body notes "Not explored to full depth (tool budget reached)" — informational reviewer budget notes, not findings; no action.

Changes

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx — one new test (+34 lines) in the existing path autocomplete suite, reusing the established helpers (mount, input, type, settle, listbox) and fake timers. No production code changed.

Conflict notes

None (--conflict false; no merge performed).

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • vitest AddWorkspaceDialog.test.tsx (packages/web-shell) — 28 passed (28)
  • vitest run (full packages/web-shell suite) — 177 files passed, 3075 tests passed
  • Mutation probe: removed the clearTimeout guard locally, reran the test file — the new test failed as expected (1 failed | 27 passed); guard restored afterwards (component byte-identical to its committed state)
  • Integration tests: not applicable — change is a component unit test, not behavior exercised only through the bundled CLI or integration harness
  • Settings schema: not applicable — no settings source changed

Commit: 2ff92ea2cf test(web-shell): cover re-blur timer cancellation in AddWorkspaceDialog (#8844)

中文说明

Autofix 审查轮次 — PR #8844

反馈处理

  • [Suggestion] onBlur 中的重复失焦定时器取消逻辑没有测试覆盖AddWorkspaceDialog.tsx:310,rc:3755220628)— 已处理。 该发现成立:没有任何测试让输入框连续失焦两次,也就没有任何测试钉住这个 clearTimeout 守卫。新增了回归测试 'opens suggestions on the first edit after a re-blur within the blur window',完全按照建议的场景执行:t=0 失焦、重新聚焦、在第一个 100 ms 定时器仍挂起时于 t=60 再次失焦、重新聚焦、越过第一个定时器的原始触发时限、输入绝对路径前缀、settle,然后断言第一次编辑后 listbox() 不为 null。并通过变异探针验证该测试确实钉住了守卫:删除这个 clearTimeout 后恰好只有这个测试失败(1 失败 | 27 通过),恢复守卫后该文件恢复 28/28 全绿。若没有该守卫,残留的第一个定时器会在重新聚焦之后触发并设置 suppressNextFetchOpenRef,导致路径变化 effect 捕获到 openOnResult = false,聚焦状态下第一次编辑的查询结果保持列表关闭,直到第二次按键才出现——正是该发现描述的"延迟一次按键"回归。
  • 审查正文中的 "Not explored to full depth (tool budget reached)" — 属于审查者的预算说明性备注,不是发现项;无需处理。

变更内容

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx — 在现有 path autocomplete 测试套件中新增一个测试(+34 行),复用既有辅助函数(mountinputtypesettlelistbox)和假定时器。未改动任何生产代码。

冲突说明

无(--conflict false,未执行合并)。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • vitest AddWorkspaceDialog.test.tsx(packages/web-shell)— 28 通过(共 28)
  • vitest run(packages/web-shell 完整套件)— 177 个文件通过,3075 个测试通过
  • 变异探针:在本地删除 clearTimeout 守卫后重跑该测试文件 — 新测试如预期失败(1 失败 | 27 通过);随后恢复守卫(组件与已提交状态逐字节一致)
  • 集成测试:不适用 — 本次变更为组件单元测试,不属于仅通过打包后 CLI 或集成测试框架才能验证的行为
  • Settings schema:不适用 — 未改动任何 settings 源

提交:2ff92ea2cf test(web-shell): cover re-blur timer cancellation in AddWorkspaceDialog (#8844)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

Not explored to full depth (tool budget reached): You are review agent reverse-audit — Reverse audit agen...: none — all planned checks completed within budget..

中文说明

已审查。 建议见行内评论。

未探索到全部深度(达到工具调用预算):You are review agent reverse-audit — Reverse audit agen...:none — all planned checks completed within budget.

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

Comment on lines +310 to +311
blurTimeoutRef.current = setTimeout(() => {
blurTimeoutRef.current = undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The newly tracked blur timer is cancelled on re-blur and in pickDirectory, but never when focus returns to the input — there is no onFocus handler. If the user blurs and refocuses within the 100 ms window, the pending timer fires on a focused input: closeList() visibly dismisses an open list mid-interaction and suppressNextFetchOpenRef.current = true persists, so the next edit's path-change effect consumes the stale flag (openOnResult = false) and that edit's lookup never opens the list — only the second keystroke does. This PR took explicit ownership of this timer's lifecycle (tracking ref, two cancellation sites, and a test asserting cancellation semantics), leaving focus-return as the one schedule site the new lifecycle never clears. Probe-verified at the reviewed commit: list open → blur → refocus within 100 ms → timer fires → first edit CLOSED / second edit OPEN; an onFocus that clears blurTimeoutRef flips the probe to OPEN / OPEN. — Failure scenario: suggestion list open → user clicks another element and clicks back into the path input within 100 ms → the timer fires while the input is focused → the open list visibly closes and the next keystroke shows no suggestions (recovers on the following keystroke).

Suggested fix — cancel the pending timer when focus returns:

onFocus={() => {
  if (blurTimeoutRef.current !== undefined) {
    clearTimeout(blurTimeoutRef.current);
    blurTimeoutRef.current = undefined;
  }
}}
中文说明

新增的受跟踪 blur 定时器会在重复失焦时以及 pickDirectory 中被取消,但当焦点回到输入框时从未被取消——组件没有 onFocus 处理器。如果用户在 100 ms 窗口内先失焦再重新聚焦,挂起的定时器会在输入框已聚焦时触发:closeList() 会把正在显示的列表关闭(用户可见),并且 suppressNextFetchOpenRef.current = true 残留;下一次编辑的路径变化 effect 会消费这个过期标志(openOnResult = false),导致该次编辑的查询不打开列表——要到第二次按键才恢复。本 PR 已明确接管了这个定时器的生命周期(跟踪 ref、两处取消点、以及一个断言取消语义的测试),焦点回归是新生命周期唯一没有清理的调度点。已在被审 commit 上通过探针验证:列表打开 → 失焦 → 100 ms 内重新聚焦 → 定时器触发 → 第一次按键列表关闭 / 第二次按键打开;增加一个清除 blurTimeoutRefonFocus 后探针翻转为 打开 / 打开。— 失败场景:建议列表已打开 → 用户点击其他元素并在 100 ms 内点回路径输入框 → 定时器在输入框聚焦时触发 → 打开的列表被关闭,且下一次按键没有建议(再下一次按键恢复)。

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

Comment on lines +79 to +81
const blurTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(
undefined,
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The tracked blur timer has no unmount cleanup: closing the dialog within 100 ms of a blur leaves the pending timer to fire on the dead component — it writes suppressNextFetchOpenRef.current = true on a dead ref and runs closeList() (setListOpen/setHighlight) against an unmounted component. Probe-verified on this package's React 19: a silent no-op today (no exception, no state-update warning) with ≤100 ms closure retention — but the codebase's own precedent for this exact delayed-close pattern pairs the timer ref with a dedicated unmount cleanup (ArtifactPanel.tsx clears sideTaskMenuCloseTimerRef in a mount-effect cleanup), and the dialog's other timers/listeners (suggest debounce, window keydown capture) all clean up on unmount. This PR otherwise carefully tracks the timer through its schedules; unmount is the one site nothing clears. — Concrete cost: post-unmount state writes plus divergence from the sibling pattern; a future edit or a harness that surfaces post-unmount updates would turn the silent no-op into noise.

Suggested fix, next to the existing mount-focus effect:

useEffect(
  () => () => {
    if (blurTimeoutRef.current !== undefined) {
      clearTimeout(blurTimeoutRef.current);
    }
  },
  [],
);
中文说明

受跟踪的 blur 定时器没有卸载清理:在失焦后 100 ms 内关闭对话框,挂起的定时器会在已卸载的组件上触发——向已失效的 ref 写入 suppressNextFetchOpenRef.current = true,并对已卸载组件执行 closeList()setListOpen/setHighlight)。已在本包的 React 19 上通过探针验证:目前是静默无操作(无异常、无 state 更新警告),闭包保留不超过 100 ms——但代码库中对同一"延迟关闭"模式的既有先例是为定时器 ref 配套专门的卸载清理(ArtifactPanel.tsx 在挂载 effect 的清理中清除 sideTaskMenuCloseTimerRef),且本对话框的其他定时器/监听器(建议 debounce、window keydown 捕获)都在卸载时清理。本 PR 在其他方面都小心地跟踪了这个定时器的各个调度点;卸载是唯一没有任何清理的调度点。— 具体代价:卸载后的状态写入,以及与兄弟模式的偏离;未来某次修改或某个会暴露卸载后更新的测试框架,会把这个静默无操作变成噪音。

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

expect(listbox()).toBeNull();
});

it('keeps suggestions closed when a lookup finishes after blur', async () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] No test opens the suggestion list before blurring the input, so closeList() inside the tracked blur timer is a surviving mutant: deleting only that line keeps the whole 28-test suite green (verified by a mutant run at the reviewed commit) — the two blur-based tests blur while their fetch is still pending (the list is never open before the blur), and the picker paths call closeList() directly. The PR's headline behavior — "close workspace path suggestions whenever the path input loses focus" — is therefore pinned by nothing. — Failure scenario: a future edit to this timer body (which this PR already restructured once) could ship with the list staying open after the user clicks away, suite green; the untested path is the PR's own stated purpose, and the regression would be user-visible yet invisible to CI.

Suggested regression test:

it('closes the suggestion list when the input blurs', async () => {
  const onSuggest = vi.fn().mockResolvedValue(SUGGESTIONS);
  mount(
    <AddWorkspaceDialog onClose={vi.fn()} onAdd={vi.fn()} onSuggest={onSuggest} />,
  );
  type('/home/me/co');
  await settle();
  expect(listbox()).not.toBeNull();
  act(() => input().blur());
  await act(async () => {
    await vi.advanceTimersByTimeAsync(100);
  });
  expect(listbox()).toBeNull();
});
中文说明

没有任何测试先把建议列表打开再让输入框失焦,因此受跟踪 blur 定时器中的 closeList() 是一个存活的变异体:只删除这一行,全部 28 个测试仍然通过(已在被审 commit 上通过变异运行验证)——两个基于 blur 的测试在查询尚未返回时就失焦(blur 前列表从未打开),而选择器路径会直接调用 closeList()。因此本 PR 的核心行为——"路径输入框失焦时关闭工作区路径建议"——没有被任何测试钉住。— 失败场景:未来对这个定时器主体的修改(本 PR 已经重构过一次)可能让"用户点击别处后列表仍然打开"的回归被发布,而测试套件依然全绿;未被测试的路径正是本 PR 自己声明的目标,该回归用户可见、CI 不可见。

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

Comment on lines +183 to +184
// Cancelled, failed, or same-value pick: the first edit must open.
suppressNextFetchOpenRef.current = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] A same-value pick no longer invalidates an in-flight suggestion lookup. Pre-diff, every truthy pick bumped suggestSeqRef.current, discarding in-flight lookups; this branch clears the suppress flag but does not bump the seq. A lookup that was debounced/in flight when Browse was clicked therefore passes the seq check when it resolves; if the user has refocused the input, the focus gate passes and the stale lookup pops the list open on mere refocus with zero edits — violating the invariant the adjacent test encodes ("Refocusing ... must not pop the list open; only a real edit may"). Probe reproduced this deterministically at the reviewed commit (type → Browse inside the debounce window → same-value pick → refocus → listbox OPEN), and bumping the seq for a truthy same-value pick flips it to CLOSED. — Failure scenario: user types an absolute path, clicks Browse while the lookup is still debounced/in flight (a window that includes daemon latency), confirms the same path in the native picker, and clicks back into the input: the listbox pops open unprompted; with exactly one suggestion, the single-suggestion Tab-accept path can then rewrite the typed path.

Suggested change
// Cancelled, failed, or same-value pick: the first edit must open.
suppressNextFetchOpenRef.current = false;
// Cancelled, failed, or same-value pick: the first edit must open.
// A same-value pick keeps the typed path; invalidate any lookup
// already in flight from before Browse was clicked.
if (pickedPath) ++suggestSeqRef.current;
suppressNextFetchOpenRef.current = false;
中文说明

选择与已输入内容相同的路径时,不再使正在进行的建议查询失效。修改前,任何非空选择都会递增 suggestSeqRef.current 以丢弃在途查询;该分支现在清除了抑制标志,但没有递增 seq。因此,点击"浏览"时已处于 debounce 或在途的查询在返回时仍能通过 seq 检查;若用户此时已重新聚焦输入框,焦点门控通过,过期查询会在零次编辑时仅因重新聚焦就弹出列表——违反了相邻测试所编码的不变量("重新聚焦……不得弹出列表;只有真正的编辑才可以")。已在被审 commit 上通过探针确定性复现(输入 → 在 debounce 窗口内点击浏览 → 选择相同路径 → 重新聚焦 → listbox 打开),为相同值的非空选择递增 seq 后翻转为 关闭。— 失败场景:用户输入绝对路径,在查询仍在 debounce/在途时(该窗口包含 daemon 延迟)点击"浏览",在系统选择器中确认了相同路径,然后点回输入框:列表在零次编辑时意外弹出;若恰好只有一条建议,单条建议的 Tab 接受路径还会改写已输入的路径。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下:

Autofix review response — PR #8844 (round 5)

All four inline suggestions were verified against the head commit and addressed in one commit (fix(web-shell): clear blur timer on focus and unmount in AddWorkspaceDialog (#8844)). No conflicts with main; no merge performed.

Feedback points and dispositions

  1. [Suggestion] Blur timer never cancelled when focus returns to the input (no onFocus)Addressed.
    Verified the defect: blur → refocus within the 100 ms window lets the pending timer fire on a focused input, visibly closing an open list and leaving suppressNextFetchOpenRef set so the next edit's lookup does not open (only the second keystroke does). Fix: added an onFocus handler on the path input that clears blurTimeoutRef, completing the timer lifecycle this PR already owns (schedule on blur, cancel on re-blur, cancel in pickDirectory). Added a regression test that opens the list, blurs, refocuses inside the window, crosses the timer deadline, and asserts the list stays open and the first subsequent edit opens suggestions. Mutant-verified: removing the onFocus handler fails this test.

  2. [Suggestion] No unmount cleanup for the tracked blur timerAddressed.
    Closing the dialog within 100 ms of a blur left the timer to fire on an unmounted component. Added a mount-effect cleanup that clears blurTimeoutRef, matching the sibling delayed-close pattern in ArtifactPanel.tsx (sideTaskMenuCloseTimerRef) and the dialog's other unmount cleanups. No dedicated test: with the fix there is no observable behavior difference to assert (React 19 already makes the post-unmount write a silent no-op).

  3. [Suggestion] No test opens the suggestion list before blur, so closeList() in the blur timer is a surviving mutantAddressed.
    Added the suggested regression test: open the list via a settled lookup, blur the input, advance 100 ms, and assert the listbox is gone. Mutant-verified: deleting only closeList() from the timer body now fails the suite (previously all tests blurred while the fetch was still pending, so the line was unpinned).

  4. [Suggestion] Same-value pick no longer invalidates an in-flight suggestion lookupAddressed.
    Verified the race: a lookup debounced/in flight when Browse is clicked survives the seq check after a same-value pick, and with the input refocused the stale result pops the list open with zero edits. Fix: bump suggestSeqRef for a truthy same-value pick, restoring the pre-diff invariant that every truthy pick discards in-flight lookups (the cancelled/falsy branch keeps its prior behavior). Added a regression test: type → Browse inside the debounce window → lookup left in flight → same-value pick → refocus → stale lookup resolves → listbox must stay closed, and the first real edit opens it. Mutant-verified: removing the seq bump fails this test.

Changes

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx (+17): onFocus cancellation of the pending blur timer; unmount cleanup for the timer; seq invalidation for truthy same-value picks.
  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx (+109): three regression tests pinning each behavior above.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • Vitest packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx (touched) — 31 passed (28 prior + 3 new)
  • Vitest full packages/web-shell suite (touched package) — 177 files, 3078 tests passed
  • Mutant checks (temporary reverts, then restored): removing onFocus / removing the same-value seq bump / removing closeList() from the blur timer each fails exactly its new regression test
  • Not run: integration tests (behavior is fully exercised by web-shell unit tests, not the bundled CLI); npm run generate:settings-schema (no settings source changed)
中文说明

Autofix 审查响应 — PR #8844(第 5 轮)

四条行内建议均已在 head commit 上核实,并在一次提交中处理完毕(fix(web-shell): clear blur timer on focus and unmount in AddWorkspaceDialog (#8844))。与 main 无冲突,未执行合并。

反馈点与处理结果

  1. [建议] blur 定时器在焦点回到输入框时从未被取消(没有 onFocus已处理。
    已核实该缺陷:在 100 ms 窗口内先失焦再重新聚焦,挂起的定时器会在已聚焦的输入框上触发,可见地关闭已打开的列表,并残留 suppressNextFetchOpenRef 标志,导致下一次编辑的查询不打开列表(要到第二次按键才打开)。修复:在路径输入框上添加 onFocus 处理器清除 blurTimeoutRef,补全本 PR 已接管的定时器生命周期(blur 时调度、重复 blur 时取消、pickDirectory 中取消)。新增回归测试:打开列表 → 失焦 → 窗口内重新聚焦 → 越过定时器截止时间 → 断言列表保持打开,且随后第一次编辑即可打开建议。已做变异验证:移除 onFocus 处理器会导致该测试失败。

  2. [建议] 受跟踪的 blur 定时器没有卸载清理已处理。
    在失焦后 100 ms 内关闭对话框,挂起的定时器会在已卸载的组件上触发。新增挂载 effect 的清理函数清除 blurTimeoutRef,与兄弟模式 ArtifactPanel.tsxsideTaskMenuCloseTimerRef)及本对话框其他卸载清理保持一致。未专门加测试:修复后没有可断言的可观测行为差异(React 19 下卸载后的写入本来就是静默无操作)。

  3. [建议] 没有测试在失焦前先打开建议列表,blur 定时器中的 closeList() 是存活变异体已处理。
    按建议新增回归测试:先通过已完成的查询打开列表,再让输入框失焦,前进 100 ms,断言 listbox 消失。已做变异验证:只删除定时器中的 closeList() 一行,现在会导致测试失败(此前所有测试都在查询尚未返回时失焦,该行一直未被钉住)。

  4. [建议] 选择相同路径时不再使在途建议查询失效已处理。
    已核实该竞态:点击"浏览"时已处于 debounce/在途的查询,在相同值选择后仍能通过 seq 检查;若输入框已重新聚焦,过期结果会在零次编辑时弹出列表。修复:为非空的相同值选择递增 suggestSeqRef,恢复修改前"任何非空选择都丢弃在途查询"的不变量(取消/空值分支保持原有行为)。新增回归测试:输入 → 在 debounce 窗口内点击浏览 → 查询保持在途 → 选择相同路径 → 重新聚焦 → 过期查询返回 → listbox 必须保持关闭,且第一次真正的编辑可以打开列表。已做变异验证:移除 seq 递增会导致该测试失败。

变更内容

  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.tsx(+17):onFocus 取消挂起的 blur 定时器;定时器卸载清理;非空相同值选择的 seq 失效。
  • packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx(+109):三个回归测试,分别钉住上述行为。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • Vitest packages/web-shell/client/components/dialogs/AddWorkspaceDialog.test.tsx(触及文件)— 31 个通过(原有 28 个 + 新增 3 个)
  • Vitest packages/web-shell 全包测试(触及包)— 177 个文件、3078 个测试全部通过
  • 变异检查(临时回退后已恢复):移除 onFocus / 移除相同值 seq 递增 / 移除 blur 定时器中的 closeList(),各自恰好使对应的新回归测试失败
  • 未运行:集成测试(相关行为完全由 web-shell 单元测试覆盖,不经由打包 CLI);npm run generate:settings-schema(未改动任何 settings 源)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not explored to full depth (tool budget reached): Context: PR #8844 (web-shell AddWorkspaceDialog focus/blu...: none — all checks above were completed within budget.; Context: PR #8844 (web-shell AddWorkspaceDialog focus/blu...: none — I finished within the tool budget with no checks left unfinished.; Context: PR #8844 (web-shell AddWorkspaceDialog) closes w...: none — I completed all checks I opened; no check was left unfinished at the tool ceiling.; Context: PR #8844 (web-shell AddWorkspaceDialog) closes w...: none — all checks I started completed within budget..

中文说明

未探索到全部深度(达到工具调用预算):Context: PR #8844 (web-shell AddWorkspaceDialog focus/blu...:none — all checks above were completed within budget.;Context: PR #8844 (web-shell AddWorkspaceDialog focus/blu...:none — I finished within the tool budget with no checks left unfinished.;Context: PR #8844 (web-shell AddWorkspaceDialog) closes w...:none — I completed all checks I opened; no check was left unfinished at the tool ceiling.;Context: PR #8844 (web-shell AddWorkspaceDialog) closes w...:none — all checks I started completed within budget.

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

Comment on lines 327 to 329
blurTimeoutRef.current = setTimeout(() => {
blurTimeoutRef.current = undefined;
suppressNextFetchOpenRef.current = true;

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] R6-1: When the 100 ms blur-dismiss timer fires (user stays blurred >100 ms), it arms suppressNextFetchOpenRef and nothing clears it until the next path change — which consumes it (openOnResult = !flag), so the user's first edit after returning to the field never opens the suggestion list; only the second keystroke does. This PR's App.tsx change makes it live: pre-PR the inline onSuggest arrow gave the suggest effect fresh identity on every App render, so churn re-runs consumed the stale flag; the stable memoized workspaceActions.suggestWorkspacePaths reference removes that incidental consumption, making the suppression deterministic. — Failure scenario: open Add Workspace → type /home/me/co (suggestions appear) → click the Persist switch → after 100 ms the timer fires (list closes, flag armed) → click back into the input and type one character → the lookup resolves with the input focused, but openOnResult || listOpenRef.current is false → the listbox stays closed on keystroke 1 and opens only on keystroke 2. Probe-reproduced at the reviewed commit in both "typed prefix then blurred" and "blur from empty then type" variants (the fetch happens, only the open is suppressed); the fix below flips the probe with all 31 existing tests still green. Same first-edit-suppressed family as R2-1/R3-1, on the timer-fired path the picker fixes don't reach.

Suggested change
blurTimeoutRef.current = setTimeout(() => {
blurTimeoutRef.current = undefined;
suppressNextFetchOpenRef.current = true;
blurTimeoutRef.current = setTimeout(() => {
blurTimeoutRef.current = undefined;
++suggestSeqRef.current;

Invalidating the dismissed lookup via the sequence counter (instead of poisoning the next edit) also subsumes R6-2: an in-flight lookup then fails the seq check on resolve, while the first edit opens normally. The existing "keeps suggestions closed when a lookup finishes after blur" test still passes under it. Add a regression test: blur → advance 100 ms → focus → type → expect the listbox open on the first edit.

中文说明

当 100 ms 的 blur 关闭定时器真正触发时(用户失焦超过 100 ms),它会置位 suppressNextFetchOpenRef,且没有任何逻辑在下一次路径变化前清除它——而下一次路径变化恰恰会消费该标志(openOnResult = !flag),因此用户回到输入框后的第一次编辑永远不会打开建议列表,要到第二次按键才打开。本 PR 在 App.tsx 中的改动使该缺陷确定性地生效:修改前内联的 onSuggest 箭头函数在每次 App 渲染时都会产生新标识,churn 导致的 effect 重跑会顺带消费过期标志;改为稳定的记忆化 workspaceActions.suggestWorkspacePaths 引用后,这一意外消费被移除,抑制行为变为确定性发生。— 失败场景:打开"添加工作区" → 输入 /home/me/co(建议出现)→ 点击 Persist 开关 → 100 ms 后定时器触发(列表关闭、标志置位)→ 重新点击输入框并输入一个字符 → 查询在输入框聚焦时返回,但 openOnResult || listOpenRef.current 为 false → 第一次按键时列表保持关闭,第二次按键才打开。已在评审提交上通过探针复现("先输入再失焦"与"空输入失焦后再输入"两种变体:查询会发出,只有打开被抑制);应用下方修复后探针翻转通过,且全部 31 个现有测试仍然通过。这与 R2-1/R3-1 属于同一类"首次编辑被抑制"缺陷,只是发生在选择器相关修复覆盖不到的"定时器已触发"路径上。

通过序列计数器使被关闭的查询失效(而不是毒化下一次编辑)同时也覆盖了 R6-2:未决查询在返回时会因 seq 检查失败而被丢弃,而第一次编辑可以正常打开列表。现有的"keeps suggestions closed when a lookup finishes after blur"测试在该修复下仍然通过。请补充回归测试:blur → 推进 100 ms → focus → 输入 → 断言第一次编辑时列表打开。

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

Comment on lines 327 to 329
blurTimeoutRef.current = setTimeout(() => {
blurTimeoutRef.current = undefined;
suppressNextFetchOpenRef.current = true;

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] R6-2: The blur-dismiss timer arms the suppress flag but never bumps suggestSeqRef, so a lookup in flight when the user blurs survives invalidation. Once the timer has fired, refocusing is a no-op (onFocus only cancels a pending timer), and when the stale lookup resolves it passes the seq check and the new focus gate (the input is focused again) with its pre-blur captured openOnResult=truepopping the list open on a bare refocus with zero edits. That violates the invariant this PR's own same-value race test documents ("so a bare refocus cannot pop the list open"), implemented for the picker-dismiss path but omitted on the blur-dismiss path. — Failure scenario: type /home/me/co → wait past the 150 ms debounce so the daemon lookup is in flight (routine for a remote daemon) → click another field → the 100 ms timer fires (closeList, flag armed, no seq bump) → click back into the input before the lookup resolves → the lookup resolves → the list pops open with zero edits; with the list unexpectedly open, handleInputKeyDown then treats subsequent keys as listbox navigation (Tab with exactly one suggestion is accepted immediately). Probe-reproduced at the reviewed commit: the listbox rendered with both options on a bare refocus; adding ++suggestSeqRef.current; in the timer callback flips the probe; no existing test pins this window ("keeps suggestions closed when a lookup finishes after blur" never refocuses; "cancels the pending blur dismiss…" refocuses before the timer fires). Distinct from R6-1 (which suppresses the next edit; this one opens the list with no edit), but R6-1's fix — seq bump instead of arming the flag — subsumes this finding, so no separate suggestion block here: one defect family, one fix.

中文说明

blur 关闭定时器会置位抑制标志,但从不递增 suggestSeqRef,因此用户失焦时仍在飞行中的查询不会被作废。定时器触发之后,重新聚焦是空操作(onFocus 只取消未决的定时器),当这个过期查询返回时,它能通过 seq 检查和新的焦点门控(此时输入框已重新聚焦),并凭借 blur 之前捕获的 openOnResult=true 调用 setListOpen(true) —— 在没有任何编辑的情况下,仅凭重新聚焦就弹出列表。这违反了本 PR 自己的相同值竞争测试所声明的不变量("so a bare refocus cannot pop the list open"):该不变量在选择器关闭路径上有实现,在 blur 关闭路径上却被遗漏。— 失败场景:输入 /home/me/co → 等待超过 150 ms 去抖使守护进程查询进入飞行状态(对远程守护进程很常见)→ 点击其他字段 → 100 ms 定时器触发(closeList、标志置位、未递增 seq)→ 在查询返回前重新点击输入框 → 查询返回 → 列表在零编辑时弹出;列表意外打开后,handleInputKeyDown 会把后续按键当作列表导航处理(恰好只有一条建议时 Tab 会立即接受)。已在评审提交上通过探针复现:仅重新聚焦即渲染出包含两个选项的列表框;在定时器回调中加入 ++suggestSeqRef.current; 即可翻转探针;现有测试均未钉住该窗口("keeps suggestions closed when a lookup finishes after blur" 从不重新聚焦;"cancels the pending blur dismiss…" 在定时器触发前就重新聚焦)。与 R6-1 不同(那个抑制下一次编辑;这个在无编辑时打开列表),但 R6-1 的修复——用 seq 递增替代置位标志——同样覆盖本发现,因此此处不再给出独立的 suggestion 块:同一缺陷家族,一个修复即可。

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

Comment on lines +177 to +178
closeList();
suppressNextFetchOpenRef.current = true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R6-3: No test pins that the suggestion list closes when Browse is clicked — deleting this closeList() keeps all 31 tests green (mutation run at the reviewed commit; comparator aliveness verified: a sanity mutation in the resolve handler fails 14 of the same 31 tests, so the green mutant run is meaningful, not a dead comparator). — Concrete cost: with the list open (user typed /home/me/co, suggestions visible), a future refactor dropping this call leaves the listbox rendered under the disabled input while the native picker is up, and still open after a cancelled or same-value pick (those branches don't clear suggestions/listOpen) — a git bisect-able regression of this PR's stated "close on picker open" behaviour shipping green. All existing picker tests either start with the list closed or assert nothing between the Browse click and the next edit. Suggested fix: in opens suggestions on the first edit after picking the typed path (the one test whose list is open when Browse is clicked), add expect(listbox()).toBeNull(); immediately after the act(() => { browseButton().click(); }) block.

中文说明

没有测试钉住"点击'浏览'时建议列表会关闭"这一行为——删除这里的 closeList()全部 31 个测试仍然通过(已在评审提交上运行变异验证;比较器活性也已确认:在结果处理器中注入一个健全性变异会使同样 31 个测试中的 14 个失败,因此该绿色变异结果是有效的,而非死比较器)。— 具体代价:当列表处于打开状态(用户已输入 /home/me/co,建议可见)时,未来某次重构若删掉该调用,系统选择器弹出期间列表框会继续渲染在被禁用的输入框下方,并且在取消选择或选择相同路径后仍然保持打开(这些分支不会清除 suggestions/listOpen)——本 PR 声明的"打开选择器时关闭列表"行为发生可被 git bisect 定位的回归,却能一路绿灯地合入。现有的选择器测试要么从列表关闭状态开始,要么在"浏览"点击与下一次编辑之间不做任何断言。建议修复:在 opens suggestions on the first edit after picking the typed path(唯一一个点击"浏览"时列表处于打开状态的测试)中,紧跟 act(() => { browseButton().click(); }) 代码块之后加上 expect(listbox()).toBeNull();

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

Comment on lines +316 to +321
onFocus={() => {
if (blurTimeoutRef.current !== undefined) {
clearTimeout(blurTimeoutRef.current);
blurTimeoutRef.current = undefined;
}
}}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R6-4: The blur-timer cancel block is hand-copied four times in this one component, all introduced by this PR: pickDirectory (lines 173-176), this onFocus handler, onBlur's clear-before-rearm (324-326), and the unmount cleanup effect (88-90) — and one copy has already drifted: the unmount effect clears the timeout without resetting blurTimeoutRef.current = undefined. — Concrete cost: the next semantic change to "cancel the pending dismiss" (e.g. also clearing suppressNextFetchOpenRef on cancel) must locate and update all four copies by hand; missing one reintroduces the exact timer-race class this round fixed — the class that took five review rounds to close. Suggested fix (spans the declaration and three call sites, so no one-click block):

const cancelBlurDismiss = useCallback(() => {
  if (blurTimeoutRef.current !== undefined) {
    clearTimeout(blurTimeoutRef.current);
    blurTimeoutRef.current = undefined;
  }
}, []);

called from the unmount effect, pickDirectory, and onFocus.

中文说明

blur 定时器的取消代码块在这一个组件中被手写了四份,且全部由本 PR 引入:pickDirectory(第 173-176 行)、这个 onFocus 处理器、onBlur 中先清除再重置的部分(324-326),以及卸载清理 effect(88-90)——其中一份已经出现漂移:卸载 effect 清除了定时器却没有把 blurTimeoutRef.current 重置为 undefined。— 具体代价:下一次对"取消待执行的关闭"的语义修改(例如取消时同时清除 suppressNextFetchOpenRef)必须手工找到并更新全部四处拷贝;漏掉任何一处都会重新引入本轮刚修复的定时器竞争——这类缺陷花了五轮评审才收敛。建议修复(跨声明与三个调用点,因此不使用一键 suggestion 块):提取如上所示的 cancelBlurDismiss 辅助函数,并在卸载 effect、pickDirectoryonFocus 中调用。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 4/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 4/100 轮)。改动内容与我反驳保留之处如下:

Autofix address-review summary — PR #8844

Commit: 797a75f8c1fix(web-shell): invalidate blurred lookups via sequence counter in AddWorkspaceDialog (#8844)

Feedback points and dispositions

All four findings were verified against the reviewed code and addressed.

R6-1 [Critical] (rc:3756750996) — fixed. Confirmed: when the 100 ms blur-dismiss timer fired, it armed suppressNextFetchOpenRef, and the next path change consumed the flag (openOnResult = !flag), so the first edit after refocusing never opened the suggestion list — only the second keystroke did. With the stable memoized onSuggest reference the dialog now receives, no incidental effect re-run consumes the stale flag, making the suppression deterministic. Fix: the timer callback no longer arms the suppress flag; it invalidates in-flight lookups by bumping suggestSeqRef instead, so the next edit starts with a clean flag and opens normally. Added regression test opens suggestions on the first edit after the blur dismiss fired (type → suggestions open → blur past the 100 ms window → refocus → one edit → listbox must be open). Verified red against the pre-fix component, green with the fix.

R6-2 [Critical] (rc:3756751014) — fixed (subsumed by the R6-1 fix, as the finding predicted). Confirmed: the timer never bumped suggestSeqRef, so a lookup in flight when the user blurred survived invalidation; after a bare refocus it passed the seq check and the focus gate with its pre-blur openOnResult=true and popped the list open with zero edits — violating the "a bare refocus cannot pop the list open" invariant the PR's same-value race test documents for the picker path. The same timer change (seq bump instead of flag) discards the stale lookup on resolve. Added regression test keeps suggestions closed when a pre-blur lookup resolves after refocus (lookup in flight → blur past the window → refocus → resolve → listbox must stay closed). Verified red against the pre-fix component, green with the fix.

R6-3 [Suggestion] (rc:3756751017) — addressed. Added expect(listbox()).toBeNull() immediately after the Browse click in opens suggestions on the first edit after picking the typed path — the one test whose list is open when Browse is clicked — pinning the "close on picker open" behaviour so a future refactor dropping that closeList() fails CI instead of shipping green.

R6-4 [Suggestion] (rc:3756751030) — addressed. Extracted a single cancelBlurDismiss helper and routed all four copies through it: the unmount cleanup effect, pickDirectory, onFocus, and the clear-before-rearm in onBlur. This also fixes the drift the finding flagged — the unmount copy now resets blurTimeoutRef.current to undefined like every other cancel site. Net diff shrinks the component (4 hand-copied blocks → 1 helper) and puts the "cancel the pending dismiss" semantics in one place.

Also refreshed one test comment that referenced the old timer mechanism ("re-set the suppress flag") and the pickDirectory comment describing the cancel, so comments match the new semantics.

The review-level CHANGES_REQUESTED entry carried only the reviewer's budget-accounting context lines ("all checks completed within budget") — no additional actionable content beyond the four inline findings above.

Conflict notes

--conflict false: no merge of origin/main was needed and none was performed.

Verification

Commands actually run this round (repo root unless noted):

  • Focused Vitest, pre-fix component (red proof): cd packages/web-shell && npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx2 failed | 31 passed: exactly the two new regression tests fail on the pre-fix code
  • Focused Vitest, with fix: cd packages/web-shell && npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx33 passed (33)
  • Full touched-package suite: cd packages/web-shell && npx vitest run177 test files, 3080 tests passed (the first attempt failed wholesale on Failed to resolve import "@qwen-code/webui/daemon-react-sdk" — unbuilt workspace dist, unrelated to this change; cleared by the build below, after which everything is green)
  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx prettier --check on the two changed files — passed
  • Pre-commit hook (lint-staged + prettier on staged files) — passed

Integration tests after npm run bundle were not run: the touched behaviour (dialog focus/blur suggestion gating) is fully exercised by the web-shell unit tests above and is not only reachable through the bundled CLI or integration harness. No settings source changed, so npm run generate:settings-schema was not needed.

中文说明

Autofix 评审处理总结 — PR #8844

提交:797a75f8c1fix(web-shell): invalidate blurred lookups via sequence counter in AddWorkspaceDialog (#8844)

反馈点及处理结果

四个发现均已对照被评审的代码核实,并全部处理

R6-1 [Critical](rc:3756750996)— 已修复。 确认属实:当 100 ms 的 blur 关闭定时器真正触发时,它会置位 suppressNextFetchOpenRef,而下一次路径变化会消费该标志(openOnResult = !flag),因此用户重新聚焦后的第一次编辑不会打开建议列表——要到第二次按键才打开。在对话框现在收到稳定的记忆化 onSuggest 引用之后,不再有 effect 意外重跑去消费这个过期标志,抑制行为变为确定性发生。修复:定时器回调不再置位抑制标志,而是通过递增 suggestSeqRef 使在飞行中的查询失效,这样下一次编辑以干净的标志开始、可以正常打开列表。新增回归测试 opens suggestions on the first edit after the blur dismiss fired(输入 → 建议出现 → 失焦超过 100 ms 窗口 → 重新聚焦 → 编辑一次 → 列表必须打开)。已验证该测试在修复前的组件上失败(红)、修复后通过(绿)。

R6-2 [Critical](rc:3756751014)— 已修复(被 R6-1 的修复一并覆盖,与该发现的预判一致)。 确认属实:定时器从不递增 suggestSeqRef,因此用户失焦时仍在飞行中的查询不会被作废;仅重新聚焦后,该过期查询会通过 seq 检查和焦点门控,并凭借 blur 之前捕获的 openOnResult=true 弹出列表——在零编辑的情况下打开列表,违反了本 PR 相同值竞争测试为选择器路径所记录的"仅重新聚焦不得弹出列表"不变量。同一个定时器改动(用 seq 递增替代置位标志)使过期查询在返回时被丢弃。新增回归测试 keeps suggestions closed when a pre-blur lookup resolves after refocus(查询在飞行中 → 失焦超过窗口 → 重新聚焦 → 让查询返回 → 列表必须保持关闭)。已验证该测试在修复前的组件上失败(红)、修复后通过(绿)。

R6-3 [Suggestion](rc:3756751017)— 已处理。opens suggestions on the first edit after picking the typed path(唯一一个点击"浏览"时列表处于打开状态的测试)中,紧跟"浏览"点击之后加上 expect(listbox()).toBeNull(),钉住"打开选择器时关闭列表"这一行为,使未来某次删掉该 closeList() 的重构会在 CI 中失败,而不是一路绿灯地合入。

R6-4 [Suggestion](rc:3756751030)— 已处理。 抽取了单一的 cancelBlurDismiss 辅助函数,并把全部四处拷贝改为调用它:卸载清理 effect、pickDirectoryonFocus,以及 onBlur 中先清除再重置的部分。这同时修复了该发现指出的漂移——卸载处的拷贝现在和其他所有取消点一样,把 blurTimeoutRef.current 重置为 undefined。净效果是组件代码变少(4 段手写拷贝 → 1 个辅助函数),且"取消待执行的关闭"语义集中在一处。

同时刷新了一处引用旧定时器机制的测试注释("re-set the suppress flag")以及 pickDirectory 中描述取消逻辑的注释,使注释与新语义一致。

评审层面的 CHANGES_REQUESTED 条目只包含评审者的工具预算核算上下文("all checks completed above were completed within budget")——除上述四条行内发现外没有其他可操作内容。

冲突说明

--conflict false:无需合并 origin/main,也未执行任何合并。

验证

本轮实际执行的命令(未注明时均在仓库根目录):

  • 聚焦 Vitest(修复前组件,红色证明):cd packages/web-shell && npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx2 failed | 31 passed:恰好是两个新回归测试在修复前代码上失败
  • 聚焦 Vitest(应用修复后):cd packages/web-shell && npx vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx33 passed (33)
  • 触及包的全量测试:cd packages/web-shell && npx vitest run177 个测试文件、3080 个测试全部通过(首次运行曾因 Failed to resolve import "@qwen-code/webui/daemon-react-sdk" 整体失败——是工作区依赖未构建的 dist 所致,与本次改动无关;执行下方 build 后问题消除,全部通过)
  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 对两个改动文件执行 npx prettier --check — 通过
  • pre-commit 钩子(lint-staged + prettier,作用于暂存文件)— 通过

未运行 npm run bundle 之后的集成测试:本次触及的行为(对话框焦点/失焦对建议列表的门控)已完全由上述 web-shell 单元测试覆盖,并非只能通过打包后的 CLI 或集成测试框架才能触达。未改动任何 settings 源,因此无需执行 npm run generate:settings-schema

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here.

Not explored to full depth (tool budget reached): Context: PR #8844 (review round 7) makes the web-shell Ad...: none — did not run the web-shell unit test suite (not needed for the perf judgment; no perf-specific harness exists). Should I mention this? The brief says to d….

中文说明

已审查。 建议见行内评论。 1 条建议级发现无法锚定到改动行,已丢弃;此处无需进一步处理。

未探索到全部深度(达到工具调用预算):Context: PR #8844 (review round 7) makes the web-shell Ad...:none — did not run the web-shell unit test suite (not needed for the perf judgment; no perf-specific harness exists). Should I mention this? The brief says to d…

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

Comment on lines +398 to +399
// Cross the blur timer's deadline: a still-pending timer would close
// the list and leave a stale suppress flag for the next edit.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-2: New test comments contradict the shipped blur-timer mechanism. The timer body this PR ships is ++suggestSeqRef.current; closeList(); and never touches suppressNextFetchOpenRef (the handler's own comment says: "Invalidate in-flight lookups via the sequence counter rather than suppressing the next fetch"). But this comment class describes the pre-fix behaviour — a pending timer that "would … leave a stale suppress flag for the next edit" (here and at lines 432-433) / "would have set the suppress flag by now" — and, in the failed-picker test, "Cross the blur timer's deadline before the first edit below" (~line 773) plus "settling before the input's 100 ms blur timer" (~line 762) assert a pending blur timer that does not exist there: pickDirectory calls blur() then synchronously cancelBlurDismiss() before await onPick(), so that 100 ms advance drains nothing blur-related. Probe-verified at the reviewed commit: after an instantly rejected picker, a lookup flown through the 100 ms window is applied (no timer fired); deleting cancelBlurDismiss() flips the probe. — Failure scenario: a maintainer debugging this file's three-ref interplay (suppress flag, sequence counter, blur timer) reads these comments and either chases suppress-flag state the timer never touches, or concludes the failed-picker path leaves a live blur timer that must be crossed — steering a refactor toward re-arming the suppress flag and reintroducing the R6-1-class first-edit leak.

Suggested fix: reword to the shipped mechanism, e.g. "a still-pending timer would close the list and invalidate the next lookup via the sequence counter", "an uncancelled timer would have bumped the sequence counter by now", and for the failed-picker test "No blur timer is pending here — pickDirectory cancels it synchronously, so this advance only drains the debounce window before the first edit below."

中文说明

新增的测试注释与实际交付的 blur 定时器机制相矛盾。本 PR 交付的定时器逻辑是 ++suggestSeqRef.current; closeList();,从不写 suppressNextFetchOpenRef(处理器自己的注释写明:"通过序列计数器使在飞行中的查询失效,而不是抑制下一次查询")。但这类注释描述的是修复前的行为——一个仍未决的定时器"会给下一次编辑留下一个过期的 suppress 标志"(此处及第 432-433 行)/"此刻本应已置位 suppress 标志";此外在"选择器失败"测试中,"在下方第一次编辑前越过 blur 定时器的截止时间"(约第 773 行)与"在输入框 100 ms blur 定时器之前结束"(约第 762 行)断言了一个实际不存在的未决 blur 定时器:pickDirectoryblur() 之后、await onPick() 之前就同步调用了 cancelBlurDismiss(),因此那 100 ms 的推进不会排空任何 blur 相关逻辑。已在评审提交上通过探针验证:立即 reject 的选择器之后,飞过 100 ms 窗口的查询会被应用(定时器未触发);删除 cancelBlurDismiss() 可翻转探针。— 失败场景:维护者调试本文件中三个 ref 的交互(suppress 标志、序列计数器、blur 定时器)时读到这些注释,要么去追查定时器从不写入的 suppress 标志状态,要么误以为"选择器失败"路径留下了一个必须越过的存活 blur 定时器——从而引导重构重新置位 suppress 标志,重新引入 R6-1 类的"首次编辑被抑制"泄漏。

建议修复:按实际机制改写注释,例如"仍未决的定时器会关闭列表并通过序列计数器使下一次查询失效"、"未被取消的定时器此刻本应已递增序列计数器",以及"选择器失败"测试中的"此处没有未决的 blur 定时器——pickDirectory 已同步取消它,这次推进只是为下方第一次编辑前排空去抖窗口"。

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

Comment on lines +432 to +433
// Cross the first timer's original deadline: an uncancelled timer
// would have set the suppress flag by now.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-2: New test comments contradict the shipped blur-timer mechanism. The timer body this PR ships is ++suggestSeqRef.current; closeList(); and never touches suppressNextFetchOpenRef (the handler's own comment says: "Invalidate in-flight lookups via the sequence counter rather than suppressing the next fetch"). But this comment class describes the pre-fix behaviour — a pending timer that "would … leave a stale suppress flag for the next edit" (here and at lines 432-433) / "would have set the suppress flag by now" — and, in the failed-picker test, "Cross the blur timer's deadline before the first edit below" (~line 773) plus "settling before the input's 100 ms blur timer" (~line 762) assert a pending blur timer that does not exist there: pickDirectory calls blur() then synchronously cancelBlurDismiss() before await onPick(), so that 100 ms advance drains nothing blur-related. Probe-verified at the reviewed commit: after an instantly rejected picker, a lookup flown through the 100 ms window is applied (no timer fired); deleting cancelBlurDismiss() flips the probe. — Failure scenario: a maintainer debugging this file's three-ref interplay (suppress flag, sequence counter, blur timer) reads these comments and either chases suppress-flag state the timer never touches, or concludes the failed-picker path leaves a live blur timer that must be crossed — steering a refactor toward re-arming the suppress flag and reintroducing the R6-1-class first-edit leak.

Suggested fix: reword to the shipped mechanism, e.g. "a still-pending timer would close the list and invalidate the next lookup via the sequence counter", "an uncancelled timer would have bumped the sequence counter by now", and for the failed-picker test "No blur timer is pending here — pickDirectory cancels it synchronously, so this advance only drains the debounce window before the first edit below."

中文说明

新增的测试注释与实际交付的 blur 定时器机制相矛盾。本 PR 交付的定时器逻辑是 ++suggestSeqRef.current; closeList();,从不写 suppressNextFetchOpenRef(处理器自己的注释写明:"通过序列计数器使在飞行中的查询失效,而不是抑制下一次查询")。但这类注释描述的是修复前的行为——一个仍未决的定时器"会给下一次编辑留下一个过期的 suppress 标志"(此处及第 432-433 行)/"此刻本应已置位 suppress 标志";此外在"选择器失败"测试中,"在下方第一次编辑前越过 blur 定时器的截止时间"(约第 773 行)与"在输入框 100 ms blur 定时器之前结束"(约第 762 行)断言了一个实际不存在的未决 blur 定时器:pickDirectoryblur() 之后、await onPick() 之前就同步调用了 cancelBlurDismiss(),因此那 100 ms 的推进不会排空任何 blur 相关逻辑。已在评审提交上通过探针验证:立即 reject 的选择器之后,飞过 100 ms 窗口的查询会被应用(定时器未触发);删除 cancelBlurDismiss() 可翻转探针。— 失败场景:维护者调试本文件中三个 ref 的交互(suppress 标志、序列计数器、blur 定时器)时读到这些注释,要么去追查定时器从不写入的 suppress 标志状态,要么误以为"选择器失败"路径留下了一个必须越过的存活 blur 定时器——从而引导重构重新置位 suppress 标志,重新引入 R6-1 类的"首次编辑被抑制"泄漏。

建议修复:按实际机制改写注释,例如"仍未决的定时器会关闭列表并通过序列计数器使下一次查询失效"、"未被取消的定时器此刻本应已递增序列计数器",以及"选择器失败"测试中的"此处没有未决的 blur 定时器——pickDirectory 已同步取消它,这次推进只是为下方第一次编辑前排空去抖窗口"。

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

'Unable to open the system folder picker',
);

// Cross the blur timer's deadline before the first edit below.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-2: New test comments contradict the shipped blur-timer mechanism. The timer body this PR ships is ++suggestSeqRef.current; closeList(); and never touches suppressNextFetchOpenRef (the handler's own comment says: "Invalidate in-flight lookups via the sequence counter rather than suppressing the next fetch"). But this comment class describes the pre-fix behaviour — a pending timer that "would … leave a stale suppress flag for the next edit" (here and at lines 432-433) / "would have set the suppress flag by now" — and, in the failed-picker test, "Cross the blur timer's deadline before the first edit below" (~line 773) plus "settling before the input's 100 ms blur timer" (~line 762) assert a pending blur timer that does not exist there: pickDirectory calls blur() then synchronously cancelBlurDismiss() before await onPick(), so that 100 ms advance drains nothing blur-related. Probe-verified at the reviewed commit: after an instantly rejected picker, a lookup flown through the 100 ms window is applied (no timer fired); deleting cancelBlurDismiss() flips the probe. — Failure scenario: a maintainer debugging this file's three-ref interplay (suppress flag, sequence counter, blur timer) reads these comments and either chases suppress-flag state the timer never touches, or concludes the failed-picker path leaves a live blur timer that must be crossed — steering a refactor toward re-arming the suppress flag and reintroducing the R6-1-class first-edit leak.

Suggested fix: reword to the shipped mechanism, e.g. "a still-pending timer would close the list and invalidate the next lookup via the sequence counter", "an uncancelled timer would have bumped the sequence counter by now", and for the failed-picker test "No blur timer is pending here — pickDirectory cancels it synchronously, so this advance only drains the debounce window before the first edit below."

中文说明

新增的测试注释与实际交付的 blur 定时器机制相矛盾。本 PR 交付的定时器逻辑是 ++suggestSeqRef.current; closeList();,从不写 suppressNextFetchOpenRef(处理器自己的注释写明:"通过序列计数器使在飞行中的查询失效,而不是抑制下一次查询")。但这类注释描述的是修复前的行为——一个仍未决的定时器"会给下一次编辑留下一个过期的 suppress 标志"(此处及第 432-433 行)/"此刻本应已置位 suppress 标志";此外在"选择器失败"测试中,"在下方第一次编辑前越过 blur 定时器的截止时间"(约第 773 行)与"在输入框 100 ms blur 定时器之前结束"(约第 762 行)断言了一个实际不存在的未决 blur 定时器:pickDirectoryblur() 之后、await onPick() 之前就同步调用了 cancelBlurDismiss(),因此那 100 ms 的推进不会排空任何 blur 相关逻辑。已在评审提交上通过探针验证:立即 reject 的选择器之后,飞过 100 ms 窗口的查询会被应用(定时器未触发);删除 cancelBlurDismiss() 可翻转探针。— 失败场景:维护者调试本文件中三个 ref 的交互(suppress 标志、序列计数器、blur 定时器)时读到这些注释,要么去追查定时器从不写入的 suppress 标志状态,要么误以为"选择器失败"路径留下了一个必须越过的存活 blur 定时器——从而引导重构重新置位 suppress 标志,重新引入 R6-1 类的"首次编辑被抑制"泄漏。

建议修复:按实际机制改写注释,例如"仍未决的定时器会关闭列表并通过序列计数器使下一次查询失效"、"未被取消的定时器此刻本应已递增序列计数器",以及"选择器失败"测试中的"此处没有未决的 blur 定时器——pickDirectory 已同步取消它,这次推进只是为下方第一次编辑前排空去抖窗口"。

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

Comment on lines 76 to 78
// Set when a suggestion is accepted or the list is dismissed, so the
// path-change effect knows whether to reopen the list for that update.
const suppressNextFetchOpenRef = useRef(false);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-3: The suppressNextFetchOpenRef declaration comment still names blur dismissal as a setter ("Set when a suggestion is accepted or the list is dismissed"), but this diff removed that setter — the blur timer now bumps suggestSeqRef instead. The only remaining = true write is pickDirectory's Browse flow, and acceptSuggestion clears the flag rather than setting it. The comment now contradicts the blur handler's comment twenty lines below. — Failure scenario: a maintainer adding a future dismiss path on the strength of this ref comment would set the flag and reintroduce exactly the first-edit suppress leak (R6-1 class) the blur handler's comment warns against.

Suggested change
// Set when a suggestion is accepted or the list is dismissed, so the
// path-change effect knows whether to reopen the list for that update.
const suppressNextFetchOpenRef = useRef(false);
// Set while Browse is in flight, so the path-change effect keeps the
// pick-triggered lookup closed until the first edit; blur dismissal
// invalidates in-flight lookups via suggestSeqRef instead.
const suppressNextFetchOpenRef = useRef(false);
中文说明

suppressNextFetchOpenRef 的声明注释仍把 blur 关闭列为置位方("当建议被接受或列表被关闭时置位"),但本次 diff 已移除该置位方——blur 定时器现在改为递增 suggestSeqRef。仅剩的 = true 写入位于 pickDirectory 的"浏览"流程中,且 acceptSuggestion 是清除而非置位该标志。该注释现在与下方约二十行处 blur 处理器的注释直接矛盾。— 失败场景:维护者依据此 ref 注释新增一条关闭路径时会置位该标志,从而重新引入 blur 处理器注释所警告的"首次编辑被抑制"泄漏(R6-1 类)。

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

onSuggest={(prefix) =>
workspaceActions.suggestWorkspacePaths(prefix)
}
onSuggest={workspaceActions.suggestWorkspacePaths}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-4: The switch to the stable onSuggest reference is load-bearing but unpinned by any App-level test. The dialog's fetch effect lists onSuggest in its deps [path, onSuggest, closeList], bumps suggestSeqRef on every run, and clears the 150 ms debounce in its cleanup — so a fresh per-render identity here restarts the debounce and invalidates in-flight lookups on every App re-render. Stability holds today only because DaemonWorkspaceProvider memoizes the actions object on [baseUrl, token]; App.test.tsx fully mocks the dialog, captures its props, and asserts the onPick/onClose/onAdd wiring, but never onSuggest. — Failure scenario: a future change re-introduces a per-render closure (the exact shape this diff removes) or widens the provider memo's deps → during streaming, when App re-renders constantly, every re-render while the dialog is open re-runs the fetch effect, so workspace suggestions churn and effectively never appear; the suite cannot detect the regression in either direction.

Suggested fix: in the existing App-level add-workspace test, assert latestAddWorkspaceDialogProps.onSuggest is mockWorkspaceActions.suggestWorkspacePaths and remains referentially identical across a re-render.

中文说明

改用稳定的 onSuggest 引用是承重的,但没有任何 App 层测试将其钉住。对话框的 fetch effect 把 onSuggest 列在依赖 [path, onSuggest, closeList] 中,每次运行都递增 suggestSeqRef,并在清理函数中清除 150 ms 去抖定时器——因此此处若重新出现每次渲染都变化的引用,App 每次重渲染都会重启去抖并使在飞行中的查询失效。当前的稳定性仅因 DaemonWorkspaceProvider[baseUrl, token] 为依赖记忆化 actions 对象而成立;App.test.tsx 完整 mock 了该对话框、捕获其 props,并断言了 onPick/onClose/onAdd 的接线,却从未断言 onSuggest。— 失败场景:未来某次改动重新引入每次渲染都变化的闭包(正是本 diff 移除的形态)或放宽 provider 记忆化的依赖 → 流式输出期间 App 持续重渲染,对话框打开时的每次重渲染都会重跑 fetch effect,工作区建议将不断抖动、实际上永远无法出现;且现有测试套件无法从任何方向检测到该回归。

建议修复:在现有的 App 层"添加工作区"测试中,断言 latestAddWorkspaceDialogProps.onSuggestmockWorkspaceActions.suggestWorkspacePaths,且在一次重渲染后引用保持同一。

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

Comment on lines +322 to 324
++suggestSeqRef.current;
closeList();
}, 100);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R7-5: Blur dismiss leaves stale suggestions that ArrowDown reopens. The blur timer bumps suggestSeqRef and closes the list, but the fetch callback's seq check returns BEFORE setSuggestions(...), so suggestions keeps the previous prefix's entries until the next edit. handleInputKeyDown's ArrowDown branch reopens a closed list whenever suggestions.length > 0 — so a bare refocus + ArrowDown pops entries that don't match the typed path, and Enter/Tab then accepts a wrong directory into the field. Diff-introduced: pre-diff, this blur sequence let the lookup resolve and refresh suggestions (at the cost of the pop-open bug this PR fixes); the seq-based invalidation is what makes the stale entries persist. — Failure scenario: type /home/me/co (list shows results A) → type /home/me/cod (lookup in flight) → blur past the 100 ms window (timer fires) → the stale lookup early-returns before setSuggestions → refocus without typing → ArrowDown reopens the list showing A against the input /home/me/cod → Enter accepts /home/me/code/ into the field. Probe-reproduced end-to-end at the reviewed commit; adding setSuggestions([]) flips the probe.

Suggested change
++suggestSeqRef.current;
closeList();
}, 100);
++suggestSeqRef.current;
setSuggestions([]);
closeList();
}, 100);
中文说明

blur 关闭会留下过期的建议数据,ArrowDown 可据此重新打开列表。blur 定时器递增 suggestSeqRef 并关闭列表,但 fetch 回调中的 seq 检查在 setSuggestions(...) 之前就 return,因此 suggestions 会保留上一个前缀的条目直到下一次编辑。handleInputKeyDown 的 ArrowDown 分支在 suggestions.length > 0 时会重新打开已关闭的列表——于是仅重新聚焦 + ArrowDown 就会弹出与当前输入不匹配的条目,Enter/Tab 随即把一个错误的目录接受进输入框。该问题由本 diff 引入:修改前,这一 blur 时序会让查询正常返回并刷新 suggestions(代价正是本 PR 要修复的自动弹出缺陷);基于序列计数器的作废机制才使过期条目得以长期残留。— 失败场景:输入 /home/me/co(列表显示结果 A)→ 输入 /home/me/cod(查询在飞行中)→ 失焦超过 100 ms 窗口(定时器触发)→ 过期查询在 setSuggestions 前提前返回 → 不做任何编辑直接重新聚焦 → ArrowDown 重新打开列表,输入框为 /home/me/cod 却显示 A → Enter 把 /home/me/code/ 接受进输入框。已在评审提交上端到端探针复现;加入 setSuggestions([]) 可翻转探针。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下:

Autofix address-review summary — PR #8844 (review round 7)

All four distinct findings (six inline comments) were verified against the reviewed commit and resolved in one commit: ff555e0e5c.

Feedback points and dispositions

  1. Misleading test comments about the blur-timer mechanism (AddWorkspaceDialog.test.tsx:399, :433, :773 — rc:3757535891, rc:3757535898, rc:3757535904) — Suggestion — Resolved. Verified against the code: the shipped blur-timer body is ++suggestSeqRef.current; closeList(); and never writes suppressNextFetchOpenRef, and pickDirectory calls blur() then synchronously cancelBlurDismiss() before await onPick(), so the failed-picker path never has a pending blur timer. Reworded all four comments to describe the shipped mechanism: the two "stale suppress flag" comments now say the timer closes the list and invalidates lookups via the sequence counter / bumps the sequence counter; the failed-picker test now states that the picker rejects instantly (dropping the false "settling before the blur timer" clause) and that no blur timer is pending because pickDirectory cancels it synchronously.
  2. Stale suppressNextFetchOpenRef declaration comment (AddWorkspaceDialog.tsx:78 — rc:3757535914) — Suggestion — Resolved. Verified: the only remaining = true write is pickDirectory's Browse flow; acceptSuggestion clears the flag, and blur dismissal no longer sets it. Reworded the comment to say the flag is set while Browse is in flight (so the path-change effect keeps the pick-triggered lookup closed until the first edit) and that blur dismissal invalidates in-flight lookups via suggestSeqRef instead.
  3. onSuggest stability unpinned by any App-level test (App.tsx:9661 — rc:3757535933) — Suggestion — Resolved. Verified that DaemonWorkspaceProvider memoizes the actions object on [baseUrl, token] and that the dialog's fetch effect lists onSuggest in its deps, bumps the sequence counter on every run, and clears the debounce in its cleanup. Added onSuggest to the captured dialog test props and asserted in the existing entry-points test that it is mockWorkspaceActions.suggestWorkspacePaths itself and stays referentially identical across a re-render. Probe check: temporarily reverting App.tsx to the old per-render closure makes the assertion fail.
  4. Blur dismiss leaves stale suggestions that ArrowDown reopens (AddWorkspaceDialog.tsx:324 — rc:3757535940) — Suggestion describing a real diff-introduced defect — Resolved. Verified the trace: the fetch callback's sequence check returns before setSuggestions, so after the blur timer invalidates an in-flight lookup the previous prefix's entries persist; handleInputKeyDown's ArrowDown branch reopens a closed list whenever suggestions.length > 0, so refocus + ArrowDown shows entries that don't match the typed path and Enter/Tab can accept a wrong directory. Added setSuggestions([]) to the blur-timer body and a regression test (drops stale suggestions on blur dismiss so refocus cannot reopen them). Probe check: temporarily removing the fix makes the new test fail.

Conflict notes

--conflict false: no merge of origin/main performed; no conflicts encountered.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx prettier --check on the three changed files — passed
  • vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx (packages/web-shell) — 34 passed (including the new regression test, probe-verified to fail without the setSuggestions([]) fix)
  • vitest run client/App.test.tsx (packages/web-shell) — 355 passed (including the new onSuggest identity assertions, probe-verified to fail against a per-render closure)
  • Integration tests — not run: the changed behavior is fully exercised by the package unit tests, not the bundled CLI or integration harness
  • npm run generate:settings-schema — not applicable: no settings source changed
中文说明

Autofix 评审处理总结 — PR #8844(评审第 7 轮)

全部四条独立发现(六条行内评论)均已在被评审提交上核实,并通过一次提交解决:ff555e0e5c

反馈点及处理

  1. 关于 blur 定时器机制的误导性测试注释AddWorkspaceDialog.test.tsx:399:433:773 — rc:3757535891、rc:3757535898、rc:3757535904)— 建议级 — 已解决。已对照代码核实:交付的 blur 定时器逻辑为 ++suggestSeqRef.current; closeList();,从不写入 suppressNextFetchOpenRef;且 pickDirectoryblur() 之后、await onPick() 之前就同步调用了 cancelBlurDismiss(),因此"选择器失败"路径上根本不存在未决的 blur 定时器。已将四处注释全部改写为描述实际交付的机制:两处"过期 suppress 标志"注释改为"定时器会关闭列表并通过序列计数器使查询失效"/"递增序列计数器";"选择器失败"测试的注释改为说明选择器立即 reject(删除了错误的"在 blur 定时器之前结束"表述),并说明此处没有未决的 blur 定时器,因为 pickDirectory 已同步取消它。
  2. 过期的 suppressNextFetchOpenRef 声明注释AddWorkspaceDialog.tsx:78 — rc:3757535914)— 建议级 — 已解决。已核实:仅剩的 = true 写入位于 pickDirectory 的"浏览"流程;acceptSuggestion 是清除该标志,blur 关闭也不再置位它。已将注释改写为:该标志在"浏览"进行中置位(使 path-change effect 让选择触发的查询保持关闭,直到第一次编辑),blur 关闭改为通过 suggestSeqRef 使在飞行中的查询失效。
  3. onSuggest 稳定性没有任何 App 层测试钉住App.tsx:9661 — rc:3757535933)— 建议级 — 已解决。已核实 DaemonWorkspaceProvider[baseUrl, token] 为依赖记忆化 actions 对象,且对话框的 fetch effect 把 onSuggest 列在依赖中、每次运行都递增序列计数器并在清理函数中清除去抖定时器。已在捕获的对话框测试 props 中加入 onSuggest,并在现有的"两个入口"测试中断言它就是 mockWorkspaceActions.suggestWorkspacePaths 本身,且在一次重渲染后引用保持同一。探针验证:把 App.tsx 临时还原为旧的每次渲染新建闭包后,该断言失败。
  4. blur 关闭留下过期建议,ArrowDown 可将其重新打开AddWorkspaceDialog.tsx:324 — rc:3757535940)— 建议级,但描述了一个由本 diff 引入的真实缺陷 — 已解决。已核实整条链路:fetch 回调中的序列检查在 setSuggestions 之前就 return,因此 blur 定时器使在飞行中的查询失效后,上一个前缀的条目仍会残留;handleInputKeyDown 的 ArrowDown 分支在 suggestions.length > 0 时会重新打开已关闭的列表,于是仅重新聚焦 + ArrowDown 就会显示与输入不匹配的条目,Enter/Tab 可能把错误的目录接受进输入框。已在 blur 定时器逻辑中加入 setSuggestions([]),并新增回归测试(drops stale suggestions on blur dismiss so refocus cannot reopen them)。探针验证:临时移除该修复后新测试失败。

冲突说明

--conflict false:未合并 origin/main,未遇到冲突。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 对三个改动文件运行 npx prettier --check — 通过
  • vitest run client/components/dialogs/AddWorkspaceDialog.test.tsx(packages/web-shell)— 34 个测试全部通过(含新增回归测试,已探针验证:移除 setSuggestions([]) 修复后该测试失败)
  • vitest run client/App.test.tsx(packages/web-shell)— 355 个测试全部通过(含新增的 onSuggest 引用同一性断言,已探针验证:还原为每次渲染新建闭包后该断言失败)
  • 集成测试 — 未运行:改动行为完全由包内单元测试覆盖,不经过打包后的 CLI 或集成测试框架
  • npm run generate:settings-schema — 不适用:未改动任何 settings 源

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

Not explored to full depth (tool budget reached): Context: PR #8844 (web-shell) closes workspace path sugge...: none — all checks I opened were completed within budget.; Context: PR #8844 (web-shell) closes workspace path sugge...: none — all checks I started were completed within budget.; Context: PR #8844 (web-shell) closes workspace path sugge...: none — all checks above were completed within budget.; Context: PR #8844 (web-shell) closes workspace path sugge...: the exact trigger of the flaky shadow DOM tests has not been identified (could not be reproduced in 11 subsequent runs).; Context: PR #8844 (web-shell) closes workspace path sugge...: Windows FolderBrowserDialog's UNC output has not been empirically verified (based on code reading only)., and 3 more.

中文说明

已审查。 建议见行内评论。

未探索到全部深度(达到工具调用预算):Context: PR #8844 (web-shell) closes workspace path sugge...:none — all checks I opened were completed within budget.;Context: PR #8844 (web-shell) closes workspace path sugge...:none — all checks I started were completed within budget.;Context: PR #8844 (web-shell) closes workspace path sugge...:none — all checks above were completed within budget.;Context: PR #8844 (web-shell) closes workspace path sugge...:the exact trigger of the flaky shadow DOM tests has not been identified (could not be reproduced in 11 subsequent runs).;Context: PR #8844 (web-shell) closes workspace path sugge...:Windows FolderBrowserDialog's UNC output has not been empirically verified (based on code reading only).,另有 3 条。

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

Comment on lines +124 to +125
getShadowAwareActiveElement(input) === input &&
(openOnResult || listOpenRef.current)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The new input-focus gate has no isolating test — deleting this conjunct leaves all 34 tests green (mutant verified by running the suite), yet the gate is load-bearing. — Failure scenario: user types an absolute path and clicks Browse while the lookup is debounced/in flight; pickDirectory closes the list and cancels the blur timer without bumping the sequence counter, so when the lookup resolves while the native picker is open (input blurred), only this gate prevents setListOpen(true). A future refactor that drops the gate ships a reopen-under-the-picker bug with every test still green. Second trigger: Escape closes the list without bumping seq, then blur, then a fast resolve inside the 100 ms window.

Suggested regression test (inverse order of the existing race test): type /home/me/co, click Browse immediately (lookup still debounced), advance timers so the lookup is in flight while the picker is up, resolve the suggestions while the picker is still open and assert listbox() is null; then resolve the pick with undefined and assert it is still null.

中文说明

新的输入框焦点门控没有专门的隔离测试——删除这个条件后全部 34 个测试仍然通过(已通过运行该变异体验证),但该门控是承重的。— 失败场景:用户输入绝对路径后,在查询处于去抖/飞行状态时点击“浏览”;pickDirectory 会关闭列表并取消 blur 定时器,但不递增序列计数器,因此当查询在系统选择器打开期间返回(输入框已失焦)时,只有这个门控能阻止 setListOpen(true)。未来某次删除该门控的重构会带着所有测试仍然绿灯 shipped 一个“选择器打开期间列表被重新打开”的缺陷。第二个触发路径:Escape 关闭列表(未递增 seq)→ blur → 查询在 100 ms 窗口内快速返回。

建议补充回归测试(与现有竞争测试相反的顺序):输入 /home/me/co,立即点击“浏览”(查询仍在去抖中),推进定时器使查询在选择器打开期间处于飞行状态,在选择器仍打开时让建议返回并断言 listbox() 为 null;再以 undefined 结束选择并断言列表仍为 null。

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

Comment on lines +182 to +184
if (pickedPath && pickedPath !== path) {
// Leave the suppress flag set: the path-change effect consumes it,
// keeping the pick-triggered lookup closed until the first edit.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] pickDirectory leaves suppressNextFetchOpenRef set for the path-change effect to consume, but the fetch effect only consumes it after the isAbsoluteLike(path) guard — a picked path that fails that check (e.g. a Windows UNC \\server\share from FolderBrowserDialog) early-returns with the flag still set, leaking it into the user's next edit. Probe-verified on this tree: the first edit does not open the list; adding the reset flips the probe with all 34 tests still green. Diff-introduced (pre-diff pickDirectory never set the flag). — Failure scenario: on Windows, Browse → pick a network share → setPath runs the effect's early-return branch, leaving the flag true → the user clears the field and types an absolute prefix → the first fetch computes openOnResult=false, so the suggestion list does not open until the second edit, violating the "first edit must open" invariant this PR establishes for every other picker outcome. Mitigation: handleSubmit rejects non-absolute-like paths, so this is a self-healing one-time UX paper cut.

Fix — consume the flag in the fetch effect's early-return branch (~line 104):

if (!isAbsoluteLike(path)) {
  suppressNextFetchOpenRef.current = false;
  setSuggestions([]);
  closeList();
  return undefined;
}

(or reset it in pickDirectory when !isAbsoluteLike(pickedPath))

中文说明

pickDirectorysuppressNextFetchOpenRef 置位后留给路径变化 effect 去消费,但 fetch effect 只在通过 isAbsoluteLike(path) 守卫之后才消费该标志——如果所选路径不满足该检查(例如 Windows 上 FolderBrowserDialog 返回的 UNC 路径 \\server\share),effect 会在标志仍为 true 时提前返回,使它泄漏到用户的下一次编辑。已在本代码树上通过探针验证:第一次编辑不会打开列表;补上重置后探针翻转,且全部 34 个现有测试仍然通过。此问题由本 diff 引入(修改前 pickDirectory 从不置位该标志)。— 失败场景:在 Windows 上点击“浏览” → 选择一个网络共享 → setPath 走 effect 的提前返回分支,标志保持 true → 用户清空输入框并输入绝对路径前缀 → 第一次查询算出 openOnResult=false,建议列表要到第二次编辑才打开,违反了本 PR 为其他所有选择器结果确立的“首次编辑必须打开”不变量。缓解因素:handleSubmit 同样拒绝非绝对路径形式的值,因此这是一次性且可自愈的轻微体验问题。

修复——在 fetch effect 的提前返回分支(约第 104 行)中消费该标志(代码见上),或在 pickDirectory 中当 !isAbsoluteLike(pickedPath) 时重置。

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

Comment on lines +190 to +192
// A same-value pick keeps the typed path, so invalidate any lookup
// already in flight from before Browse was clicked.
if (pickedPath) ++suggestSeqRef.current;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The else branch invalidates a pre-Browse in-flight lookup only for a same-value pick; the sibling outcomes grouped in the same comment (cancelled or failed picker) get the identical state transition but no seq invalidation. Probe-verified: cancelled picker + refocus pops the list open on zero edits; making the bump unconditional flips the probe with all 34 tests still green. — Failure scenario: type /home/me/co → lookup in flight → click Browse → cancel the picker (pickedPath undefined, no seq bump) → refocus → the stale lookup resolves with the pre-Browse captured openOnResult=true and passes the focus gate → setListOpen(true) pops the list open on a bare refocus with zero edits — exactly the outcome the PR's own same-value race test prevents for the sibling branch. Outcome is benign (entries match the unchanged path), but the guard is asymmetric between branches the comment treats as one family.

Suggested change
// A same-value pick keeps the typed path, so invalidate any lookup
// already in flight from before Browse was clicked.
if (pickedPath) ++suggestSeqRef.current;
// Cancelled, failed, and same-value picks keep the typed path, so
// invalidate any lookup already in flight from before Browse.
++suggestSeqRef.current;
中文说明

else 分支只在“选择相同路径”时作废“浏览”之前已在飞行中的查询;同一段注释归为一类的兄弟结果(取消或失败的选择器)经历完全相同的状态转换,却没有序列作废。已通过探针验证:取消选择器 + 重新聚焦会在零编辑时弹出列表;把递增改为无条件后探针翻转,且全部 34 个现有测试仍然通过。— 失败场景:输入 /home/me/co → 查询进入飞行 → 点击“浏览” → 取消选择器(pickedPath 为 undefined,未递增 seq)→ 重新聚焦 → 过期查询带着“浏览”前捕获的 openOnResult=true 返回并通过焦点门控 → setListOpen(true) 在零编辑时仅凭重新聚焦就弹出列表——这正是本 PR 自己的相同值竞争测试为兄弟分支所阻止的结果。后果本身无害(条目与未改变的路径一致),但注释视为同一族的两个分支之间,守卫是不对称的。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix round: no action

This round found nothing actionable on PR #8844:

  • Reviews: none newer than the last evaluation (2026-08-11T11:30:53Z).
  • Inline comments: none.
  • Issue-level comments: none.
  • Failed checks: none — every CI check on the current head completed as SUCCESS or SKIPPED.
  • Still-red checks: none.
  • Base conflicts: none reported (--conflict false); no merge was performed.

The PR is in Critical-only mode after five change-producing rounds. The remaining non-Critical feedback (one automated review and three inline suggestions on AddWorkspaceDialog.tsx) is deferred for human follow-up per the deferred-feedback audit record; this round intentionally makes no code changes, resolves no threads, and posts no replies for those items.

No commit was created; the branch stays at ff555e0e5c.

中文说明

Autofix 轮次:无需操作

本轮在 PR #8844 上未发现任何可处理的内容:

  • 评审(Reviews):自上次评估(2026-08-11T11:30:53Z)之后没有新的评审。
  • 行内评论(Inline comments):无。
  • Issue 级评论:无。
  • 失败的检查(Failed checks):无——当前 head 上的所有 CI 检查均以 SUCCESSSKIPPED 完成。
  • 持续失败的检查(Still-red checks):无。
  • 与基础分支的冲突:未报告冲突(--conflict false);未执行合并。

该 PR 在经过 5 个产生改动的轮次后已进入仅处理 Critical 的模式。剩余的非 Critical 反馈(一条自动化评审,以及针对 AddWorkspaceDialog.tsx 的三条行内建议)已按延后反馈审计记录留待人工跟进;本轮有意不进行任何代码改动、不解决任何线程,也不针对这些条目发布回复。

未创建任何提交;分支保持在 ff555e0e5c

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@wenshao

wenshao commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Maintainer verification report (local, real stack)

Verified head ff555e0 on macOS against a fully real stack: qwen serve daemon started from the PR source, plus two Vite dev frontends pointed at the same daemon — one serving the PR head ("after"), one serving an identical tree with the PR reverted ("before"). A Playwright-driven Chromium ran the same scripted interaction against both arms. GET /workspace-path-suggestions hit the real daemon/filesystem (fixture tree /var/tmp/ws8844/{alpha-app,beta-service,delta-lib,gamma-tool,workspace-root}); only POST /workspace-directory-picker was stubbed at the browser network layer with a 1.5 s delayed success response, so the automation doesn't pop a real macOS dialog — the client behavior under test is unaffected.

1. Unit tests & build (PR head)

  • AddWorkspaceDialog.test.tsx: 34/34 passed; App.test.tsx: 355/355 passed.
  • Full workspace build (including web-shell production build) succeeded.
  • Mutation check: reverting only the implementation (keeping the PR's tests) makes 9 of the new tests fail (blur-dismiss, delayed-lookup invalidation, blur-timer cancel/stacking, stale-suggestion drop, and the Browse/pick suppress cases) — the added tests genuinely pin the fix, they don't pass vacuously.

2. Scenario A — list must close on blur and stay closed

Typed /var/tmp/ws8844/, waited for real suggestions, then clicked outside the input (dialog heading) and sampled the DOM every 200 ms for 4 s.

before (PR reverted) after (PR head)
Blur closes the list ✅ closes ✅ closes
List stays closed afterwards spontaneously reopened ~0.6 s later with no user input ✅ stays closed for the whole 4 s window

The before-arm reopen is driven by the per-render onSuggest closure: every App re-render re-runs the dialog's fetch effect, the one-shot suppressNextFetchOpenRef is consumed by the first re-run, and the next re-run's lookup resolves with openOnResult=true — so the list pops back open while the input is unfocused. The PR closes both halves (memoized workspaceActions.suggestWorkspacePaths in App.tsx + focus gate / sequence-counter invalidation in the dialog).

typing — suggestions open (after arm) before: reopened after blur after: stays closed
typing before reopen after closed

3. Scenario B — Browse fills the path and keeps the list closed

Typed /var/tmp/ws8844/g (real lookup returns gamma-tool/), clicked Browse… (picker resolves after 1.5 s with /var/tmp/ws8844/gamma-tool), then sampled for 4 s after the fill.

before (PR reverted) after (PR head)
List while the picker is open ❌ stays open ✅ closed the moment Browse is clicked
After the pick fills the path reopened ~0.4 s later showing the redundant gamma-tool/ entry ✅ path filled, input unfocused, list stays closed
before: pending picker, list open before: redundant suggestion after pick after: clean final state
before pending before redundant after clean

4. Side observation — duplicate daemon queries eliminated

For the identical interaction sequence, the before arm issued 12 GET /workspace-path-suggestions requests (3 distinct prefixes, each re-fetched ~1/s by the effect re-runs), the after arm issued exactly 3 — one per prefix. The memoization fix also removes real duplicate daemon/filesystem load, not just the visual glitch.

Notes / caveats

  • The PR description's "Browse kept the path input focused" (before-state) did not reproduce exactly under Playwright — in both arms focus had already left the input at the sampled moment during the pending picker. What does reproduce, and what the fix visibly changes, is the suggestion list staying open during the pick and reopening with the redundant entry afterwards (screenshots above).
  • Native picker was network-stubbed as described; real osascript picker behavior itself was not exercised. Windows/Linux untested (matches the PR's stated scope).

Conclusion: works as described on a real daemon + real browser; before/after difference is exactly the fixed behavior; new tests fail on the un-fixed code. LGTM from a verification standpoint.

中文版本(Chinese version)

维护者本地真实环境验证报告

在 macOS 上对 head ff555e0 做了全真实栈验证:daemon 用 PR 源码启动(qwen serve),两个 Vite 前端指向同一个 daemon——一个跑 PR head("after"),一个跑回退了 PR 改动的相同代码树("before")。Playwright 驱动 Chromium 对两个 arm 执行完全相同的脚本化交互。GET /workspace-path-suggestions 打真实 daemon/文件系统(fixture 目录树 /var/tmp/ws8844/…);仅 POST /workspace-directory-picker 在浏览器网络层桩掉(延迟 1.5 秒返回成功),避免自动化时弹出真实 macOS 对话框——被测的客户端行为不受影响。

1. 单元测试与构建(PR head)

  • AddWorkspaceDialog.test.tsx:34/34 通过;App.test.tsx:355/355 通过;全仓构建(含 web-shell 生产构建)成功。
  • 变异测试:只回退实现、保留 PR 的测试,9 个新增测试失败(失焦关闭、延迟查询作废、blur 定时器取消/叠加、陈旧建议清除、Browse/pick 抑制等场景)——新测试确实钉住了修复,不是空转通过。

2. 场景 A——失焦后列表必须关闭且保持关闭

输入 /var/tmp/ws8844/ 等真实建议出现,点击输入框外部,随后每 200ms 采样 DOM 共 4 秒。

  • before:失焦关闭后,约 0.6 秒后列表在无任何用户输入的情况下自己弹回来
  • after:整个 4 秒窗口内保持关闭 ✅

before 的重开由逐 render 新建的 onSuggest 闭包驱动:App 每次重渲染都会让对话框的查询 effect 重跑,一次性的 suppress 标记被第一次重跑消费,下一次重跑的查询带着 openOnResult=true 返回,列表就在输入框失焦时弹开。PR 同时修了两半(App.tsx 传 memoize 的 action + 对话框内焦点门控/序号作废)。

3. 场景 B——Browse 填入路径且列表保持关闭

输入 /var/tmp/ws8844/g(真实查询返回 gamma-tool/),点击"浏览…"(选择器 1.5 秒后返回 /var/tmp/ws8844/gamma-tool),填入后采样 4 秒。

  • before:选择器挂起期间列表保持打开;选完后约 0.4 秒列表带着冗余的 gamma-tool/ 条目重新弹出
  • after:点击 Browse 即关列表;路径填入、输入框失焦、列表保持关闭 ✅

4. 附带发现——重复 daemon 查询被消除

相同交互序列下,before arm 发出 12GET /workspace-path-suggestions(3 个前缀,effect 重跑导致每个前缀约每秒重查一次),after arm 精确 3 次(每个前缀一次)。memoize 修复不只消除视觉问题,也消除了真实的重复 daemon/文件系统负载。

备注

  • PR 描述中"修改前 Browse 会让输入框保持焦点"这一点在 Playwright 下未精确复现(两个 arm 在选择器挂起时焦点均已离开输入框);但能复现、且修复明显改变的是:选择器挂起期间列表保持打开、选完后带冗余条目重开(见上方截图)。
  • 原生选择器按上述方式网络桩掉,osascript 本身未实测;Windows/Linux 未测(与 PR 声明范围一致)。

结论:在真实 daemon + 真实浏览器下行为与描述一致,before/after 差异恰为所修复的行为,新测试在未修复代码上失败。验证角度 LGTM。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix round: no action needed

This round's feedback contains no actionable items:

  • Reviews: none.
  • Inline comments: none.
  • Issue-level comments: the single new comment is @wenshao's maintainer verification report — a positive before/after verification of head ff555e0 on a real daemon + real browser stack. It confirms both fixed scenarios (the suggestion list closes on blur and stays closed; Browse fills the path while the list stays closed), confirms the new tests fail on the un-fixed code (mutation check), and notes the memoization also removes duplicate daemon queries (12 → 3 requests). Its conclusion is "LGTM from a verification standpoint". It requests no changes; the one caveat (the PR description's focus-state wording not reproducing exactly under Playwright) is informational and does not identify a defect in the shipped behavior.
  • Deferred non-Critical feedback: Critical-only mode is active after five change-producing rounds; the deferred section lists no items, and deferred items are audit records for human follow-up, not work for this round.
  • Failed / still-red checks: none.

No code changes were made; the branch remains at ff555e0.

中文说明

Autofix 本轮:无需处理

本轮反馈中没有任何可执行条目:

  • Reviews:无。
  • 行内评论:无。
  • Issue 级评论:唯一的新评论是 @wenshao 的维护者验证报告——在真实 daemon + 真实浏览器环境下对 head ff555e0 进行的修复前后对比验证,结论为正面。报告确认了两个修复场景(建议列表在失焦时关闭并保持关闭;点击 Browse 填入路径且列表保持关闭),确认新增测试在未修复代码上会失败(变异测试),并指出 memoize 还消除了重复的 daemon 查询(12 → 3 次请求)。其结论为"验证角度 LGTM"。报告未提出任何修改请求;其中一条备注(PR 描述中关于焦点状态的表述在 Playwright 下未精确复现)属于信息性说明,并未指出已发布行为存在缺陷。
  • 延后的非 Critical 反馈:已完成 5 个产生改动的轮次,当前处于仅处理 Critical 的模式;延后区域未列出任何条目,且延后条目是留待人工跟进的审计记录,不属于本轮工作。
  • 失败 / 持续失败的检查:无。

未做任何代码改动;分支保持在 ff555e0

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@wenshao

wenshao commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@wenshao
wenshao enabled auto-merge August 12, 2026 06:11
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 12, 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: 189 passed · 0 failed · 189 total

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

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

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

Verification report

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

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

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

Scripted assertions: 189 passed · 0 failed · 189 total

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

沙箱验证在隔离、无凭证的容器中复测了该 PR 的新 head(ff555e0e,比第一轮多 5 个提交)。脚本断言 189 通过 · 0 失败。

  • A/B 结论:21 个行为单元格在三个构建(base 16ff42bd / 第一轮 head 67c0e3db / 新 head ff555e0e)上全部与预测一致(63/63)。base 复现全部症状;第一轮 head 修复了原始 bug 但带 6 个残余缺陷(blur 定时器泄漏 suppress 标志导致取消/报错/同值选择后首个编辑不弹列表、旧建议可被 ArrowDown 重开、pre-blur 查询在重新聚焦后弹开、re-blur 定时器叠加);新 head 全部修复(见下表与 01-ab-three-arm-cells.png)。
  • 第一轮发现状态:① “失焦后重聚焦首个按键不弹列表” 的小毛病 → 已修复(B1 单元格 + 新测试钉住);② Browse 按钮 onMouseDown preventDefault 变异存活 → 仍然存在,jsdom 无法钉住且新代码中已被显式 blur+cancel 取代,信息级;③ 描述中 “23/23” → 仍不准确,现为 34 个测试。
  • 新发现(均非阻塞):焦点门控(getShadowAwareActiveElement(input) === input)在 PR 自带测试中无钉住(删除后 34/34 仍绿),但 harness 证明它在 100ms 失焦宽限窗和 picker 打开期间两个窗口仍 load-bearing(建议级,附候选 fixture);M4/M8/M9/M10 四个存活变异已逐一分类为冗余/防御性子句。
  • 门槛:web-shell 全量 181 文件 3281/3281 通过;typecheck、eslint、prettier 干净且均先以植入错误验证门槛是活的。
  • 未覆盖:真实系统目录选择器、真实浏览器指针语义、仓库级门槛、Playwright e2e。
Verification report

PR 8844 deep verification (round 2) — fix(web-shell): keep workspace picker suggestions closed

Verdict: merge-ready — 189/189 scripted assertions passed (0 unexpected failures).
Verified head: ff555e0e5c725cdeda229659d84b15fb0e89135c (git rev-parse HEAD^2 of merge commit 6992c4c9), base 16ff42bde7 (HEAD^1). The metadata snapshot's baseRefOid (a86f1e5c…) predates the checked-out merge-ref base; per the CI contract the effective diff HEAD^1..HEAD (5 web-shell files, clean merge) was measured. This is a follow-up round; the previous report (at head 67c0e3db, verdict merge-ready) is carried forward below and every measurement was re-run at the new head.

0. Previous-finding status table (re-measured at ff555e0e)

# finding (round 1) severity status at new head
R1-1 After a blur dismiss, the first keystroke once the input is refetched fetches but does not show suggestions (pre-existing suppress-flag quirk) informational fixed — cell B1: base red, prev red, head green; pinned by the PR's new test opens suggestions on the first edit after the blur dismiss fired; the new guards that fix it are pinned (M5/M6/M7 kills)
R1-2 Restoring onMouseDown preventDefault on Browse survives the suite (jsdom .click() fires no mousedown) informational stands — clause still present; mutant M10 still survives (34/34); classification unchanged (unpinnable in jsdom), and at the new head it is additionally superseded: pickDirectory blurs and cancels the dismiss timer explicitly, so the clause's removal is behaviorally inert in the production flow too
R1-3 (correction) Description said "focused Web Shell tests (23/23)" while the file had 24 tests correction stands, now wider — the description still says 23/23; the file now contains 34 tests (the five delta commits added 10). All 34 pass (measured). Description correction only

Declined/deferred rows from round 1: none.

1. Central claim and A/B proof

Central claim. Once the workspace-path input loses focus, the suggestion list closes and stays closed — a delayed lookup completing after blur must not reopen it, and the Browse flow must fill the selected path with the input unfocused and no list.

Delta under test (5 commits since round 1). 0e80df09 cancels the 100 ms blur-dismiss timer inside pickDirectory and applies close+suppress synchronously, with outcome-dependent suppress handling; 2ff92ea2 adds the re-blur cancellation test; b5037580 cancels the timer on focus and unmount; 797a75f8 replaces the blur-time suppressNextFetchOpenRef=true with a sequence-counter bump (invalidating in-flight lookups instead of poisoning the next fetch); ff555e0e clears stale suggestions on blur dismiss and extracts getShadowAwareActiveElement into utils/dom.ts (also used by two App.tsx focus sites), plus pins onSuggest to the memoized workspace action so the dialog's fetch effect no longer restarts on every App render.

The same 21-cell harness (harness/zz-verify-ab.test.tsx, fake timers, controlled prop promises, plain-document and shadow-root portal modes) ran in three trees — base worktree (HEAD^1), round-1-head worktree (67c0e3db), and the merge head — with per-arm expectations encoded, so every bug cell is an assertion that the build misbehaves as predicted (predicted reds count as passing assertions). 63/63 matched:

cell oracle base 16ff42bd prev 67c0e3db head ff555e0e
C00 input focused on mount activeElement focused focused focused
A1 typing opens suggestions listbox opens opens opens
A2 lookup resolves after blur listbox reopens closed closed
A3 Browse releases focus activeElement retained released released
A4 list visible while picker open listbox visible closed closed
A5 list reopens after fill listbox reopens closed closed
A6 shadow-DOM portal, focused input listbox opens opens opens
B1 first edit after dismiss opens listbox closed closed opens
B2a blurred when late lookup lands listbox reopens closed closed
B2b ArrowDown on refocus listbox reopens reopens closed
B3a quick pick (50 ms), before edit listbox opens closed closed
B3b first edit after quick pick listbox opens closed opens
B4 re-blur within window, then edit listbox closed closed opens
B5 unmount with pending dismiss no throw ok ok ok
B6 pre-blur lookup resolves after refocus listbox pops pops closed
B7 first edit after same-value pick listbox opens closed opens
B8 first edit after cancelled picker listbox opens closed opens
B9a picker error surfaced alert shown shown shown
B9b first edit after picker error listbox opens closed opens
G1 lookup resolves in 100 ms grace window listbox reopens closed closed
G2 in-flight lookup resolves during picker listbox reopens closed closed

Witness: evidence/01-ab-three-arm-cells.png (live re-run of all three arms printing the full CHECK grid).

Attribution. Base reproduces every symptom the PR describes. Round-1 head fixed the original five document-mode cells but left six residual defects, all visible as red prev cells: the leaked dismiss timer set suppress=true after cancel/error/same-value outcomes (B3b, B7, B8, B9b), stale entries survived dismissal (B2b), a pre-blur lookup could pop the list open after refocus (B6), and stacked re-blur timers were never cancelled (B4). The new head turns all six green while keeping every round-1 fix green. Each delta commit's diff (object-level, trees available despite the shallow checkout) matches its headline; git rev-list HEAD^1..HEAD^2 returns 1 (shallow-boundary artifact) while all 11 commit objects from the snapshot exist locally with intact parent chains — per-commit attribution for the five delta commits was exercised at the object level.

2. Corrections

  • The description's evidence line still says "focused Web Shell tests (23/23)". At this head the file contains 34 tests, all passing (measured, §4). Description correction only — no code change implied.

3. Vacuity check and mutation matrix (PR's own tests, at head)

Unmutated control M0 green (34/34). Single-point mutants of the production files, scored against the PR's unmodified test file by harness/score.mjs (116/116 scripted expectations) and re-run live for the capture:

mutant change result killed by (behavioural)
M1 focus gate reverted to if (openOnResult || listOpenRef.current) survives (34/34) — (see finding 1)
M2 gate reads document.activeElement killed (1) opens suggestions for a focused input in a shadow-DOM portal rootexpected null not to be null
M3 inputRef.current?.blur() removed from pickDirectory killed (1) opens the system picker and fills the selected absolute path — focus assertion
M4 cancelBlurDismiss() removed from pickDirectory survives (34/34) — (classified §5)
M5 ++suggestSeqRef.current removed from blur timer killed (2) keeps suggestions closed when a pre-blur lookup resolves after refocus + drops stale suggestions…expected <ul …> to be null
M6 setSuggestions([]) removed from blur timer killed (1) drops stale suggestions on blur dismiss…
M7 onFocus={cancelBlurDismiss} removed killed (2) cancels the pending blur dismiss when focus returns… + …first edit after a re-blur…
M8 unmount cleanup effect removed survives (34/34) — (classified §5)
M9 input !== null && guard removed survives (34/34) — (classified §5)
M10 Browse onMouseDown preventDefault removed survives (34/34) — (R1-2 stands)
M11 getShadowAwareActiveElementdocument.activeElement killed (1) shadow-DOM test (positive control at the shared seam)
M12 App.tsx onSuggest back to a per-render closure killed (1) opens one App-owned Add workspace dialog…expected [Function onSuggest] to be [Function spy]

Witness: evidence/03-mutation-matrix-live.png (live M0–M12 run), evidence/02-cross-arm-suite-matrix.png (scripted scoring of the cross-arm suite runs and the matrix).

Cross-arm suite oracle. The head test file run against all three arms: head 34/34 green; base fails 9, prev fails 9 — same count, different sets (6 shared): base-only reds (keeps suggestions closed when a lookup finishes after blur, keeps the pick-triggered lookup closed until the first edit, opens the system picker and fills the selected absolute path) are exactly the round-1 fixes; prev-only reds (does not pop suggestions open on refocus when a same-value pick raced an in-flight lookup, opens suggestions on the first edit after a cancelled picker, shows an error when the system picker fails) are exactly the delta commits' fixes. Every new guard is pinned by the test its commit says it strengthens; no mutant regressed from killed to survived versus round 1's matrix.

4. Findings

  1. The focus gate is load-bearing but not pinned by the suite (Suggestion). Removing it (M1) leaves the 34-test suite green, yet the 21-cell harness flips cells G1 and G2 red under M1 (19/21): a lookup resolving inside the 100 ms blur grace window, or an in-flight lookup resolving while the picker is open, would pop the list open while the input is unfocused. The sequence counter covers post-dismiss resolutions; the gate covers these two windows. The code is correct — this is a coverage gap. A pinning fixture: type a prefix, let the debounce fire, blur, advance 50 ms (inside the grace window), resolve the lookup, and assert listbox() is null. Not a merge condition.
  2. Surviving mutants classified (informational). M4 (cancelBlurDismiss in pickDirectory): behaviorally equivalent — the harness runs 21/21 under it, because at this head the leaked timer no longer poisons suppressNextFetchOpenRef (the author's own test comment states this); redundant defense-in-depth. M8 (unmount cleanup) and M9 (input !== null): React 18+ makes post-unmount setState a no-op, so the consequence is unobservable in any environment; defensive hygiene. M10: see R1-2.
  3. Description drift (informational) — see Corrections.

No blocking findings. The PR's risk note ("suggestions continue to be fetched and updated while unfocused, but cannot become visible until existing input interactions open them again") holds at head for every probed window except the intended ones (focus returned within the grace window; refocus after a pick, where ArrowDown shows the picked path's suggestions for fine-tuning).

5. Not covered

  • Real native directory picker: onPick is host-provided and was driven with controlled promises at the prop seam; picker UX verified only by the author on macOS.
  • Real-browser pointer semantics (mousedown-driven focus movement, click-outside): jsdom does not simulate them; cells drive .click()/.blur() directly. This is why M10 survives and why the Reviewer Test Plan's "click outside" step was exercised as a blur() event — the wire shape is reproduced, the pointer mechanism is not.
  • Repo-wide gates not run; gates scoped to packages/web-shell (the effective diff's only workspace): 181 files / 3281/3281 tests (junit-verified), tsc -p tsconfig.json --noEmit, eslint on the five changed files, prettier --check — each proven live with a planted violation first (evidence/04-gates-live.png). The M12 filter run skipped the other 385 App.test tests; the full file ran green inside the workspace gate.
  • Playwright e2e suites not run — unit-level A/B chosen instead.
  • Per-commit attribution for commits 1–6 comes from round 1 plus the prev arm; the five delta commits were diffed at the object level (all trees present locally; rev-list undercounts at the shallow boundary).

6. Methodology

Environment: CI verify container (node:22-bookworm), Node 22.23.2, vitest 3.2.4, jsdom 26.1.0; repo pre-installed and pre-built at the merge commit. A/B arms ran in git worktrees (HEAD^1, 67c0e3db) reusing the root node_modules — clean control: the effective diff leaves package-lock.json untouched, and the dialog's import closure contains no @qwen-code/* packages (grep-verified; the internal symlinks in node_modules/@qwen-code/* point at the head tree but are never resolved by the harness). The harness renders the real component through real react-dom into jsdom (plain document and shadow-root portal modes), drives it with fake timers and controlled prop promises, and records every check as CHECK|arm|cell|PASS/FAIL lines plus a per-arm tally; a predicted-red control cell counts as a passing assertion. Cross-arm suite runs and the mutation matrix were scored programmatically by harness/score.mjs (116/116), which parses the saved vitest logs (ANSI-stripped) and compares per-test outcomes to encoded expectations. Raw logs, harness sources, mutants and captures live under logs/, harness/, evidence/ in this artifact directory. The dom-probe capture's shadow-mode|false console line was an over-strict compound print in the probe (it wrongly expected the host element to resolve through its own shadow root); the two real assertions of that case passed (utility resolves the inner element for nodes inside the shadow root; document.activeElement retargets to the host).

Evidence images

01-ab-three-arm-cells

02-cross-arm-suite-matrix

03-mutation-matrix-live

04-gates-live

Qwen Code · sandboxed verification

Evidence images

01-ab-three-arm-cells

02-cross-arm-suite-matrix

03-mutation-matrix-live

04-gates-live

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

Qwen Code · sandboxed verification

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix round summary — PR #8844 (no action)

Nothing to address this round; no changes were made.

  • Critical-only mode is active after 5 change-producing rounds. Every actionable section this round was empty: no new reviews, no new inline comments, no issue-level comments, no failed checks, and no still-red checks.
  • One non-Critical item from the automated reviewer was excluded by the workflow and recorded in the "Deferred non-Critical feedback" section for human follow-up. Per Critical-only rules, deferred items were not acted on this round (no code changes, no thread resolutions, no comment replies).
  • No merge with origin/main was performed (--conflict false).
  • No commit was created; the branch head remains ff555e0e5c (fix(web-shell): clear stale suggestions on blur dismiss in AddWorkspaceDialog (fix(web-shell): keep workspace picker suggestions closed #8844)).
中文说明

Autofix 轮次总结 — PR #8844(无操作)

本轮没有需要处理的内容,未做任何改动。

  • 在完成 5 个产生改动的轮次后,已进入仅处理 Critical 的模式。本轮所有可处理区域均为空:没有新的评审、没有新的行内评论、没有 issue 级评论、没有失败的检查、也没有持续失败的检查。
  • 自动化评审器的一条非 Critical 条目已被工作流排除,并记录在 "Deferred non-Critical feedback" 部分,留待人工跟进。按照仅处理 Critical 的规则,本轮不处理被延后的条目(不改代码、不解决讨论串、不回复评论)。
  • 未与 origin/main 合并(--conflict false)。
  • 未创建提交;分支头仍为 ff555e0e5c(fix(web-shell): clear stale suggestions on blur dismiss in AddWorkspaceDialog (fix(web-shell): keep workspace picker suggestions closed #8844))。

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


🧠 Handled by Qwen Code · model/模型 qwen3.8-max

@wenshao
wenshao added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit 6195895 Aug 12, 2026
145 checks passed
@QwenLM QwenLM deleted a comment Aug 12, 2026
@QwenLM QwenLM deleted a comment Aug 12, 2026
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.11.

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

Labels

autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants