Skip to content

feat(core): add a per-project outside-repo artifact landing - #9776

Merged
wenshao merged 15 commits into
mainfrom
feat/audit-fallback-dir
Aug 25, 2026
Merged

feat(core): add a per-project outside-repo artifact landing#9776
wenshao merged 15 commits into
mainfrom
feat/audit-fallback-dir

Conversation

@wenshao

@wenshao wenshao commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds Storage.getAuditFallbackDir(projectRoot): a per-user, per-project directory under QWEN_HOME where artifacts can land when they must not reach the audited repository. It is created 0700, keyed by the project hash, and stable across symlink spellings of the same root.

Adoption of an existing landing is validated rather than assumed, in two layers:

  • The leaf itself. The path is fully predictable — the project hash is a pure function of the root — and 0700 does not exclude the user's own other processes, so "it already exists" is not evidence this tool created it. A leaf planted as a symlink is refused; a permissive mode is tightened, because mkdirSync's mode applies only to directories it creates.
  • What is inside it. Artifacts land BELOW the leaf, and an O_NOFOLLOW open only ever guards the final component, so a planted symlink child is a complete escape: mkdirSync treats a symlink-to-directory as the directory, and everything written "inside" the landing goes wherever the link points — while the leaf keeps passing every check on itself. A hardlinked regular file is the same story through O_TRUNC. Both are refused by name. The landing is reused across runs, so a merely non-empty one stays adoptable.

Why it's needed

This is the first of six parts of the /audit workflow (design doc #8397), split out of #9749 because that PR was too large to review — every automated review round on it disclosed tool budget reached and could not execute a single test file.

The landing is the piece with no /audit dependencies, so it lands first and alone. /audit writes reports, sidecars, plans, and findings files that quote the audited module verbatim; when the audited repository's ignore state cannot keep those out of version control, the workflow relocates them here instead of refusing to run.

The containment properties are the point of the change, not a detail of it: this directory exists to hold content that must stay private, and it sits at a path anything running as the user can predict.

Reviewer Test Plan

How to verify

  1. npx vitest run src/config/storage.test.ts in packages/core — 74 pass.
  2. Confirm the landing's shape: Storage.getAuditFallbackDir('/some/project') returns <QWEN_HOME>/audits/<64-hex>, created 0700, idempotent, distinct per project, and identical for a symlinked spelling of the same root.
  3. Confirm each refusal, and that each is discriminating — deleting the assertAuditLandingIsClean(dir) call turns the symlink-child and hardlink cases red, and dropping the leaf lstat turns the planted-symlink case red:
    • a leaf pre-planted as a symlink to another directory → refused, not a directory;
    • a symlink child inside the leaf (the escape primitive: audit-<ts>.sidecar pointing out of the landing) → refused, contains a symlink;
    • a hardlinked file inside the leaf → refused, hardlinked file;
    • a landing holding an ordinary previous report and sidecar directory → still adopted, because the landing is reused across runs.

Evidence (Before & After)

Before: no outside-repo landing exists; there is no getAuditFallbackDir.

After: the landing exists and is validated on adoption. The suite covers each refusal and the reuse case; mutation-checking each guard (removing the call, removing the lstat) turns the corresponding cases red, so none of them pass vacuously.

Tested on

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

The symlink and hardlink cases are win32-skipped: creating either needs elevation or Developer Mode there, and the mode check is a no-op on a platform whose stat carries no POSIX group/other bits.

Environment (optional)

Node.js 22 development checkout on macOS. packages/core unit suite, TypeScript type checking, ESLint, Prettier.

Risk & Scope

  • Main risk or tradeoff: the contents check costs one readdir (plus an lstat per regular file) per call. The landing is small and the call happens a handful of times per run.
  • Not validated / out of scope: Windows and Linux; no caller exists yet — /audit arrives in the follow-ups. Write-time containment (binding each artifact write to this root) lands with the writers that need it; this PR closes the static-plant arm, and nothing writes here until then.
  • Breaking changes / migration notes: none. New method, no existing behaviour touched.

Linked Issues

Part 1 of 6 implementing #8397. Split out of #9749.

中文说明

本 PR 做什么

新增 Storage.getAuditFallbackDir(projectRoot)QWEN_HOME 下按用户、按项目的目录,供产物在不能进入被审计仓库时落地。以 0700 创建,按项目哈希取名,且对同一根目录的不同符号链接写法保持稳定。

对已存在落点的采纳是校验而非假定,分两层:

  • 叶子本身。 路径完全可预测——项目哈希是根目录的纯函数——且 0700 并不排除用户自己的其他进程,因此「它已经存在」不能证明是本工具创建的。被植入为符号链接的叶子会被拒绝;权限过宽会被收紧,因为 mkdirSync 的 mode 只作用于它新建的目录。
  • 叶子里面的内容。 产物落在叶子之下,而 O_NOFOLLOW 只保护最末一段路径,所以植入的符号链接子项是一条完整的逃逸路径:mkdirSync 会把指向目录的符号链接当作该目录,于是写入「落点内部」的一切都去了链接指向的地方——而叶子自身始终通过所有检查。硬链接的常规文件经由 O_TRUNC 是同样的故事。两者都被具名拒绝。落点会跨运行复用,因此仅仅非空的落点仍可采纳。

为什么需要

这是 /audit 工作流(设计文档 #8397)六个部分中的第一个,从 #9749 拆出——那个 PR 体量过大无法评审:其上每一轮自动评审都披露「工具预算耗尽」,且一个测试文件都没能执行。

落点是唯一不依赖 /audit 任何部分的片段,因此单独先行。/audit 写出的报告、sidecar、计划与发现文件都逐字引用被审计模块;当被审计仓库的 ignore 状态无法把它们挡在版本控制之外时,工作流会把它们搬迁到这里,而不是拒绝运行。

封闭性正是这次改动的要点而非细节:这个目录的存在就是为了存放必须保持私有的内容,而它所在的路径,任何以该用户身份运行的东西都能预测出来。

评审测试计划

如何验证

  1. packages/core 执行 npx vitest run src/config/storage.test.ts——74 项通过。
  2. 确认落点形态:Storage.getAuditFallbackDir('/some/project') 返回 <QWEN_HOME>/audits/<64 位十六进制>,以 0700 创建,幂等,按项目区分,且同一根目录的符号链接写法得到相同结果。
  3. 确认各项拒绝,并确认它们具备判别力——删掉 assertAuditLandingIsClean(dir) 调用会让符号链接子项与硬链接两例变红,去掉叶子的 lstat 会让「植入符号链接叶子」一例变红:
    • 叶子被预先植入为指向其他目录的符号链接 → 拒绝,not a directory
    • 叶子内含符号链接子项(逃逸原语:audit-<ts>.sidecar 指向落点之外)→ 拒绝,contains a symlink
    • 叶子内含硬链接文件 → 拒绝,hardlinked file
    • 叶子内含上一次运行留下的普通报告与 sidecar 目录 → 仍然采纳,因为落点跨运行复用。

证据(前后对比)

前:不存在仓库外落点,也没有 getAuditFallbackDir

后:落点存在并在采纳时校验。测试覆盖每一项拒绝与复用场景;对每道守护做变异(删调用、删 lstat)都会让对应用例变红,因此没有一条是空过的。

测试平台

系统 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

符号链接与硬链接用例在 win32 上跳过:在该平台创建两者都需要管理员权限或开发者模式,而其 stat 不携带 POSIX group/other 位,权限检查也是空操作。

环境(可选)

macOS 上的 Node.js 22 开发检出。packages/core 单元套件、TypeScript 类型检查、ESLint、Prettier。

风险与范围

  • 主要权衡:内容检查每次调用花费一次 readdir(以及每个常规文件一次 lstat)。落点很小,且每次运行只调用少数几次。
  • 未验证/范围外:Windows 与 Linux;目前还没有调用者——/audit 在后续 PR 中到来。写入时封闭(把每次产物写入绑定到该根目录)随需要它的写入方一起落地;本 PR 关闭的是静态植入这一路,而在此之前没有任何东西会写入这里。
  • 无破坏性变更:新增方法,未触碰任何既有行为。

关联 Issue

实现 #8397 的第 1/6 部分。自 #9749 拆出。

`/audit` (landing in follow-ups) writes reports, sidecars, and intermediates
that quote the audited module verbatim. When the audited repository's ignore
state cannot keep those out of version control, they have to land somewhere
the repository can never commit — this is that landing: per user and per
project under QWEN_HOME, 0700, so quoted (possibly exploitable) module
content stays private.

Adoption is validated rather than assumed. The path is fully predictable —
the project hash is a pure function of the root — and 0700 does not exclude
the user's own other processes, so an existing leaf is not evidence this
tool created it. A leaf planted as a symlink is refused, and a permissive
mode is tightened, since mkdirSync's mode only applies to directories it
creates.

The contents are validated too, because artifacts land BELOW the leaf and an
O_NOFOLLOW open only guards the final component: a symlink child is a
complete escape (mkdirSync treats a symlink-to-directory as the directory,
so everything written "inside" goes wherever it points) while the leaf keeps
passing every check on itself. A hardlinked file is the same story through
O_TRUNC. Both are refused. The landing is reused across runs — the report
and its sidecar are the durable artifacts — so a merely non-empty landing
stays adoptable.
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-run at 71a6928c, after the prior round's blocker was fixed and seven autofix rounds followed.

Template looks good ✓ — all sections present, including the reviewer test plan with per-guard mutation evidence.

Problem: unchanged from the prior pass — not a bugfix; part 1 of 6 of the /audit workflow (design doc #8397, merged), split out of #9749 because that PR grew too large to review. The need for an outside-repo landing stands on the merged design doc, and the threat model is concrete: the landing sits at a path anything running as the user can predict and will hold sensitive artifacts, so validated adoption is the feature.

Direction: aligned, same anchor as before (merged design doc; no CHANGELOG analogue, expected for a novel workflow). One naming nit: the PR body still says getAuditFallbackDir, while the API settled on ensureAuditFallbackDir during the review rounds — worth correcting when this merges.

Size: core paths touched (packages/core/src/config/**). Now 275 production lines (storage.ts, +274/−1) vs 827 test lines vs 0 generated/schema. Production roughly tripled since the last gate pass, driven by findings from the previous review (parent-component validation, containment guard, race re-checks) — still far below every threshold, feat type, maintainer-authored.

Approach: scope still right. Every line added since the prior pass maps to a prior-round finding; no drive-by changes. The one shared-helper edit (case folding in isResolvedPathWithinDirectory) also affects the existing plans-dir guard, but only on case-insensitive volumes and only in the stricter direction — it can add a refusal, never remove one.

Risk: no elevated risk signals — neither changed file matches the revert-correlated high-risk paths.

Moving on to code review. 🔍

中文说明

71a6928c 重新运行——上一轮的阻塞项已修复,其后又经历了七轮 autofix。

模板完整 ✓ —— 各节齐全,评审测试计划仍为每个防护提供变异验证说明。

问题:与上一轮相同——不是 bug 修复;是 /audit 工作流 6 个部分中的第 1 部分(设计文档 #8397 已合入),从过大的 #9749 中拆出。仓库外落点的需求由已合入的设计文档确立;威胁模型是具体的:落点路径对同用户进程完全可预测且将存放敏感产物,因此"校验后采纳"是功能本身。

方向:对齐,锚点不变(已合入的设计文档;CHANGELOG 无对应项,对新工作流属预期)。一个小命名问题:PR 描述仍写 getAuditFallbackDir,而 API 在评审轮次中已定名 ensureAuditFallbackDir——合入时值得更正。

规模:触及核心路径(packages/core/src/config/**)。现为 275 行生产代码(storage.ts,+274/−1)、827 行测试、0 行生成/schema。生产代码自上次门禁通过以来约增至三倍,均由上一轮评审的发现驱动(父组件校验、容纳性防护、竞态复查)——仍远低于所有阈值,feat 类型,作者为维护者。

方案:范围仍然合理。上次通过之后新增的每一行都对应上一轮的发现,无顺手改动。唯一一处共享 helper 修改(isResolvedPathWithinDirectory 的大小写折叠)也会影响现有 plans 目录防护,但只在大小写不敏感卷上生效、且只会更严格——只可能增加拒绝,不会放行。

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

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

The blocker from the last review is fixed, in exactly the shape suggested there. Adoption validation now walks every component the method creates, not just the leaf: adoptDirectory does a non-recursive mkdirSync(…, { mode: 0o700 }) per component, then lstat and refuses anything that is not a real directory — applied to audits and to the project leaf alike. A planted audits symlink (the prior-round escape: one ln -s, no race) now dies at the lstat instead of relocating the whole landing, and the regression test plants it, asserts the refusal, and asserts nothing was created inside the planter's directory.

The rounds since then added hardening that holds up, not churn:

  • Containment guard — the landing must resolve outside the audited repository, checked before creation, re-checked after the base exists (a not-yet-existing QWEN_HOME passes the first check by design), and failing closed at the final site where nothing downstream owns a resolution failure. A same-UID plant of the QWEN_HOME tail between check and mkdir is covered by a race-injection test.
  • Content validation is recursive and stat-driven — every arm decides from a fresh per-entry lstat, not the readdir snapshot's dirent types, which also closes the prior round's non-blocking observation about untyped dirents slipping through. Symlink children, nested symlinks under real subdirectories, hardlinked files (nlink > 1), and special files (FIFO/socket/device) are each refused with a test that plants the real shape on tmpfs.
  • TOCTOU posture — the pre-return re-validation (re-adoption → content re-check → containment re-check → re-adoption again) is exercised by ~10 deterministic race tests injecting swaps at the mkdir/readdir seams. The code comment is honest that this narrows the race but cannot close the tail of a path-returning API against a same-UID planter — the right call; full closure belongs to the writer follow-ups binding writes to the returned root.
  • Case folding on win32/darwin, before hashing and in the containment comparison, with tests for both properties (case-variant spellings share one leaf; a case-variant spelling of the audited root is still refused). The fold touches the shared isResolvedPathWithinDirectory helper, so it also applies to the existing plans-dir guard — only on folding platforms, and only in the stricter direction (uniform lowercasing preserves string-prefix containment, so it can add a refusal, never remove one).

Non-blocking, recorded on this PR already and not repeated as findings: the vanished between readdir and lstat continue arm has no dedicated test (continue→throw mutant survives), and the PR body's getAuditFallbackDir naming is stale relative to the landed ensureAuditFallbackDir. Neither gates this.

Testing

Unattended CI run — nothing is built or executed from the PR in this review; the evidence below is the PR's own CI read through the API. All checks on 71a6928c are complete — no failures, nothing pending. The Ubuntu unit suite is the load-bearing signal: it runs every new non-win32 case (planted leaf, planted parent, symlink child, nested symlink, hardlink, FIFO, 0300 repair, the race-injection set, case-variant refusal) on a real Linux filesystem and is green. macOS/Windows legs show skipped by design (merge-queue-only per ci.yml); the merge queue exercises them, where the symlink/hardlink cases are platform-skipped and the mode check is a documented no-op. No failing check to excerpt. The sandboxed verification job started with this triage dispatch is still in flight; its report posts separately when it lands.

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

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

中文说明

代码审查

上一轮的阻塞项已修复,且正是当时建议的形态。采纳校验现在覆盖本方法创建的每一层组件,而不只是叶子:adoptDirectory 对每层做非递归 mkdirSync(…, { mode: 0o700 }),随后 lstat 拒绝一切非真实目录——同样应用于 audits 与项目叶子。植入的 audits 符号链接(上一轮的逃逸:一条 ln -s、无需竞态)现在会在 lstat 处被拒绝,而不是把整个落点转移;回归测试植入该符号链接、断言拒绝、并断言植入者目录内未创建任何内容。

其后的各轮补充的是站得住的加固,而非搅动:

  • 容纳性防护——落点必须解析在被审计仓库之外:创建前检查一次,基目录存在后复查一次(尚不存在的 QWEN_HOME 按设计通过首次检查),终点处失败即关闭——该处之后没有任何环节能兜住解析失败。QWEN_HOME 尾部在检查与 mkdir 之间被同用户植入的竞态由注入测试覆盖。
  • 内容校验是递归的、且以 stat 为准——每个分支都由每条目新鲜 lstat 裁决,而非 readdir 快照的 dirent 类型,这同时关闭了上一轮关于无类型 dirent 漏过的非阻塞观察。符号链接子项、真实子目录下的嵌套符号链接、硬链接文件(nlink > 1)、特殊文件(FIFO/socket/设备)各有在 tmpfs 上真实植入的拒绝测试。
  • TOCTOU 姿态——返回前复查(再采纳 → 内容复查 → 容纳性复查 → 再次采纳)由约 10 个在 mkdir/readdir 缝隙注入置换的确定性竞态测试演练。代码注释诚实地说明这能收窄竞态、但无法关闭路径返回型 API 面对同用户植入者的尾部——这是正确的取舍;彻底关闭属于后续 writer PR 把写入绑定到返回根的工作。
  • 大小写折叠应用于 win32/darwin 的哈希前与容纳性比较,两条性质均有测试(大小写变体共享同一叶子;被审计根的大小写变体仍被拒绝)。折叠触及共享的 isResolvedPathWithinDirectory,因此也作用于现有 plans 目录防护——仅在折叠平台、且只会更严格(统一小写保持字符串前缀容纳性,只可能增加拒绝,不会放行)。

非阻塞、已在本 PR 记录、不再作为发现重复:vanished between readdir and lstat 的 continue 分支暂无专门测试(continue→throw 变异体可存活);PR 描述中的 getAuditFallbackDir 命名相对已落地的 ensureAuditFallbackDir 已过时。两者均不构成门禁。

测试

无人值守 CI 运行——本审查不构建、不执行 PR 的任何代码;以下证据为经 API 读取的 PR 自身 CI。71a6928c 上所有检查已完成——无失败、无进行中。Ubuntu 单元测试是承重信号:它在真实 Linux 文件系统上运行全部新增非 win32 用例(植入叶子、植入父目录、符号链接子项、嵌套符号链接、硬链接、FIFO、0300 修复、竞态注入组、大小写变体拒绝)且为绿。macOS/Windows 腿按设计跳过(依 ci.yml 仅 merge queue 运行),将由合并队列执行;那里符号链接/硬链接用例按平台跳过、模式检查为文档化的空操作。无失败检查可摘录。随本次分诊启动的沙箱验证任务仍在运行,其报告将另行发布。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — the prior blocker is fixed with a discriminating regression test, the hardening added since is real and tested rather than churn, and every check on this commit is green; the two remaining items are recorded non-blocking nits.

Stepping back: this is what a good review loop looks like. The last pass found a genuine containment bypass against the PR's own stated threat model — the audits parent planted as a symlink, relocating the whole landing while every leaf check passed. The fix is not a patch over it: adoption validation now walks every component the method creates, the regression test plants the exact shape from the review, and the follow-up rounds turned the same scrutiny on every seam the re-validation introduced — containment re-checks, stat-driven content validation, race-injection tests at each swap window. The code is unusually honest about its own limits: the comment names that the re-walk narrows but cannot close the tail of a path-returning API against a same-UID planter, and assigns that closure to the writer follow-ups, which is the correct scoping.

Against my independent proposal from the last pass, this exceeds it — I would have validated the parent and stopped there; the containment guard, the case-folding for the win32/darwin spelling problem, and the fail-closed final check all answer attacks I did not enumerate. Every line of the growth since the gate pass maps to a prior-round finding; there is no drive-by scope. The two open items — the untested vanished-entry continue arm and the stale getAuditFallbackDir naming in the PR body — are suggestions, not gates. CI is green on the reviewed commit with the Ubuntu suite running the full non-win32 refusal set on a real filesystem, and nothing is pending. Approving.

中文说明

置信度:4/5 —— 上一轮的阻塞项已以具有判别性的回归测试修复,其后的加固是真实且有测试支撑的而非搅动,本提交上所有检查为绿;剩余两项均为已记录的非阻塞小问题。

退后看:这是一次良性评审循环的样子。上一轮发现了一个针对 PR 自述威胁模型的真实容纳性绕过——把 audits 父目录植入为符号链接,即可在所有叶子检查照常通过的情况下转移整个落点。修复不是在表面打补丁:采纳校验现在覆盖本方法创建的每一层组件,回归测试植入的正是评审中给出的形态,后续各轮又把同样的审视投向复查机制引入的每一条缝隙——容纳性复查、以 stat 为准的内容校验、每个置换窗口的竞态注入测试。代码对自身边界异常诚实:注释明说复查能收窄、但无法关闭路径返回型 API 面对同用户植入者的尾部,并把该关闭工作划给后续 writer PR——这是正确的范围划分。

对照我上一轮的独立方案,本实现超出了它——我只会校验父目录然后止步;容纳性防护、针对 win32/darwin 写法问题的大小写折叠、终点失败即关闭,都回应了我未列举的攻击。门禁通过以来新增的每一行都对应上一轮的发现,无顺手扩张。两个未决项——消失条目 continue 分支暂无测试、PR 描述中 getAuditFallbackDir 命名过时——是建议而非门禁。被审提交上 CI 为绿,Ubuntu 套件在真实文件系统上运行了完整的非 win32 拒绝用例集,且无进行中检查。予以批准。

Qwen Code · qwen3.8-max

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

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

One blocking finding: the static-plant arm is still open through the audits parent component — a planted symlink there relocates the whole landing while every check on the leaf passes. Full analysis, repro, and suggested fix in my review comments above. Everything else is mergeable quality. 🙏

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

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

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

Qwen Code · serve A/B

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 85.34% 85.34% 90.67% 84.36%
Core 88.52% 88.52% 90.25% 87.04%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   85.34 |    84.36 |   90.67 |   85.34 |                   
 src               |   85.82 |    81.89 |   88.03 |   85.82 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |   73.34 |    78.04 |   80.76 |   73.34 | ...1336-1340,1467 
  ...ractiveCli.ts |   88.26 |    82.64 |   88.88 |   88.26 | ...3135,3141,3207 
  ...liCommands.ts |   88.93 |    83.21 |      80 |   88.93 | ...97-599,615,721 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |    73.5 |    76.25 |   93.17 |    73.5 |                   
  acpAgent.ts      |   72.37 |    75.94 |   92.27 |   72.37 | ...74,12285,12331 
  ...k-reporter.ts |     100 |       80 |     100 |     100 | 81,84,119,141     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  ...heap-probe.ts |   97.39 |    96.66 |     100 |   97.39 | 243,264-265       
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...figuration.ts |     100 |     91.3 |     100 |     100 | 73,124            
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
  ...ersistence.ts |   94.95 |    92.24 |     100 |   94.95 | ...13-118,227-228 
  ...management.ts |   74.75 |     66.3 |     100 |   74.75 | ...92-496,505-509 
  ...e-download.ts |    64.7 |    62.24 |    87.5 |    64.7 | ...08-609,615-619 
 ...tegration/live |    97.5 |       88 |   92.85 |    97.5 |                   
  ...en-context.ts |   95.74 |    82.35 |     100 |   95.74 | ...0,66-67,99-100 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...ak-to-user.ts |   96.66 |      100 |    87.5 |   96.66 | 37-38             
  ...task-tools.ts |   98.97 |      100 |   88.88 |   98.97 | 201-202           
 ...ration/service |    97.1 |    95.89 |   93.75 |    97.1 |                   
  filesystem.ts    |    97.1 |    95.89 |   93.75 |    97.1 | ...22-123,246-247 
 ...ration/session |   91.05 |    86.57 |   95.75 |   91.05 |                   
  Session.ts       |    90.4 |    85.32 |   95.13 |    90.4 | ...50,12677-12681 
  ...entTracker.ts |   96.81 |    89.36 |      90 |   96.81 | 137-143,222       
  ...projection.ts |   98.85 |    91.59 |     100 |   98.85 | 234,250,262       
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   94.16 |    86.36 |     100 |   94.16 | ...43,347,427,431 
  ...y-replayer.ts |   83.41 |    93.22 |   94.11 |   83.41 | ...29-147,265-267 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...oal-update.ts |   98.61 |    97.29 |     100 |   98.61 | 64                
  ...lure-guard.ts |   98.32 |    97.72 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.62 |    92.73 |   97.05 |   95.62 |                   
  ...ageEmitter.ts |   95.25 |    93.54 |     100 |   95.25 | ...08-115,128-129 
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  base-emitter.ts  |   78.26 |    77.77 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   98.57 |    94.84 |     100 |   98.57 | 75-76,394-395     
 ...ession/rewrite |    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 |    81.59 |   91.53 |      89 |                   
  attach-lease.ts  |     100 |    96.96 |     100 |     100 | 173               
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  ...ged-detach.ts |     100 |     90.9 |     100 |     100 | 40,64             
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  pty-host-env.ts  |     100 |      100 |     100 |     100 |                   
  ...st-process.ts |   87.99 |     77.6 |   94.28 |   87.99 | ...1219,1309-1311 
  pty-host.ts      |   84.51 |    85.04 |   90.69 |   84.51 | ...14-516,531-532 
  ...sor-client.ts |   80.38 |    72.81 |   77.41 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    89.47 |   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.16 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |    91.54 |   83.33 |   93.98 | 228-238           
  ...r-sideband.ts |   95.37 |    86.44 |     100 |   95.37 | 203-204,228-233   
 src/commands      |   90.66 |    78.53 |   65.62 |   90.66 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.85 |      100 |      50 |   98.85 | 98                
  serve.ts         |   89.46 |    76.02 |     100 |   89.46 | ...12-915,927,938 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   89.06 |    88.57 |   90.64 |   89.06 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   94.88 |    95.49 |      90 |   94.88 | ...20-323,368-371 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.83 |    96.35 |     100 |   95.83 | ...03-208,266-269 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.91 |    85.61 |   94.33 |   93.91 | ...1264,1271-1272 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.53 |    96.66 |     100 |   98.53 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    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.85 |    87.73 |   87.09 |   88.85 |                   
  consent.ts       |   72.53 |    90.32 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     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.63 |    55.55 |     100 |   75.63 | ...30-134,136-140 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.25 |    84.61 |   83.33 |   90.25 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |    92.9 |    84.84 |      80 |    92.9 | ...79-181,199-200 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   91.63 |    90.09 |   92.84 |   91.63 |                   
  agent-prompt.ts  |   94.89 |    92.99 |   97.95 |   94.89 | ...3286,3621-3701 
  base-tree.ts     |   77.02 |    80.76 |   77.77 |   77.02 | ...63-384,386-399 
  capture-local.ts |   73.58 |     90.9 |      75 |   73.58 | 112-116,163-186   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   92.18 |    89.69 |    90.9 |   92.18 | ...1061,1063-1064 
  comment-body.ts  |   67.85 |    87.09 |   66.66 |   67.85 | ...30,157,159-164 
  ...ent-status.ts |   94.22 |    87.32 |    90.9 |   94.22 | ...96,462,738-758 
  ...ose-review.ts |   97.17 |    93.76 |   98.52 |   97.17 | ...5563-5607,5882 
  cost-ledger.ts   |   94.58 |     94.4 |   81.25 |   94.58 | ...53-654,694-704 
  drive.ts         |    94.1 |    92.85 |   92.85 |    94.1 | ...80-782,787-789 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-diff.ts    |   73.75 |      100 |   66.66 |   73.75 | 77-97             
  fetch-pr.ts      |   97.29 |    92.25 |     100 |   97.29 | ...1566,1724-1729 
  findings.ts      |   96.02 |    92.15 |     100 |   96.02 | ...1249,1258-1259 
  issue-context.ts |   88.15 |     93.1 |   85.71 |   88.15 | 249-276           
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.55 |     92.3 |   66.66 |   85.55 | 74-79,144-150     
  meta.ts          |   79.43 |    93.75 |   66.66 |   79.43 | 123-128,147-162   
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |   99.49 |    95.66 |     100 |   99.49 | 585,856,912       
  plan-diff.ts     |   71.42 |      100 |   66.66 |   71.42 | 162-197           
  pr-context.ts    |   96.03 |    87.58 |     100 |   96.03 | ...2233,2333-2349 
  presubmit.ts     |   94.32 |    90.83 |   94.11 |   94.32 | ...1214,1249-1280 
  ...ish-assets.ts |    81.3 |    82.22 |   85.71 |    81.3 | ...75-479,506-552 
  ...r-findings.ts |   90.74 |    83.75 |     100 |   90.74 | ...17-422,429-430 
  repo-context.ts  |   94.62 |    90.75 |     100 |   94.62 | ...66-467,482-487 
  ...ve-anchors.ts |   78.34 |    89.28 |      75 |   78.34 | ...83-188,200-217 
  run.ts           |   82.66 |    88.54 |   94.11 |   82.66 | ...22,638-692,706 
  save-artifact.ts |    94.2 |    92.46 |   94.11 |    94.2 | ...14-617,710-713 
  scratch-tree.ts  |   95.93 |       86 |     100 |   95.93 | ...91-392,461-464 
  script-lint.ts   |   81.27 |    79.38 |   88.88 |   81.27 | ...69-783,785-807 
  submit.ts        |   94.11 |    89.38 |   94.44 |   94.11 | ...1673,1701-1738 
  test-delta.ts    |    86.4 |       92 |      60 |    86.4 | 177-208,471-479   
  test-efficacy.ts |   85.62 |    81.26 |      96 |   85.62 | ...3120,3128-3148 
  test-plan.ts     |   94.61 |    91.79 |      95 |   94.61 | ...29-832,873-874 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |   97.37 |    94.81 |   98.75 |   97.37 |                   
  agent-briefs.ts  |   99.08 |      100 |      50 |   99.08 | 821-822           
  ...t-identity.ts |     100 |      100 |     100 |     100 |                   
  anchors.ts       |     100 |    97.04 |     100 |     100 | ...39,175,184,231 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  audit-layers.ts  |   98.67 |    96.15 |     100 |   98.67 | 288-290           
  authorization.ts |   93.48 |    93.45 |     100 |   93.48 | ...79-385,583-584 
  budget.ts        |     100 |    97.95 |     100 |     100 | 887,940           
  build-budget.ts  |     100 |      100 |     100 |     100 |                   
  certification.ts |     100 |      100 |     100 |     100 |                   
  convergence.ts   |   99.46 |    97.17 |    90.9 |   99.46 | 590,808           
  coverage.ts      |   98.97 |    95.11 |     100 |   98.97 | ...1103,1648-1649 
  deadline.ts      |   98.03 |    91.66 |     100 |   98.03 | ...20,752,820,837 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 75                
  diff-plan.ts     |   98.77 |    93.26 |     100 |   98.77 | ...78,301,327-328 
  disk.ts          |     100 |      100 |     100 |     100 |                   
  effort.ts        |     100 |      100 |     100 |     100 |                   
  failing-files.ts |     100 |    93.33 |     100 |     100 | 41                
  gh.ts            |   89.53 |    95.52 |   78.94 |   89.53 | ...47,384-385,412 
  git.ts           |   96.77 |    93.93 |     100 |   96.77 | 234-235,272-273   
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  import-graph.ts  |   96.68 |     95.4 |     100 |   96.68 | 180-182,211-212   
  ...ntal-scope.ts |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ...audit-gate.ts |     100 |     97.5 |     100 |     100 | 135               
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |   84.86 |    90.38 |     100 |   84.86 | ...63-473,475-483 
  ...ry-context.ts |   96.61 |    95.48 |     100 |   96.61 | ...47-450,496-499 
  md-field.ts      |     100 |      100 |     100 |     100 |                   
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  narrow-diff.ts   |     100 |      100 |     100 |     100 |                   
  npm-toolchain.ts |   98.23 |    95.29 |     100 |   98.23 | ...,819,1200,1217 
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   96.96 |       95 |     100 |   96.96 | 32-33             
  prompt-record.ts |   98.03 |    94.23 |     100 |   98.03 | 293-294,300       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   98.03 |    94.73 |     100 |   98.03 | 109-110           
  report.ts        |   92.92 |    86.66 |     100 |   92.92 | 213-214,216-220   
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 187               
  resume.ts        |     100 |      100 |     100 |     100 |                   
  retirement.ts    |     100 |    94.36 |     100 |     100 | ...58-559,760,917 
  review-footer.ts |   99.55 |     98.1 |     100 |   99.55 | 548-549           
  ...w-settings.ts |     100 |    95.83 |     100 |     100 | 89                
  roster.ts        |     100 |    97.14 |     100 |     100 | 177,222           
  round-model.ts   |     100 |      100 |     100 |     100 |                   
  run-ledger.ts    |    98.2 |    93.87 |     100 |    98.2 | ...23,541,647,670 
  same-file.ts     |     100 |    94.11 |     100 |     100 | 35                
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.18 |    94.04 |     100 |   98.18 | 431,472,512-513   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  toolchain.ts     |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   98.09 |    95.07 |     100 |   98.09 | ...92,438,707-708 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 186               
  workspaces.ts    |     100 |    96.85 |     100 |     100 | 222,452,499,512   
  ...ree-reader.ts |     100 |      100 |     100 |     100 |                   
  worktree.ts      |   89.39 |    81.78 |     100 |   89.39 | ...1813-1814,1827 
 ...w/lib/platform |   94.71 |    87.89 |   97.05 |   94.71 |                   
  aone-client.ts   |   94.94 |     87.3 |     100 |   94.94 | ...92-293,299-302 
  aone.ts          |   93.06 |    89.86 |   94.73 |   93.06 | ...34,598-603,655 
  github.ts        |   99.08 |     75.8 |     100 |   99.08 | 249-250           
  registry.ts      |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...mands/sessions |   94.11 |    89.06 |   89.47 |   94.11 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
  ps.ts            |     100 |    94.44 |     100 |     100 | 58                
 src/config        |   94.32 |    90.38 |   95.01 |   94.32 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.36 |    88.37 |     100 |   93.36 | ...06-307,330-331 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   89.54 |    90.29 |   83.78 |   89.54 | ...2497,2499-2507 
  ...cy-monitor.ts |      90 |    77.27 |     100 |      90 | ...72-73,90-92,98 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  environment.ts   |    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.4 |       50 |     100 |    97.4 | 240-243           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.96 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   78.57 |       92 |   86.66 |   78.57 | ...18-319,324-326 
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.93 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.16 |    92.71 |      90 |   91.16 | ...1027,1029-1030 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  settingsUtils.ts |   80.82 |     89.2 |   85.18 |   80.82 | ...85-603,610-618 
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.54 |     100 |   92.53 | ...36-337,373-384 
 ...nfig/migration |   95.23 |    78.94 |   85.71 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |       80 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |   75.08 |    67.64 |   71.42 |   75.08 |                   
  ...tputBridge.ts |   75.33 |    68.18 |   73.68 |   75.33 | ...09-410,418-421 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   89.68 |    88.66 |   93.02 |   89.68 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languageUtils.ts |   98.88 |    97.01 |     100 |   98.88 | 184-185           
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   87.37 |    83.73 |   89.32 |   87.37 |                   
  ...ng-failure.ts |     100 |      100 |     100 |     100 |                   
  ...iveHelpers.ts |   94.95 |    91.05 |     100 |   94.95 | ...30-431,529,542 
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  ...iagnostics.ts |    95.8 |     87.5 |   93.75 |    95.8 | ...03,277-278,289 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...33-634,637-638 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |   57.47 |     66.3 |   73.68 |   57.47 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   70.04 |    62.92 |   91.66 |   70.04 | ...11-620,635-640 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   53.96 |    67.08 |   66.66 |   53.96 | ...78-690,699-728 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.18 |    94.09 |   95.34 |   98.18 |                   
  ...putAdapter.ts |   98.07 |    93.18 |   98.11 |   98.07 | ...1448,1464-1465 
  ...putAdapter.ts |   96.22 |    91.66 |   85.71 |   96.22 | 52-53             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.51 |      100 |   90.47 |   98.51 | 90-91,131-132     
  ...projection.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/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.69 |    96.28 |     100 |   99.69 |                   
  ...livery-ipc.ts |     100 |    91.17 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   87.24 |    84.43 |    90.8 |   87.24 |                   
  ...extra-args.ts |     100 |      100 |     100 |     100 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.99 |     91.5 |     100 |   93.99 | ...29-430,433-435 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 702               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.54 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.98 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   89.64 |    94.16 |   96.55 |   89.64 | ...57-269,521-524 
  ...ebhook-ipc.ts |    98.5 |     87.5 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.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 
  ...horization.ts |     100 |      100 |     100 |     100 |                   
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.54 |    84.53 |   97.14 |   92.54 | ...1489,1543-1547 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.9 |     78.6 |   94.73 |    90.9 | ...1001,1022-1027 
  ...tree-guard.ts |   92.89 |    87.55 |     100 |   92.89 | ...2766,2836-2840 
  daemon-logger.ts |   82.82 |    78.68 |   92.04 |   82.82 | ...1775,1802-1808 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.69 |    91.96 |     100 |   98.69 | ...1590,1592-1593 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    87.09 |     100 |   92.06 | ...72,287-293,316 
  ...h-settings.ts |   94.94 |    90.45 |     100 |   94.94 | ...30,708,724,734 
  fast-path.ts     |   91.38 |       82 |   95.45 |   91.38 | ...46-555,633-634 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-149             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...30-131,142-143 
  ...pp-sandbox.ts |   96.72 |    95.23 |     100 |   96.72 | 41-42             
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...-with-auth.ts |     100 |      100 |     100 |     100 |                   
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  ...nal-ledger.ts |    94.9 |    84.78 |     100 |    94.9 | ...81,302,361-362 
  rate-limit.ts    |   92.68 |    88.29 |     100 |   92.68 | ...89-291,303-305 
  ...qwen-serve.ts |   84.04 |    80.69 |   76.06 |   84.04 | ...7995,8013-8017 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.52 |    59.42 |   76.92 |   45.52 | ...1050,1062-1085 
  ...-keepalive.ts |   94.31 |    88.18 |     100 |   94.31 | ...37,541-542,581 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  ...-lifecycle.ts |   89.16 |    90.29 |   86.95 |   89.16 | ...24-325,330-334 
  serve-token.ts   |     100 |      100 |     100 |     100 |                   
  server.ts        |   91.16 |    90.45 |   71.42 |   91.16 | ...3012,3042-3043 
  ...-admission.ts |   99.13 |    95.94 |     100 |   99.13 | 308-309           
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...-redaction.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.72 |    77.93 |     100 |   93.72 | ...51,854,867-869 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   93.45 |    86.88 |     100 |   93.45 | ...77-280,323-326 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |    98.6 |     79.8 |     100 |    98.6 | 108,136,179,182   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   94.98 |    90.55 |     100 |   94.98 | ...67-568,575-576 
  ...e-remember.ts |   98.23 |    92.56 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |    89.4 |    90.55 |     100 |    89.4 | ...89-190,258-279 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...visibility.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.83 |   96.15 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.09 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   80.34 |    80.22 |    94.5 |   80.34 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |   93.03 |    84.13 |   98.52 |   93.03 | ...1624,1671-1682 
  dispatch.ts      |   75.51 |    77.21 |   93.33 |   75.51 | ...5509,5566-5572 
  index.ts         |   82.68 |    79.74 |   91.22 |   82.68 | ...2424,2510-2511 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  ...ach-budget.ts |     100 |      100 |     100 |     100 |                   
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   98.26 |    88.75 |     100 |   98.26 | 87-88,117         
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   94.06 |    89.09 |     100 |   94.06 | 50,55,134,138-141 
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 .../conversations |   90.17 |    85.27 |      95 |   90.17 |                   
  ...e-activity.ts |     100 |      100 |     100 |     100 |                   
  ...ime-errors.ts |     100 |      100 |     100 |     100 |                   
  ...me-manager.ts |     100 |      100 |     100 |     100 |                   
  ...-ownership.ts |   87.33 |    83.58 |   88.46 |   87.33 | ...57-558,601-602 
  ...-workspace.ts |   89.09 |    78.66 |     100 |   89.09 | ...91-292,339-340 
 src/serve/fs      |   87.77 |    82.34 |     100 |   87.77 |                   
  audit.ts         |     100 |    96.29 |     100 |     100 | 211               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |    74.01 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.52 |    89.18 |     100 |   90.52 | 172-180           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   88.02 |    81.85 |     100 |   88.02 | ...3027,3037-3038 
 src/serve/live    |   77.23 |     70.5 |   90.46 |   77.23 |                   
  discovery.ts     |   85.89 |    82.05 |    91.3 |   85.89 | ...73-579,592-593 
  ...oordinator.ts |   82.67 |    76.63 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |    76.7 |    67.47 |   85.71 |    76.7 | ...1885,1976-1977 
  ...controller.ts |   67.82 |    79.66 |      75 |   67.82 | ...66-278,287-295 
  ...sk-service.ts |   87.45 |    65.93 |   95.65 |   87.45 | ...1186-1187,1215 
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.85 |    77.39 |     100 |   94.85 | ...18,327-330,350 
  types.ts         |     100 |      100 |     100 |     100 |                   
 .../local-control |   82.89 |    88.77 |      90 |   82.89 |                   
  credentials.ts   |   96.42 |    95.45 |     100 |   96.42 | 109-110           
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...interfaces.ts |   43.58 |    82.75 |   42.85 |   43.58 | ...09-117,130-142 
  ...r-identity.ts |     100 |    85.71 |     100 |     100 | 61                
  service.ts       |    93.4 |       90 |     100 |    93.4 | ...20-222,313-315 
 src/serve/routes  |   85.87 |    81.03 |   95.27 |   85.87 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |   98.73 |    96.15 |     100 |   98.73 | 82                
  ...nel-notify.ts |   79.16 |    85.18 |     100 |   79.16 | ...03-104,120-126 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.94 |    91.17 |     100 |   98.94 | 143               
  health.ts        |   99.09 |    91.17 |     100 |   99.09 | 147               
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |   84.61 |    76.47 |     100 |   84.61 | ...04,106-111,131 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.94 |    85.26 |   93.75 |   87.94 | ...1539,1584-1585 
  ...on-runtime.ts |   91.42 |       90 |     100 |   91.42 | 56-64             
  session.ts       |   86.25 |    82.36 |   93.45 |   86.25 | ...6730,6732-6733 
  sse-events.ts    |   86.85 |    85.64 |   94.11 |   86.85 | ...18-929,932,939 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.35 |    78.94 |     100 |   90.35 | ...52-553,576-577 
  ...d-contacts.ts |   83.62 |    94.59 |     100 |   83.62 | 123,125-142       
  ...controller.ts |   83.33 |    80.47 |      90 |   83.33 | ...1056,1061,1068 
  ...extensions.ts |    88.8 |    77.83 |   93.84 |    88.8 | ...2329,2374-2375 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   89.72 |    79.35 |     100 |   89.72 | ...05,719-726,807 
  ...t-branches.ts |   75.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 
  ...al-control.ts |   74.17 |    69.23 |     100 |   74.17 | ...18,220-226,231 
  ...management.ts |   87.47 |       85 |     100 |   87.47 | ...1733,1743-1748 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.67 |       75 |     100 |   75.67 | ...15-726,732-733 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.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 |   76.92 |     67.1 |      80 |   76.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    81.02 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   92.75 |    89.98 |   97.22 |   92.75 |                   
  access-log.ts    |   98.73 |    97.26 |     100 |   98.73 | 119,196           
  ...-timestamp.ts |     100 |      100 |     100 |     100 |                   
  ...er-helpers.ts |   63.82 |    78.15 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.87 |       80 |     100 |   97.87 | 27                
  ...r-response.ts |   87.73 |    76.19 |     100 |   87.73 | ...97,814,877-886 
  fs-factory.ts    |     100 |    95.52 |     100 |     100 | 77,144,200        
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...list-cache.ts |   99.01 |    95.52 |     100 |   99.01 | 184-185           
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |       80 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.13 |    95.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 |   91.39 |    87.04 |   97.56 |   91.39 | ...,975,1003-1004 
  ...ion-export.ts |     100 |       95 |     100 |     100 | 64                
  session-list.ts  |      97 |    93.45 |     100 |      97 | ...1068,1273-1277 
  ...ry-context.ts |    87.5 |       50 |     100 |    87.5 | 49-50             
  telemetry.ts     |   99.06 |    97.26 |     100 |   99.06 | ...04,873,952-954 
 src/serve/voice   |    92.7 |    91.53 |   97.72 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.24 |     100 |     100 | 176               
 ...kspace-service |    90.9 |    88.03 |   91.66 |    90.9 |                   
  index.ts         |   90.41 |    87.29 |      90 |   90.41 | ...1505-1509,1512 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.69 |    89.67 |   98.13 |   92.69 |                   
  ...mandLoader.ts |     100 |       95 |     100 |     100 | 106               
  ...killLoader.ts |   97.19 |    85.71 |     100 |   97.19 | 142,153-154       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   87.09 |    83.07 |     100 |   87.09 | ...35-340,345-350 
  ...omptLoader.ts |   79.55 |    88.42 |   85.71 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.77 |     92.3 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   92.14 |    92.42 |     100 |   92.14 | ...91-296,329-330 
  ...low-loader.ts |     100 |    96.29 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...s/housekeeping |      93 |    88.34 |      95 |      93 |                   
  scheduler.ts     |      93 |    88.34 |      95 |      93 | ...57-359,411-415 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.94 |    86.86 |   96.29 |   88.94 |                   
  DataProcessor.ts |   88.31 |    86.84 |      95 |   88.31 | ...1368,1372-1379 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.25 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |       85 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.83 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.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            |   70.84 |    77.49 |   72.04 |   70.84 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   76.08 |       72 |   69.44 |   76.08 | ...4298,4414-4420 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |   63.63 |      100 |   41.17 |   63.63 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...AutoUpdate.ts |   93.54 |    94.64 |      90 |   93.54 | 126,131,202-213   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...ractiveUI.tsx |   71.53 |    75.47 |    62.5 |   71.53 | ...11,338,405-410 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  systemInfo.ts    |   95.09 |    90.27 |     100 |   95.09 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
 src/ui/auth       |   58.76 |    66.66 |   51.06 |   58.76 |                   
  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.83 |       75 |     100 |   94.83 | ...33-234,253-259 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   84.04 |     84.2 |   91.07 |   84.04 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...or-command.ts |     100 |    95.65 |     100 |     100 | 104,182           
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 28,62             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...28-129,137-146 
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...essCommand.ts |   68.22 |    54.05 |      75 |   68.22 | ...97-198,212-215 
  ...astCommand.ts |   84.27 |       75 |     100 |   84.27 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   74.79 |    74.39 |   84.61 |   74.79 | ...89-622,633-634 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   90.56 |    87.83 |    90.9 |   90.56 | ...75-280,327-334 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 26                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  doctorCommand.ts |   70.16 |    84.61 |      95 |   70.16 | ...29-679,682-816 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   80.48 |       75 |     100 |   80.48 | 49-54,69-72,93-98 
  effort-utils.ts  |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |     100 |    96.49 |     100 |     100 | 139,192           
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.25 |    65.71 |   85.71 |   81.25 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   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,102-103        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.01 |    85.76 |     100 |   86.01 | ...1093,1127-1132 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |    89.6 |       90 |     100 |    89.6 | ...72-176,212-219 
  ...oreCommand.ts |   90.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.33 |    72.13 |     100 |   77.33 | ...46-150,173-178 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |     100 |      100 |     100 |     100 |                   
  voice-command.ts |   93.63 |       88 |     100 |   93.63 | 36,98-103         
  ...owsCommand.ts |   94.38 |    85.29 |     100 |   94.38 | ...78-183,282-287 
 src/ui/components |    73.1 |    80.02 |   77.58 |    73.1 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   89.06 |    90.78 |     100 |   89.06 | ...87-289,303-305 
  Composer.tsx     |   94.54 |    66.66 |     100 |   94.54 | ...-76,88,143,158 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |   11.28 |      100 |       0 |   11.28 | 71-598            
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   81.27 |    69.23 |      50 |   81.27 | ...06,245,267-272 
  ...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.69 |    67.61 |     100 |   79.69 | ...17,520,523-529 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   86.26 |     83.3 |      80 |   86.26 | ...2231,2252,2348 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.88 |    96.03 |   46.15 |   95.88 | ...20,523-527,530 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   85.22 |    74.17 |     100 |   85.22 | ...1042,1098,1100 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |   16.66 |      100 |       0 |   16.66 | 14-56             
  ...onsDialog.tsx |    2.13 |      100 |       0 |    2.13 | 62-133,148-1004   
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |    8.57 |      100 |       0 |    8.57 | 24-55,58-134      
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |   21.42 |      100 |       0 |   21.42 | 13-39             
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.55 |    73.89 |   69.23 |   71.55 | ...1252,1258-1259 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-171             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.9 |    86.88 |     100 |    93.9 | ...20,282,302-304 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   95.62 |    87.09 |     100 |   95.62 | ...24-125,273-275 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   58.69 |    70.24 |    62.5 |   58.69 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |     100 |    81.81 |     100 |     100 | 82                
  ...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 |   45.51 |    70.53 |   60.86 |   45.51 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |    9.77 |      100 |       0 |    9.77 | 27-166            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...ackground-view |   85.86 |     85.1 |   92.98 |   85.86 |                   
  ...sksDialog.tsx |   82.66 |    83.09 |   85.71 |   82.66 | ...1854,1977-1983 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |    50.7 |    52.38 |   20.83 |    50.7 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.24 |      100 |       0 |    9.24 | 40-67,70-163      
 ...mponents/hooks |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.51 |    87.35 |   85.71 |   90.51 |                   
  ...orMessage.tsx |     100 |      100 |     100 |     100 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   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.51 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.85 |    88.38 |   93.75 |   93.85 | ...1051,1096-1098 
 ...ponents/shared |   86.52 |    82.35 |   86.72 |   86.52 |                   
  ...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 |   90.37 |    82.85 |   18.18 |   90.37 | ...60-63,65,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 |    3.96 |      100 |       0 |    3.96 |                   
  ...gerDialog.tsx |    3.96 |      100 |       0 |    3.96 | 79-137,140-681    
 ...ents/subagents |   30.87 |        0 |       0 |   30.87 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   10.95 |      100 |       0 |   10.95 | ...1,56-57,60-102 
 ...bagents/create |    9.13 |      100 |       0 |    9.13 |                   
  ...ionWizard.tsx |    7.28 |      100 |       0 |    7.28 | 34-299            
  ...rSelector.tsx |   14.75 |      100 |       0 |   14.75 | 26-85             
  ...onSummary.tsx |    4.26 |      100 |       0 |    4.26 | 27-331            
  ...tionInput.tsx |    8.63 |      100 |       0 |    8.63 | 23-177            
  ...dSelector.tsx |   33.33 |      100 |       0 |   33.33 | 20-21,26-27,36-63 
  ...nSelector.tsx |    37.5 |      100 |       0 |    37.5 | 20-21,26-27,36-58 
  ...EntryStep.tsx |   12.76 |      100 |       0 |   12.76 | 34-78             
  ToolSelector.tsx |    4.16 |      100 |       0 |    4.16 | 31-253            
 ...bagents/manage |    21.6 |    59.52 |   27.27 |    21.6 |                   
  ...ctionStep.tsx |   10.25 |      100 |       0 |   10.25 | 21-103            
  ...eleteStep.tsx |   20.93 |      100 |       0 |   20.93 | 23-62             
  ...tEditStep.tsx |   25.53 |      100 |       0 |   25.53 | ...2,37-38,51-124 
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |   13.72 |      100 |       0 |   13.72 | 18-73             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   86.01 |    81.62 |   86.48 |   86.01 |                   
  ...ewContext.tsx |   87.56 |       80 |      75 |   87.56 | ...37-240,246-256 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 237-238           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.45 |    73.87 |   95.45 |   88.45 |                   
  ...ui-adapter.ts |   88.45 |    73.87 |   95.45 |   88.45 | ...81,799-800,886 
 src/ui/editors    |   93.33 |    85.71 |   66.66 |   93.33 |                   
  ...ngsManager.ts |   93.33 |    85.71 |   66.66 |   93.33 | 49,63-64          
 src/ui/hooks      |   85.97 |     83.9 |   87.81 |   85.97 |                   
  ...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 |   86.79 |    71.86 |   83.33 |   86.79 | ...1529,1558-1562 
  ...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.41 |    82.08 |   66.66 |   92.41 | ...12,514-515,670 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      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.23 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |   11.62 |      100 |       0 |   11.62 | 44-87             
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |    87.4 |    84.04 |   78.26 |    87.4 | ...5817-5819,5821 
  ...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 |   85.29 |    80.28 |    92.3 |   85.29 | ...36,351-361,441 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.13 |     86.9 |     100 |   89.13 | ...61-463,496-506 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |    95.4 |    77.77 |     100 |    95.4 | 133-134,236-241   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.19 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.79 |    85.33 |   94.73 |   82.79 | ...86-688,696-732 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.32 |    93.93 |     100 |   97.32 | ...18-422,518-525 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |    79.2 |    35.29 |     100 |    79.2 | ...15-116,120-121 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |   91.25 |    89.47 |     100 |   91.25 |                   
  ...AppLayout.tsx |   90.99 |     87.5 |     100 |   90.99 | 61-63,111-116,152 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   93.56 |    86.19 |     100 |   93.56 |                   
  screen-buffer.ts |   94.73 |    66.66 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   93.81 |     92.1 |     100 |   93.81 | ...1,45-46,99-100 
  ...tion-state.ts |     100 |      100 |     100 |     100 |                   
  ...ction-text.ts |   93.85 |    93.44 |     100 |   93.85 | 30-34,130-131     
  ...selection.tsx |   91.88 |    78.57 |     100 |   91.88 | ...16-417,446-447 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   87.73 |    85.82 |   96.06 |   87.73 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   80.07 |     75.6 |     100 |   80.07 | ...70,274,332-333 
  ...wnDisplay.tsx |   92.87 |     93.5 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   93.63 |    81.77 |   95.23 |   93.63 | ...47-750,803-808 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |    52.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.61 |    93.27 |     100 |   98.61 | 189,217-218,424   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.21 |     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.65 |     100 |     100 | 45,151            
  historyUtils.ts  |   96.07 |     97.1 |     100 |   96.07 | 104-107           
  ...mage-parts.ts |   97.75 |    94.59 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   91.33 |    79.03 |     100 |   91.33 | ...73,273,277-278 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   83.24 |    80.12 |     100 |   83.24 | ...02-624,755-756 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   95.19 |      100 |   88.88 |   95.19 | 121-126           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...ize-reflow.ts |     100 |     92.3 |     100 |     100 | 57,62,209,217,347 
  ...wOptimizer.ts |     100 |    94.73 |     100 |     100 | 35,78             
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   98.71 |    95.72 |     100 |   98.71 | 292-293,478-479   
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   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       
  windowTitle.ts   |   96.55 |    94.73 |     100 |   96.55 | 56-57             
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |     60.1 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    51.35 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.24 |    79.78 |   81.69 |   81.24 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   92.25 |    89.67 |   96.39 |   92.25 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.14 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  ...y-identity.ts |   87.06 |    81.91 |     100 |   87.06 | ...70-371,378-379 
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 50-52,58          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.81 |    94.69 |     100 |   97.81 | ...03,420-421,466 
  ...projection.ts |   95.27 |    95.58 |     100 |   95.27 | 140-145           
  jsonc-editor.ts  |   93.18 |    92.66 |     100 |   93.18 | ...80-381,384-385 
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   86.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...-part-list.ts |     100 |      100 |     100 |     100 |                   
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  shell-args.ts    |     100 |      100 |     100 |     100 |                   
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       90 |     100 |     100 | 23                
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   94.35 |    94.11 |     100 |   94.35 |                   
  cleanup.ts       |   92.59 |    93.75 |     100 |   92.59 | ...02-205,209-211 
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  throttledOnce.ts |   95.95 |    93.93 |     100 |   95.95 | 77-78,153-154     
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   88.52 |    87.04 |   90.25 |   88.52 |                   
 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.24 |    84.51 |   94.55 |   90.24 |                   
  ...transcript.ts |   88.49 |    84.09 |     100 |   88.49 | ...32,640,646-650 
  ...ent-resume.ts |   85.64 |       78 |    85.1 |   85.64 | ...1793-1797,1800 
  ...ound-tasks.ts |   95.19 |    90.75 |   96.42 |   95.19 | ...1889,1897-1898 
  forkedAgent.ts   |   93.18 |    83.47 |   94.44 |   93.18 | ...90,698,703-710 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.27 |    88.23 |   98.33 |   95.27 | ...1478,1492-1494 
  ...w-snapshot.ts |   75.73 |    72.22 |    87.5 |   75.73 | ...21,445,452-454 
  worktree-pin.ts  |     100 |    88.23 |     100 |     100 | 78,99             
 src/agents/arena  |   76.96 |    68.22 |   78.94 |   76.96 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.91 |     65.2 |   78.57 |   75.91 | ...1888,1894-1895 
  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.07 |    85.19 |   76.12 |   78.07 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   90.87 |    85.24 |   93.18 |   90.87 | ...83,685,687-688 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   93.21 |    87.65 |   91.18 |   93.21 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   90.27 |    80.44 |   80.95 |   90.27 | ...2525,2571-2573 
  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.38 |      100 |    92.3 |   98.38 | 85-86             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   92.78 |    78.12 |     100 |   92.78 | ...49-150,192-194 
  ...ta-literal.ts |   95.96 |    92.63 |     100 |   95.96 | ...78-379,395-396 
  ...chestrator.ts |   93.87 |    90.47 |   91.48 |   93.87 | ...2216,2309-2312 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   95.47 |    83.47 |   94.44 |   95.47 | ...44,312,332-335 
  ...ow-sandbox.ts |   96.91 |    91.02 |     100 |   96.91 | ...1704,1710-1711 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 170-171,270       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   84.25 |    85.18 |   91.03 |   84.25 |                   
  TeamManager.ts   |   77.21 |    83.04 |   83.87 |   77.21 | ...1832,1855-1856 
  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.29 |       83 |     100 |   89.29 | ...1000,1044-1045 
  team-events.ts   |   73.68 |      100 |   66.66 |   73.68 | 140-144,151-155   
  teamHelpers.ts   |   91.71 |    94.44 |      95 |   91.71 | ...18-319,355-365 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   95.06 |    95.16 |   98.21 |   95.06 |                   
  ...on-harness.ts |   96.49 |       85 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |     100 |    96.77 |     100 |     100 | 158,167           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   85.57 |    87.79 |   77.53 |   85.57 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |    84.1 |    87.09 |   75.28 |    84.1 | ...8990,8997-8998 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  models.ts        |     100 |      100 |     100 |     100 |                   
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  storage.ts       |   96.02 |    93.38 |   89.28 |   96.02 | ...18-719,722-723 
 ...nfirmation-bus |   98.27 |    97.22 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.14 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.76 |    88.56 |   93.79 |   92.76 |                   
  ...on-restore.ts |   88.23 |    85.41 |     100 |   88.23 | ...60,63-64,67-68 
  baseLlmClient.ts |    88.4 |    83.68 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |    92.7 |    88.26 |   91.11 |    92.7 | ...4351,4449-4450 
  ...tGenerator.ts |   87.45 |    88.09 |   88.88 |   87.45 | ...08-509,554-560 
  ...lScheduler.ts |   89.82 |    84.83 |   94.73 |   89.82 | ...6483,6511-6527 
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  geminiChat.ts    |   95.19 |    90.72 |   96.69 |   95.19 | ...5651,5696-5697 
  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 | 46-47             
  output-styles.ts |     100 |      100 |     100 |     100 |                   
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.98 |    96.96 |     100 |   98.98 | 109               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.89 |    91.66 |      85 |   93.89 | ...1272,1475-1476 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    91.89 |     100 |     100 | 87,122-139        
  ...-arguments.ts |     100 |      100 |     100 |     100 |                   
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 83-87             
  ...allIdUtils.ts |   98.81 |    91.22 |     100 |   98.81 | 43,52             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   99.19 |    94.48 |     100 |   99.19 | 698-699,768       
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.59 |    89.11 |   97.43 |   96.59 |                   
  ...tGenerator.ts |   97.67 |    88.91 |   97.43 |   97.67 | ...1497,1526,1537 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1334,1555-1557 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   89.24 |    72.72 |   94.11 |   89.24 |                   
  ...tGenerator.ts |   87.54 |    71.42 |   93.75 |   87.54 | ...93-294,356-362 
  index.ts         |     100 |    85.71 |     100 |     100 | 51                
 ...ntentGenerator |   96.65 |     91.3 |   95.23 |   96.65 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   96.59 |    90.75 |      95 |   96.59 | ...1299-1300,1328 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   92.18 |    90.84 |   96.58 |   92.18 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.26 |    89.67 |   96.87 |   91.26 | ...1948,2117-2132 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   68.25 |    82.35 |      50 |   68.25 | 44-53,74-78,90-94 
  ...tGenerator.ts |      70 |    73.33 |     100 |      70 | ...07-112,121-127 
  pipeline.ts      |   95.36 |    91.52 |     100 |   95.36 | ...1433-1434,1541 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.11 |    92.25 |     100 |   92.11 | ...21-522,542-545 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |    97.2 |    91.81 |   98.63 |    97.2 |                   
  dashscope.ts     |   98.42 |    95.27 |   96.55 |   98.42 | ...51-752,894-895 
  deepseek.ts      |   95.23 |    89.79 |     100 |   95.23 | ...49-150,163-164 
  default.ts       |   98.87 |       96 |     100 |   98.87 | 178,304           
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |      90 |    76.31 |     100 |      90 | ...,72-73,173-175 
 src/extension     |   88.71 |    86.07 |   93.41 |   88.71 |                   
  ...ive-safety.ts |   97.77 |    93.75 |     100 |   97.77 | 100-101           
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...redentials.ts |   95.33 |    89.47 |     100 |   95.33 | ...21-122,173-175 
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   92.82 |    89.27 |    98.3 |   92.82 | ...1641-1647,1691 
  ...ionManager.ts |   84.52 |    83.52 |      83 |   84.52 | ...3139,3177-3178 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.71 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |    92.7 |     87.7 |     100 |    92.7 | ...1340-1341,1351 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |    90.16 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.54 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.33 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 ...ent-plugins-v1 |   84.94 |    79.51 |     100 |   84.94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  manifest.ts      |   81.87 |    84.48 |     100 |   81.87 | ...55-156,161-174 
  mcp.ts           |   84.98 |    79.56 |     100 |   84.98 | ...88-389,419-420 
  paths.ts         |     100 |    94.44 |     100 |     100 | 59                
  skills.ts        |   82.31 |    63.88 |     100 |   82.31 | ...38-141,150-151 
 src/followup      |   84.72 |    81.87 |   86.84 |   84.72 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   76.36 |     70.4 |   58.33 |   76.36 | ...42-743,750-751 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   86.11 |    87.17 |     100 |   86.11 | ...39-244,356-358 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   92.88 |    89.34 |   94.65 |   92.88 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |    91.17 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  ...ion-prompt.ts |   89.13 |    83.33 |     100 |   89.13 | 52-56             
  goal-evidence.ts |   88.54 |    87.98 |   97.67 |   88.54 | ...1200,1223-1226 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...87,190,194-196 
  ...ersistence.ts |   87.36 |    85.71 |    87.5 |   87.36 | ...53-154,185-190 
  goal-protocol.ts |   96.87 |    95.65 |     100 |   96.87 | 215-216           
  goal-reducer.ts  |   95.25 |    92.82 |   97.29 |   95.25 | ...73,552,570-571 
  goal-runtime.ts  |   96.38 |    89.73 |   95.83 |   96.38 | ...1349-1350,1480 
  goal-tools.ts    |   98.38 |    94.17 |   95.83 |   98.38 | ...05-206,307-308 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    93.02 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.35 |   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.09 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.67 |   66.49 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |    72.22 |   95.65 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |    81.81 |   21.05 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.48 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.71 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   88.97 |    85.08 |   91.31 |   88.97 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 135,145           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   93.82 |    84.09 |     100 |   93.82 | 78-83,122,154-157 
  ...entPlanner.ts |   91.55 |    76.74 |     100 |   91.55 | ...05,118-121,296 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   90.16 |    78.76 |   94.44 |   90.16 | ...06,629,642-648 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |   78.51 |    83.16 |   77.77 |   78.51 | ...1487,1500-1502 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |    83.33 |     100 |   90.47 | 50-51             
  ...yDiscovery.ts |   93.42 |    90.72 |     100 |   93.42 | ...11,370,592-595 
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    86.79 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   86.86 |    86.23 |   92.85 |   86.86 | ...33-538,571-582 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.2 |    85.71 |     100 |    93.2 | ...45-146,148-149 
  remember.ts      |   98.88 |    90.19 |     100 |   98.88 | 50,70             
  scan.ts          |   93.75 |       80 |     100 |   93.75 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   76.89 |    74.07 |   72.22 |   76.89 | ...47-451,454,460 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |    85.71 |     100 |     100 | 27                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |     79.1 |   81.81 |   81.21 | ...66-280,294-299 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.82 |    89.74 |   91.35 |   92.82 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   79.43 |    68.96 |   85.71 |   79.43 | ...,89-96,131-142 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,262           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1407,1436-1437 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.18 |   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.74 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.07 |   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.78 |    78.34 |   81.25 |   83.78 |                   
  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.91 |    73.48 |   78.26 |   75.91 | ...74-475,503-504 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   98.04 |    91.66 |   63.63 |   98.04 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 81-83,86-88,90-93 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  moonshot.ts      |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.36 |    78.59 |   95.94 |   85.36 |                   
  ...tGenerator.ts |    98.6 |    98.14 |     100 |    98.6 | 103-104           
  qwenOAuth2.ts    |   82.79 |    73.45 |    90.9 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |     76.8 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |    90.6 |    86.32 |   96.78 |    90.6 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   98.48 |    87.28 |     100 |   98.48 | 81-82,105,474-475 
  branch-points.ts |     100 |    95.23 |     100 |     100 | ...20,211,224,327 
  ...ionService.ts |   97.72 |    96.53 |     100 |   97.72 | ...1081,1224-1232 
  ...ingService.ts |   92.43 |    87.75 |   94.73 |   92.43 | ...2843,2858-2859 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.23 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   95.52 |    90.99 |     100 |   95.52 | ...37,346-347,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |   74.75 |    70.76 |   96.07 |   74.75 | ...2296,2325-2326 
  ...on-service.ts |   86.58 |    74.39 |     100 |   86.58 | ...56-460,498-499 
  ...references.ts |   98.57 |    91.42 |     100 |   98.57 | 156-157,217-218   
  ...ionService.ts |   98.26 |    97.23 |     100 |   98.26 | ...65-866,889-890 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |   97.22 |    90.99 |     100 |   97.22 | ...55-456,609-610 
  ...ttachments.ts |   97.74 |     90.9 |     100 |   97.74 | 298-308,646       
  ...pi-history.ts |   98.94 |    88.88 |     100 |   98.94 | 43                
  ...ersistence.ts |   91.67 |    80.64 |     100 |   91.67 | ...1062-1063,1091 
  ...tory-state.ts |     100 |       95 |     100 |     100 | 31                
  ...on-service.ts |   94.49 |     92.3 |   97.22 |   94.49 | ...98-600,656-664 
  ...pr-service.ts |   96.22 |    89.13 |     100 |   96.22 | 90-93             
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...n-registry.ts |   98.73 |    96.29 |     100 |   98.73 | 584,638-639,692   
  ...ken-counts.ts |     100 |       96 |     100 |     100 | 58                
  ...ipt-reader.ts |    93.7 |    91.22 |    97.8 |    93.7 | ...2791-2792,2869 
  ...turn-state.ts |   94.11 |     90.9 |   91.66 |   94.11 | 108-112,129-130   
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   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 |   89.61 |    87.01 |    93.4 |   89.61 | ...3013,3027-3047 
  sessionTitle.ts  |   96.35 |    79.71 |     100 |   96.35 | ...08-311,342-343 
  ...ContextEnv.ts |     100 |    94.73 |     100 |     100 | 76,111            
  ...ionService.ts |   84.43 |    78.45 |   97.18 |   84.43 | ...2496,2502-2507 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...Estimation.ts |     100 |    94.11 |     100 |     100 | 118               
  ...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.76 |    84.07 |     100 |   90.76 | ...10-513,565-566 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   88.36 |     87.7 |     100 |   88.36 | ...48-449,465-466 
 ...icrocompaction |   98.91 |    95.08 |     100 |   98.91 |                   
  microcompact.ts  |   98.91 |    95.08 |     100 |   98.91 | ...60,769,778-779 
 ...s/visionBridge |    98.8 |    92.12 |     100 |    98.8 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.77 |    86.05 |   94.73 |   89.77 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |    87.69 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   86.09 |    85.64 |   86.11 |   86.09 | ...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.07 |     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     |   88.56 |    89.42 |    98.3 |   88.56 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   85.51 |    86.52 |   97.43 |   85.51 | ...1583,1660-1661 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   82.55 |    84.83 |   85.71 |   82.55 |                   
  ...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 |   80.71 |    81.91 |   79.16 |   80.71 | ...92,499-501,517 
  ...attributes.ts |   96.98 |    91.37 |     100 |   96.98 | ...47-348,366-367 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.38 |    83.33 |      50 |   65.38 | ...08-109,112-113 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |    99.02 |     100 |     100 | 106               
  ...ai-request.ts |   87.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.12 |    96.03 |      95 |   99.12 | 150,379-380       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.73 |    78.01 |   66.66 |   60.73 | ...1507,1524-1544 
  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      |   93.95 |    86.44 |      75 |   93.95 | ...41,483-484,500 
  sdk.ts           |    82.7 |     90.9 |   66.66 |    82.7 | ...00-204,242-264 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ion-events.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   91.17 |    88.72 |    97.5 |   91.17 | ...1920,1949-1952 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   83.26 |    95.68 |   86.36 |   83.26 | ...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.38 |    98.64 |   84.09 |   96.38 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |      80 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   87.25 |    85.68 |   90.06 |   87.25 |                   
  ...erQuestion.ts |   89.71 |    81.13 |    92.3 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.72 |    91.48 |   83.33 |   89.72 | ...06-307,318-325 
  cron-create.ts   |   90.64 |     93.1 |      75 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   85.71 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.45 |   88.88 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    85.71 |    90.9 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.88 |   82.35 |   82.76 | ...45-746,865-915 
  ...r-worktree.ts |   83.14 |    68.42 |   88.88 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |       84 |      90 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |     83.8 |   94.73 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.71 |   86.36 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    78.12 |   91.66 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.11 |    83.33 |   85.71 |   94.11 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |     93.1 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.54 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.9 |    90.9 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.06 |    80.15 |   85.71 |   82.06 | ...3234,3236-3237 
  mcp-client.ts    |   86.08 |     87.5 |   93.93 |   86.08 | ...2483,2487-2490 
  ...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.5 |    93.93 |     100 |    97.5 | 178-179           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   97.95 |    92.37 |     100 |   97.95 | ...1161,1216-1217 
  ...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.39 |   82.35 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.61 |    87.5 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  readManyFiles.ts |   95.79 |    81.35 |     100 |   95.79 | ...10,563,573-577 
  ...d-artifact.ts |   85.68 |    81.59 |   94.73 |   85.68 | ...1071,1095-1096 
  ...t-shutdown.ts |    87.2 |    86.66 |   77.77 |    87.2 | ...,75-79,162-165 
  ripGrep.ts       |    94.6 |    87.34 |   95.45 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |      80 |    89.74 |   66.66 |      80 | ...59-265,333-340 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.96 |    84.29 |      93 |   78.96 | ...5036,5111-5112 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.75 |   83.33 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   80.43 |    86.95 |   85.71 |   80.43 | ...67,121,125-132 
  task-stop.ts     |   93.14 |    96.29 |    87.5 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.87 |     86.5 |   92.85 |   82.87 | ...54-564,588-599 
  team-create.ts   |   97.24 |    86.36 |   85.71 |   97.24 | 48-49,129-130     
  team-delete.ts   |   86.74 |    84.61 |   85.71 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.96 |   81.81 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  ...repeat-key.ts |     100 |      100 |     100 |     100 |                   
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   80.35 |    81.52 |   85.71 |   80.35 | ...1017,1025-1026 
  ...-finalizer.ts |    98.1 |     92.3 |   93.33 |    98.1 | ...34-235,237-241 
  ...iagnostics.ts |   99.06 |    97.69 |   91.66 |   99.06 | 133-134,205       
  ...-retention.ts |     100 |    95.83 |     100 |     100 | 116               
  tool-search.ts   |   96.19 |    89.79 |   93.75 |   96.19 | ...09,259-264,426 
  tool-utils.ts    |   97.46 |    96.55 |     100 |   97.46 | 26-27             
  tools.ts         |   92.93 |    92.18 |      92 |   92.93 | ...64-565,581-587 
  truncation.ts    |   90.61 |    90.35 |     100 |   90.61 | ...53-461,498-504 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   87.06 |    85.71 |   89.47 |   87.06 | ...29-832,869-904 
  zoom-image.ts    |   95.76 |    93.93 |    90.9 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.49 |    88.65 |   89.56 |   87.49 |                   
  agent.ts         |   86.18 |    87.83 |   87.36 |   86.18 | ...4385,4419-4429 
  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 |                   
 ...tools/workflow |   88.32 |    86.77 |   81.48 |   88.32 |                   
  workflow.ts      |   88.32 |    86.77 |   81.48 |   88.32 | ...35,780,782-783 
 src/utils         |   92.75 |    89.76 |    96.8 |   92.75 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |      95 |     92.7 |     100 |      95 | ...49-550,657-661 
  auth-type.ts     |     100 |      100 |     100 |     100 |                   
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.79 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.89 |    94.11 |      95 |   95.89 | ...99-500,512-525 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |     100 |    97.14 |      95 |     100 | 79,86             
  ...qwen-model.ts |     100 |      100 |     100 |     100 |                   
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   88.92 |    93.08 |      68 |   88.92 | ...92,394,410-411 
  fetch.ts         |   90.68 |    82.63 |     100 |   90.68 | ...72,483-484,503 
  ...ng-options.ts |     100 |      100 |     100 |     100 |                   
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.79 |    92.16 |   96.29 |   94.79 | ...2076,2084-2085 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  git-ignore.ts    |     100 |      100 |     100 |     100 |                   
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.83 |    82.35 |    87.5 |   78.83 | ...22-123,164-215 
  github-prs.ts    |   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.08 |    93.47 |     100 |   95.08 | ...62-166,234-238 
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  is-tool.ts       |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   96.15 |    93.51 |     100 |   96.15 | ...86-387,429-432 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...-constants.ts |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...tProcessor.ts |   94.01 |    89.88 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.18 |     100 |   98.96 | 154               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   90.88 |    90.66 |     100 |   90.88 | ...28-629,631-633 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  ...s-liveness.ts |     100 |    93.47 |     100 |     100 | 62,72,108         
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.36 |     100 |   96.98 | ...87-688,763-764 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...72,563-564,582 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |   97.77 |    91.48 |     100 |   97.77 | 172-173           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.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 |       90 |     100 |     100 | 95                
  ...orageUtils.ts |   96.21 |    85.47 |     100 |   96.21 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.37 |    88.59 |     100 |   86.37 | ...2361,2368-2372 
  ...lAstParser.ts |    98.3 |    91.59 |     100 |    98.3 | ...1340-1342,1352 
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |    57.14 |     100 |   77.77 | 44,54-59          
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminal-env.ts  |      50 |      100 |       0 |      50 | 18-19             
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...error-type.ts |     100 |      100 |     100 |     100 |                   
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ultCleanup.ts |   54.62 |    57.14 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.34 |    96.55 |     100 |   96.34 | ...35-340,342-347 
  ...pt-records.ts |   87.61 |    86.23 |     100 |   87.61 | ...80-484,514-529 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...-directory.ts |    83.7 |    80.95 |    87.5 |    83.7 | ...37-238,252-253 
  ...ifact-path.ts |   94.11 |    92.85 |     100 |   94.11 | 32-33             
  ...aceContext.ts |   95.39 |    89.47 |     100 |   95.39 | ...16-317,321-322 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.75 |   94.78 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.86 |      90 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |    92.3 |      100 |   88.88 |    92.3 |                   
  ...ageFormats.ts |   81.81 |      100 |   66.66 |   81.81 | 56-61             
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
-------------------|---------|----------|---------|---------|-------------------

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

The leaf was validated but the path walked to reach it was not, which left
the whole landing relocatable by a single symlink.

mkdirSync(recursive) follows symlinks in every component ABOVE the final
one, and lstat refuses to follow only the final one — so a leaf-only check
cannot see a redirected parent. Planting `audits` needs one `ln -s` and no
race, because ~/.qwen exists long before `audits` does: the leaf is then
created inside the planter's directory, reports as a perfectly real
directory, passes the contents check, and every artifact written "into the
landing" lands wherever the link points. Probed against the built module:
before, the landing resolved inside the planted directory and a written
report appeared there; after, the call refuses by name and the planter's
directory stays empty.

Each component this method creates is now created non-recursively and
adopted only after its own lstat — recursive creation is precisely what
walks a planted component unchecked. QWEN_HOME itself stays unvalidated: it
is the user's own configured location, not a path this method invents.

Also closes the unknown-dirent-type gap in the contents check: on a
filesystem that does not report entry types, isSymbolicLink() and isFile()
both answer false, so an entry slipped past every arm; those entries now get
an explicit lstat.
@wenshao

wenshao commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator Author

The blocker is real and is fixed at aab0887eb1 — thank you, this was the right catch and I had the containment claim wrong.

Reproduced first, against the built module rather than a transcription. With audits planted as a symlink before the first run, getAuditFallbackDir('/any/project') returned without throwing, the landing resolved inside the planted directory, and a report written "into the landing" appeared in the planter's directory:

threw: null
landing realpath: …/probe-attacker-yqajJ1/39ba6d9d…
ESCAPED into attacker dir: true
attacker dir now holds: [ '39ba6d9d…', '39ba6d9d…/report.md' ]

Your analysis of why the leaf check cannot see it is exactly right: lstat refuses to follow only the final component, so the redirected leaf reports as a real directory and the contents check passes on it too. And the no-race point holds — ~/.qwen exists long before audits does, so planting it is one ln -s.

The fix walks every component this method creates. Each is now created non-recursively and adopted only after its own lstatrecursive: true is precisely what walks a planted component unchecked, so it had to go rather than gain a check around it. The same probe against the built module after the fix:

threw: audit: the audit artifact directory …/audits is not a directory (it may be a symlink planted ahead of the run) — remove it and re-run.
landing: null
attacker dir contents: []
ESCAPED: false

QWEN_HOME itself is deliberately left unvalidated, and the code now says so: it is the user's own configured location, not a path this method invents. If you would rather it were validated too, say so and I will — I read it as the user's own choice rather than something planted.

A regression test plants the parent and asserts both the refusal and that nothing was created inside the planted directory. It is discriminating: reverting to the old recursive-mkdir-plus-leaf-lstat shape turns it red while the other 74 stay green.

The non-blocking dirent observation is in too. On a filesystem that does not report entry types, isSymbolicLink() and isFile() both answer false and the entry slipped past every arm of the contents check silently. Unknown-type entries now get an explicit lstat before the symlink and hardlink arms.

On the CI note: the Ubuntu leg's earlier failure was infrastructure, not this branch — the self-hosted runner …-18 could not clear its own workspace (EACCES … rmdir .qwen/tmp/review-pr-9748-scratch-verify-…/probe-ws/.qwen/tmp/review-pr-666), and feat/review-coverage-ledger failed at the identical step on the identical runner and path. It passed on a re-run that landed elsewhere; the residue on that runner is still there and will keep hitting whatever is scheduled onto it.

@wenshao

wenshao commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

@qwen-code-dev-bot qwen-code-dev-bot added the autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+) label Aug 23, 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-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.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

中文说明

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.test.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.test.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts Outdated
Comment on lines +413 to +414
if (process.platform !== 'win32' && (stat.mode & 0o077) !== 0) {
fs.chmodSync(dir, 0o700);

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] On Windows, adoption applies zero privacy enforcement: this mode-repair branch is gated off (process.platform !== 'win32') and has no ACL counterpart, so a pre-existing audits or landing directory is adopted with whatever DACL it carries, while on POSIX the same pre-existing component is tightened to 0700. assertAuditLandingIsClean never inspects the directory's own permissions. This contradicts the unconditional docstring purpose ("0700 so the quoted … content stays private to the user"). The comment argues only that the POSIX check cannot run on Windows — not that win32 adoption is privacy-safe.

Modeled probe (win32 gate spoofed on Linux — real Windows not exercised): a planted 0777 component is adopted silently, mode intact (auditsMode=777), while the POSIX arm tightens it to 700. Concretely: on a shared Windows host/CI runner where another principal can write into QWEN_HOME, that principal pre-creates the fully predictable audits/<sha256(root)> with a permissive DACL (e.g. Everyone:Read); adoption passes on isDirectory() alone, and once the audit writer exists the quoted module content is written into a directory readable by the other principal.

Node exposes no portable ACL API, so the cheap safe option is to refuse adoption of pre-existing components on win32 — in the EEXIST branch, when process.platform === 'win32', throw the existing "remove it and re-run" error instead of adopting an unverified pre-existing directory (the method created nothing in that case, so refusal costs only the planted/legacy directory).

中文说明

[Suggestion] 在 Windows 上,采纳不施加任何隐私强制:本模式修复分支被门控关闭(process.platform !== 'win32')且没有 ACL 对应物,因此已存在的 audits 或落点目录会带着其既有 DACL 被采纳;而在 POSIX 上同样的已存在组件会被收紧为 0700assertAuditLandingIsClean 也从不检查目录自身的权限。这与无条件的 docstring 目的(「0700 以使被引用的内容仅属主可见」)相悖。注释只论证了 POSIX 检查在 Windows 上无法运行,并未论证 win32 采纳在隐私上是安全的。

模型化探针(在 Linux 上伪造 win32 门控——未跑真实 Windows):植入的 0777 组件被静默采纳、模式原样保留(auditsMode=777),而 POSIX 分支将其收紧为 700。具体地:在另一个主体可写入 QWEN_HOME 的共享 Windows 主机/CI runner 上,该主体可预建完全可预测的 audits/<sha256(root)> 并赋宽松 DACL(如 Everyone:Read);采纳仅凭 isDirectory() 通过,一旦审计写入方落地,被引用的模块内容就会被写进其他主体可读的目录。

Node 没有可移植的 ACL API,因此廉价而安全的选项是在 win32 上拒绝采纳已存在组件——在 EEXIST 分支,当 process.platform === 'win32' 时抛出既有的「移除后重跑」错误,而不是采纳未经验证的已存在目录(此时方法什么都没创建,拒绝的代价只是那个植入/遗留目录)。

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

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.

Declined as proposed, with the limitation documented instead. Refusing adoption of pre-existing components on win32 would also refuse this tool's OWN landings from previous runs — the landing is deliberately reused across runs (the report and its sidecar are the durable artifacts), and on Windows nothing distinguishes self-created from planted. The effect would be every second /audit run per project failing forever with "remove it and re-run", breaking the reuse contract this same file argues for. Instead the mode-repair comment now states the win32 truth plainly: an adopted component keeps whatever DACL it had, since Node exposes no portable ACL enforcement. If a maintainer wants a stronger win32 guarantee anyway, a creation marker (written when this tool creates a component, required for adoption) could distinguish self-created landings — say the word and I will implement it.

中文说明

按提议的方案予以拒绝,改为如实记录该限制。在 win32 上拒绝采纳已存在组件,会同时拒绝本工具此前运行自建的落点——落点是刻意跨运行复用的(报告及其 sidecar 是持久产物),而 Windows 上无法区分自建与植入。其后果将是每个项目每隔一次 /audit 运行就永远失败并提示「移除后重跑」,打破同一文件为之辩护的复用契约。因此改为在模式修复注释中如实写明 win32 现状:已存在组件保留其既有 DACL,因为 Node 没有可移植的 ACL 强制。若维护者仍希望更强的 win32 保证,可以用创建标记(本工具创建组件时写入、采纳时要求存在)来区分自建落点——如有指示,乐意实现。

@qwen-code-dev-bot

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

Copy link
Copy Markdown
Collaborator

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

中文说明

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

Adoption now normalizes the full mode — a 0300 plant kept owner write
and blinded the content check while writes still succeeded — and an
unlistable landing fails closed instead of skipping validation. The
landing is refused before creation when QWEN_HOME resolves inside the
audited repository, a missing QWEN_HOME base is created instead of
throwing ENOENT, and the mutating getter is renamed to
ensureAuditFallbackDir so the filesystem side effect is visible.
@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 轮)。改动内容与我反驳保留之处如下:

Feedback dispositions

  • [rc:3838295036] (Critical) — FIXED. Reproduced first against the current sources: a 0300-planted landing was adopted with no error (leafModeAfter: 300), and a write into it followed the planted symlink child into the attacker's directory (contentLandedInAttackerDir: true). Both layers are fixed: adoption now normalizes the FULL mode to 0700 on POSIX (a missing owner-read bit is repaired, not just loose group/other bits), and an unlistable landing now fails closed with a "could not be listed for validation" error instead of skipping validation. After the fix the same probe throws contains a symlink (audit-2026-01-01.sidecar). Two regression tests pin it: a planted-0300 landing (asserts the repair to 0700 AND the symlink refusal) and an unlistable-landing test.
  • [rc:3838295042] (Suggestion) — FIXED. Added adopts a pre-existing loose-mode directory and tightens it to 0700: pre-creates audits at 0755 (chmod, so umask cannot pre-tighten it) and asserts adoption repairs it to 0700. Mutation-verified: deleting the repair chmod turns this test red (probe P6).
  • [rc:3838295043] (Suggestion) — FIXED. Added falls back to lstat when a dirent arrives untyped: the file-wide fs mock now also covers readdirSync, and the test stubs one call to return a dirent whose isSymbolicLink()/isFile()/isDirectory() all answer false while a real symlink exists on disk, then expects contains a symlink. Mutation-verified: removing the DT_UNKNOWN lstatSync fallback turns it red (probe P3).
  • [rc:3838295044] (Suggestion) — FIXED (rename option). getAuditFallbackDir is renamed to ensureAuditFallbackDir, matching the getProjectTempDir / ensureProjectTempDirExists precedent so the filesystem side effect is visible in the name. Kept to a rename rather than splitting out a pure getter: a pure helper with zero callers would be dead code, and the reviewer offered the rename as sufficient.
  • [rc:3838295046] (Suggestion) — FIXED. The five early-return tests now use the house it.skipIf(process.platform === 'win32') convention, so Windows reports them as skipped instead of falsely passed. The 0700 test stays cross-platform with its existing conditional assertions, as the finding allows.
  • [rc:3838295051] (Suggestion) — FIXED. The adoptDirectory docstring no longer claims an ownership check; it now states exactly what happens: a real directory (not a symlink), tightened to 0700 on POSIX, ownership itself not checked.
  • [rc:3838295052] (Suggestion) — FIXED. Reproduced: with QWEN_HOME inside the audited repo the landing resolved inside the working tree (insideRepo: true). The method now refuses before creating anything when the landing resolves inside the project root, using the file's existing isPathWithinDirectory helper (which realpath-resolves through existing ancestors). Error message directs the user to point QWEN_HOME outside the repository. Regression test asserts the refusal AND that nothing was created inside the repo.
  • [rc:3838295056] (Suggestion) — FIXED. Reproduced: a not-yet-existing QWEN_HOME threw ENOENT: no such file or directory, mkdir '<QWEN_HOME>/audits'. The base is now created recursively before the two adoptDirectory calls — it is declared outside the validation model, so this weakens none of the symlink checks on the two validated components, and it matches every other writer under the global dir. Regression test added.
  • [rc:3838295059] (Suggestion) — DECLINED with reason (thread left open, reply posted). Refusing adoption of pre-existing components on win32 would refuse the tool's OWN landings from previous runs — the landing is reused across runs, and on Windows nothing distinguishes self-created from planted — so every second /audit run per project would fail forever with "remove it and re-run". That breaks the documented reuse contract the same file argues for. Instead the win32 limitation is now documented honestly in the mode-repair comment (adopted components keep their existing DACL; Node exposes no portable ACL enforcement). If a maintainer wants stronger win32 guarantees, a creation marker could distinguish self-created landings — happy to implement on request.
  • [rv:5001776146] (CHANGES_REQUESTED, against commit 94f4457) — ALREADY FIXED at the round-2 head. The audits-parent symlink arm was closed by aab0887eb1 ("validate every component of the fallback landing path"), as confirmed in [ic:5384950999]. Re-verified this round: the existing refuses an audits PARENT planted as a symlink test is green, and the per-component non-recursive adoption walks both audits and the leaf.
  • [rv:5002193765] Test Plan path note — NOT ACTIONABLE in this mode, flagged for maintainer. The note is about the PR body's Reviewer Test Plan, which address-review rounds cannot edit (the workflow consumes no PR-body output here and this agent has no GitHub write access). For what it is worth, src/config/storage.test.ts is the package-relative path used by this repository's own AGENTS.md convention for single-test runs (cd packages/core && npx vitest run src/config/storage.test.ts); the checker appears to resolve it against the repo root. The full path is packages/core/src/config/storage.test.ts.

Changes

  • ensureAuditFallbackDir (renamed from getAuditFallbackDir): refuses in-repo landings before creation; creates a missing QWEN_HOME base recursively; docstring now says "Create or adopt" and scopes the 0700 promise to POSIX.
  • adoptDirectory: normalizes the full mode to 0700 (not just group/other bits); docstring no longer overclaims ownership; comment documents the win32 DACL limitation.
  • assertAuditLandingIsClean: fails closed when the landing cannot be listed.
  • Tests: five early-return tests converted to it.skipIf; readdirSync added to the file-wide fs mock; six new tests (missing base, in-repo refusal, 0755 repair, 0300 repair + planted symlink, unlistable landing, untyped dirent).

Mutation probes (each new guard witnessed)

  • P1: revert mode normalization to the old group/other-only check → 0300 test RED; restored → GREEN.
  • P2: revert fail-closed readdir to fail-open return → unlistable test RED; restored → GREEN.
  • P3: delete the DT_UNKNOWN lstatSync fallback → untyped-dirent test RED; restored → GREEN.
  • P4: delete the in-repo containment check → in-repo test RED; restored → GREEN.
  • P5: delete the base mkdirSync → missing-base test RED; restored → GREEN.
  • P6: delete the mode-repair chmodSync entirely → loose-mode test RED; restored → GREEN.
  • Bite simulation: this round's test file run against the PRE-round sources fails 18 tests (not all-green), so the regression tests demonstrably bite.

Verification

  • Repro probes (tsx, before fix): F1 threw: none, leafModeAfter: 300, contentLandedInAttackerDir: true; F7 insideRepo: true; F8 ENOENT ... mkdir '<QWEN_HOME>/audits' — all three defect claims reproduced.
  • Repro probes (after fix): F1 throws contains a symlink; F7 throws resolves inside the audited project root; F8 returns the landing — all closed.
  • npx vitest run src/config/storage.test.ts — 78 passed, 3 failed; all 15 ensureAuditFallbackDir tests green. The 3 failures (getGlobalSettingsPath, getUserCommandsDir, getMcpOAuthTokensPath) are pre-existing environmental failures from this runner's QWEN_HOME/HOME pollution — reproduced identically with the pre-round baseline files swapped in.
  • npm run test --workspace @qwen-code/qwen-code-core -- --changed origin/main — the 12 failing files (logger, ide-client, token-storage, oauth, skill-manager, etc.) are all os.homedir()/QWEN_HOME-dependent path tests; swapping in the pre-round baseline sources reproduces the same failures (e.g. logger 31, installationManager 2, storage 3), so they are environmental, not caused by this round.
  • npm run build — passed.
  • npm run typecheck — passed.
  • npm run lint — passed.
  • npx prettier --check on both changed files — passed.
  • No settings source changed → generate:settings-schema not applicable. No bundled-CLI-only behavior changed (the helpers have no production callers yet) → integration tests not applicable.
中文说明

反馈处置

  • [rc:3838295036](Critical)— 已修复。 先对当前源码复现:以 0300 模式植入的落点被无错采纳(leafModeAfter: 300),向其中的写入顺着植入的符号链接子项落进了攻击者目录(contentLandedInAttackerDir: true)。两层均已修复:采纳时现在会把完整模式归一为 0700(POSIX 下,缺失的属主读位也会被修复,而不只是清 group/other 位);无法列目录的落点现在以「could not be listed for validation」错误失败即关闭,不再跳过校验。修复后同一探针抛出 contains a symlink (audit-2026-01-01.sidecar)。新增两个回归测试锁定:植入 0300 的落点(同时断言修复为 0700 与符号链接被拒)以及不可列目录的落点测试。
  • [rc:3838295042](Suggestion)— 已修复。 新增 adopts a pre-existing loose-mode directory and tightens it to 0700:先以 0755 预建 audits(用 chmod,避免 umask 提前收紧),再断言采纳后被修复为 0700。已做变异验证:删除修复用 chmod 后该测试变红(探针 P6)。
  • [rc:3838295043](Suggestion)— 已修复。 新增 falls back to lstat when a dirent arrives untyped:文件级 fs mock 现在也覆盖 readdirSync;测试将某次调用打桩为返回 isSymbolicLink()/isFile()/isDirectory() 全为 false 的 dirent,而磁盘上该名字是真实符号链接,然后断言 contains a symlink。已做变异验证:删除 DT_UNKNOWN 的 lstatSync 兜底后该测试变红(探针 P3)。
  • [rc:3838295044](Suggestion)— 已修复(采用重命名方案)。 getAuditFallbackDir 重命名为 ensureAuditFallbackDir,对齐 getProjectTempDir / ensureProjectTempDirExists 先例,使文件系统副作用在方法名上可见。只做重命名而不拆出纯 getter:零调用方的纯助手是死代码,且反馈本身已说明重命名即可。
  • [rc:3838295046](Suggestion)— 已修复。 五个提前 return 的测试改用项目惯用的 it.skipIf(process.platform === 'win32'),Windows 上将报告 skipped 而非假通过。0700 测试按反馈允许保留其跨平台条件断言。
  • [rc:3838295051](Suggestion)— 已修复。 adoptDirectory 的 docstring 不再声称有属主检查;现在如实描述:真实目录(非符号链接)、POSIX 下收紧为 0700、不检查属主。
  • [rc:3838295052](Suggestion)— 已修复。 已复现:QWEN_HOME 位于被审计仓库内时,落点解析进工作树(insideRepo: true)。现在当落点解析进项目根时,方法在创建任何内容之前即拒绝,复用文件内现成的 isPathWithinDirectory 助手(它会穿过已存在的祖先做 realpath 解析)。错误信息指引用户把 QWEN_HOME 指向仓库外。回归测试同时断言拒绝行为与仓库内未创建任何内容。
  • [rc:3838295056](Suggestion)— 已修复。 已复现:尚不存在的 QWEN_HOME 会抛 ENOENT: no such file or directory, mkdir '<QWEN_HOME>/audits'。现在在两次 adoptDirectory 调用之前递归创建基目录——基目录本就被声明在校验模型之外,因此不削弱两个受校验组件上的符号链接检查,并与全局目录下其他所有写入者一致。已补回归测试。
  • [rc:3838295059](Suggestion)— 附理由拒绝(线程保持打开,已回帖)。 在 win32 上拒绝采纳已存在组件会连带拒绝本工具前几轮运行自建落点——落点是跨运行复用的,而 Windows 上无法区分自建与植入——于是每个项目隔一次 /audit 运行就会永远失败并提示「移除后重跑」,打破了同一文件为之辩护的复用契约。改为在模式修复注释中如实记录 win32 限制(已存在组件保留其既有 DACL;Node 没有可移植的 ACL 强制)。若维护者希望更强的 win32 保证,可以用创建标记区分自建落点——如有需要乐意实现。
  • [rv:5001776146](CHANGES_REQUESTED,针对提交 94f4457)— 已在二轮头部修复。 audits 父目录符号链接这一攻击面已由 aab0887eb1(「validate every component of the fallback landing path」)关闭,见 [ic:5384950999] 的确认。本轮再次验证:既有测试 refuses an audits PARENT planted as a symlink 为绿,逐组件非递归采纳会分别校验 audits 与叶子。
  • [rv:5002193765] Test Plan 路径提示 — 本模式无法处理,转维护者。 该提示针对 PR 正文的 Reviewer Test Plan,address-review 轮无法编辑(工作流在此不消费 PR 正文输出,且本代理无 GitHub 写权限)。供参考:src/config/storage.test.ts 是本仓库 AGENTS.md 自身约定的单测试运行所用的包内相对路径(cd packages/core && npx vitest run src/config/storage.test.ts),检查器似乎按仓库根解析。完整路径为 packages/core/src/config/storage.test.ts

改动

  • ensureAuditFallbackDir(由 getAuditFallbackDir 重命名):创建前拒绝仓库内落点;缺失的 QWEN_HOME 基目录递归创建;docstring 改为「Create or adopt」,并把 0700 承诺限定于 POSIX。
  • adoptDirectory:把完整模式归一为 0700(而非仅 group/other 位);docstring 不再过度承诺属主;注释记录 win32 DACL 限制。
  • assertAuditLandingIsClean:落点无法列目录时失败即关闭。
  • 测试:五个提前 return 的测试转换为 it.skipIf;文件级 fs mock 增加 readdirSync;新增六个测试(缺失基目录、仓库内拒绝、0755 修复、0300 修复+植入符号链接、不可列目录落点、无类型 dirent)。

变异探针(每个新防御均有见证)

  • P1:把模式归一回退为旧的仅 group/other 检查 → 0300 测试变红;恢复 → 绿。
  • P2:把失败即关闭的 readdir 回退为敞开的 return → 不可列目录测试变红;恢复 → 绿。
  • P3:删除 DT_UNKNOWN 的 lstatSync 兜底 → 无类型 dirent 测试变红;恢复 → 绿。
  • P4:删除仓库内容纳检查 → 仓库内测试变红;恢复 → 绿。
  • P5:删除基目录 mkdirSync → 缺失基目录测试变红;恢复 → 绿。
  • P6:整体删除模式修复 chmodSync → 宽松模式测试变红;恢复 → 绿。
  • Bite 模拟:本轮测试文件对轮前源码运行失败 18 例(并非全绿),证明回归测试确有辨别力。

验证

  • 复现探针(tsx,修复前):F1 threw: none, leafModeAfter: 300, contentLandedInAttackerDir: true;F7 insideRepo: true;F8 ENOENT ... mkdir '<QWEN_HOME>/audits' —— 三项缺陷主张全部复现。
  • 复现探针(修复后):F1 抛 contains a symlink;F7 抛 resolves inside the audited project root;F8 正常返回落点 —— 全部关闭。
  • npx vitest run src/config/storage.test.ts — 78 通过、3 失败;ensureAuditFallbackDir 全部 15 个测试为绿。3 个失败(getGlobalSettingsPathgetUserCommandsDirgetMcpOAuthTokensPath)是本 runner QWEN_HOME/HOME 污染导致的既有环境性失败——换入轮前基线文件后同样复现。
  • npm run test --workspace @qwen-code/qwen-code-core -- --changed origin/main — 12 个失败文件(logger、ide-client、token-storage、oauth、skill-manager 等)全部是依赖 os.homedir()/QWEN_HOME 的路径测试;换入轮前基线源码后复现相同失败(如 logger 31、installationManager 2、storage 3),故为环境问题,与本轮改动无关。
  • npm run build — 通过。
  • npm run typecheck — 通过。
  • npm run lint — 通过。
  • 对两个改动文件运行 npx prettier --check — 通过。
  • 未改动设置源 → 无需 generate:settings-schema。未改动仅经捆绑 CLI 暴露的行为(这些助手尚无生产调用方)→ 无需集成测试。

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.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

中文说明

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
@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 轮)。改动内容与我反驳保留之处如下:

Round summary — PR #9776 (audit fallback landing)

One commit: fix(core): close audit landing race seams with re-validation (#9776) (+189/−11 across packages/core/src/config/storage.ts and its test). No conflict resolution was needed (--conflict false).

Feedback dispositions

[rc:3838796976] Critical — check→mkdir race on the QWEN_HOME tail — RESOLVED

Reproduced first: a deterministic test injects the attack at the exact seam (the mkdirSync(baseDir) call plants the not-yet-existing QWEN_HOME tail as a symlink into the audited repo, as a same-UID process would). On the pre-round code the method returned a landing whose realpath is inside the repo — no throw.

Fix: the containment check is re-run immediately after the base creation, when baseDir exists and the predicate realpath-resolves it, exactly as suggested. The test also asserts nothing was created inside the working tree.

[rc:3838796985] Critical — audits swapped between the two adoption checks — RESOLVED

Reproduced first: a deterministic test swaps audits for a symlink into the audited repo at the leaf-creation seam (the window between the first and second adoptDirectory); a second test swaps the leaf itself at the content-check seam (the "one step later" variant from the finding). On the pre-round code both returned successfully with the landing relocated.

Fix: the method re-validates the full path before returning — it re-runs adoptDirectory on audits and on the leaf (reuse of the existing validation: lstat-refuses a swapped component and refuses non-directories) and re-runs the containment check now that every component exists, catching a swapped ancestor the lstats cannot see.

Scope note: a swap landing after this final re-validation remains possible — the irreducible TOCTOU tail the finding itself names, fully closable only by fd-relative creation (O_NOFOLLOW | O_DIRECTORY + mkdirat), which Node.js does not expose. The implemented shape matches the finding's suggested fix (whose own measurements show the same residual tail): in-window swaps now surface as explicit refusals instead of silent relocation, so the method fails closed.

[rc:3838796987] Suggestion — bare Error for user-actionable refusals — RESOLVED

Verified by reading errors.ts and handleCriticalError in packages/cli/src/cli.ts: a bare Error prints "An unexpected critical error occurred:" with a stack and exits 1. All five refusals (containment, not-a-directory, unlistable landing, symlink child, hardlinked file) now throw FatalConfigError — the class this file already uses for the same failure class (assertPathWithinDirectory, getPlansDir) — printing the actionable message cleanly and exiting with the scriptable code 52. FatalConfigError was already imported.

[rc:3838796990] Suggestion — raw ENOTDIR pre-empts the actionable diagnostic — RESOLVED

Reproduced first: with audits planted as a regular file, the pre-round code threw the raw ENOTDIR: not a directory, lstat '…' instead of the actionable adoption message the round-1 anchor produced.

Fix: the containment check is wrapped (extracted into assertAuditLandingIsOutsideRepo, shared by all three call sites); a resolution failure falls through to the component checks instead of escaping as a raw errno — a path whose component is not a directory cannot resolve to a usable landing, and adoption surfaces the state with its actionable message. The friendly message is restored and the containment refusal still fires.

[rv:5002654243] CHANGES_REQUESTED — "Test Plan (not a blocker): src/config/storage.test.ts — no such file or directory" — REFUTED, no code action

The file exists at packages/core/src/config/storage.test.ts (1108 lines; verified in this checkout), and the focused vitest run passes 87/87. The ENOENT comes from running the relative path without the packages/core prefix: the command is cd packages/core && npx vitest run src/config/storage.test.ts. The review marks this note as non-blocking; there is nothing to change in code, and the PR body is not editable in this mode.

Mutation probes (each new guard witnessed)

Probe Mutation Result
0 Pre-round source (HEAD) against the new tests 6 failed / 81 passed — all new tests reproduce the filed defects
1 Remove the post-mkdir containment re-check 1 failed — QWEN_HOME-tail race test
2 Remove the pre-return re-adoption of audits 1 failed — audits-race test
3 Remove the pre-return re-adoption of the leaf 1 failed — leaf-race test
4 Remove the resolution-failure fall-through wrapper 1 failed — audits-as-file test
5 FatalConfigError reverted to bare Error 2 failed — both error-class tests
Restored fixed source 87/87 passed

Verification

  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0)
  • npm run lint (repo-wide eslint . --ext .ts,.tsx + integration-tests) — passed (exit 0)
  • npx eslint packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts — passed (exit 0)
  • cd packages/core && env -u QWEN_HOME npx vitest run src/config/storage.test.ts — 87 passed (87)
  • cd packages/core && npx vitest run src/config/ (with the sandbox's ambient QWEN_HOME) — 683 passed / 3 failed; the 3 failures are pre-existing environment-dependent storage tests that assume QWEN_HOME is unset (they fail identically on the pre-round commit and pass with the variable unset). Note on the sandbox: the harness exports QWEN_HOME to isolate its own state, and the real home directory is root-owned, so the two suites need opposite settings of that variable here; CI is unaffected (the feedback's failed-checks sections are empty).
  • Integration tests after npm run bundle — not run: ensureAuditFallbackDir has no production callers yet (it is staged for the coming /audit wiring), so nothing exercises this behavior through the bundled CLI or integration harness; unit coverage is exhaustive.
  • npm run generate:settings-schema — not run: no settings source changed.

Diff growth this round: source net +45 / test +144 lines.

中文说明

本轮摘要 — PR #9776(审计落备落点)

单次提交:fix(core): close audit landing race seams with re-validation (#9776)packages/core/src/config/storage.ts 及其测试共 +189/−11)。无需冲突解决(--conflict false)。

反馈处置

[rc:3838796976] Critical — QWEN_HOME 末端的「检查→mkdir」竞争 — 已解决

先复现:确定性测试在精确缝隙处注入攻击(在 mkdirSync(baseDir) 调用时,把尚不存在的 QWEN_HOME 末端植入为指向被审计仓库的符号链接,模拟同 UID 进程的行为)。在本轮之前的代码上,方法返回了一个 realpath 位于仓库内部的落点——没有抛出。

修复:在基础目录创建之后立即重跑封闭性检查——此时 baseDir 已存在,谓词会对其做 realpath 解析,与建议完全一致。测试还断言工作树内部没有创建任何东西。

[rc:3838796985] Critical — 两次采纳检查之间 audits 被交换 — 已解决

先复现:确定性测试在叶子创建缝隙处(第一次与第二次 adoptDirectory 之间的窗口)把 audits 换为指向被审计仓库的符号链接;第二个测试在内容检查缝隙处交换叶子本身(即发现中「其后一步」的变体)。在本轮之前的代码上,两者都在落点被搬迁的情况下成功返回。

修复:方法在返回前重新校验完整路径——对 audits 与叶子重跑 adoptDirectory(复用既有校验:lstat 拒绝被交换的组件、拒绝非目录),并在所有组件已存在时重跑封闭性检查,以捕获 lstat 看不到的、被交换的祖先组件。

范围说明:在最终复核之后发生的交换仍然可能——这是发现本身指明的不可约 TOCTOU 尾部,只有通过相对文件描述符的创建(O_NOFOLLOW | O_DIRECTORY + mkdirat)才能完全闭合,而 Node.js 不暴露该能力。实现的形态与发现建议的修复一致(其自身的测量也显示存在同样的残余尾部):窗口内的交换现在表现为显式拒绝而非静默搬迁,方法失败即关闭。

[rc:3838796987] Suggestion — 用户可处置的拒绝抛出裸 Error — 已解决

通过阅读 errors.tspackages/cli/src/cli.ts 中的 handleCriticalError 核实:裸 Error 会打印「An unexpected critical error occurred:」加堆栈并以 1 退出。五处拒绝(封闭性、非目录、无法列出、符号链接子项、硬链接文件)现在都抛 FatalConfigError——本文件对同一失败类别已在使用的类(assertPathWithinDirectorygetPlansDir)——干净地打印可照做的消息,并以脚本可分支的退出码 52 退出。FatalConfigError 此前已被导入。

[rc:3838796990] Suggestion — 裸 ENOTDIR 抢占了可照做的诊断 — 已解决

先复现:当 audits 被植入为普通文件时,本轮之前的代码抛出裸 ENOTDIR: not a directory, lstat '…',而不是第一轮锚点对同一状态给出的可照做的采纳消息。

修复:封闭性检查被包装(提取为 assertAuditLandingIsOutsideRepo,三个调用点共享);解析失败不再以裸 errno 逃逸,而是穿透到组件检查——组件不是目录的路径不可能解析为可用落点,采纳检查会以可照做的消息呈现该状态。友好消息恢复,且封闭性拒绝仍然触发。

[rv:5002654243] CHANGES_REQUESTED — 「Test Plan(非阻断):src/config/storage.test.ts — no such file or directory」 — 已证伪,无代码动作

该文件存在于 packages/core/src/config/storage.test.ts(1108 行;已在当前检出中核实),聚焦 vitest 运行 87/87 通过。ENOENT 源于在未带 packages/core 前缀的情况下运行相对路径:正确命令是 cd packages/core && npx vitest run src/config/storage.test.ts。该评审将此条标注为非阻断;代码中无可改动之处,且本模式下无法编辑 PR 正文。

变异探针(每个新防线均有见证)

探针 变异 结果
0 本轮之前的源码(HEAD)运行新测试 6 失败 / 81 通过 —— 全部新测试复现了所申报的缺陷
1 移除 mkdir 之后的封闭性复核 1 失败 —— QWEN_HOME 末端竞争测试
2 移除返回前对 audits 的重新采纳 1 失败 —— audits 竞争测试
3 移除返回前对叶子的重新采纳 1 失败 —— 叶子竞争测试
4 移除解析失败穿透包装 1 失败 —— audits 为文件的测试
5 FatalConfigError 还原为裸 Error 2 失败 —— 两个错误类测试
恢复修复后的源码 87/87 通过

验证

  • npm run build — 通过(退出码 0)
  • npm run typecheck — 通过(退出码 0)
  • npm run lint(全仓库 eslint . --ext .ts,.tsx + integration-tests)— 通过(退出码 0)
  • npx eslint packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts — 通过(退出码 0)
  • cd packages/core && env -u QWEN_HOME npx vitest run src/config/storage.test.ts — 87 通过(87)
  • cd packages/core && npx vitest run src/config/(带沙箱环境自带的 QWEN_HOME)— 683 通过 / 3 失败;这 3 个失败是既有的、依赖环境的 storage 测试,它们假定 QWEN_HOME 未设置(在本轮之前的提交上同样失败,去掉该变量后通过)。沙箱说明:本运行环境导出 QWEN_HOME 以隔离自身状态,且真实家目录属主为 root,因此这两个测试套件在此需要该变量的相反设置;CI 不受影响(反馈中失败检查部分为空)。
  • npm run bundle 之后的集成测试 — 未运行:ensureAuditFallbackDir 尚无生产调用方(为即将到来的 /audit 接线而预备),没有任何行为经由打包后的 CLI 或集成测试装置被执行;单元覆盖已完备。
  • npm run generate:settings-schema — 未运行:未改动任何 settings 源。

本轮差异增长:源码净 +45 / 测试 +144 行。

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.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:482 — [review] both vanished-entry continue branches untested — mutating each to throw keeps 87/87 green (deferred by the code-age rule: anchored on code unchanged since the round-2 head)

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

中文说明

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

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

Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.test.ts
Comment thread packages/core/src/config/storage.test.ts
@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-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.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:356 — [review] Design doc promises mkdtemp semantics; code delivers a predictable reused landing
  • packages/core/src/config/storage.ts:350 — [review] Hand-rolled realpath duplicates realpathNearestExisting
  • packages/core/src/config/storage.test.ts:737 — [probe] No test pins that the landing ignores runtime-base redirection
  • packages/core/src/config/storage.ts:483 — [probe] Both vanished-entry catch-continue branches untested
  • packages/core/src/config/storage.ts:383 — [probe] QWEN_HOME existing as/traversing a regular file -> raw errno escape
  • packages/core/src/config/storage.ts:356 — [review] Design doc mentions QWEN_RUNTIME_DIR; code honors only QWEN_HOME
  • packages/core/src/config/storage.ts:402 — [probe] Final re-validation never re-runs the content check
  • packages/core/src/config/storage.ts:446 — [probe] adoptDirectory's chmodSync unguarded — raw EPERM on unowned component
中文说明

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts Outdated
Comment thread packages/core/src/config/storage.test.ts
Comment thread packages/core/src/config/storage.test.ts

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows.

Not explored to full depth (tool budget reached): "agent 4": none — nothing was cut short..

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.test.ts:23 — [probe] Default mockReaddirSync forces { withFileTypes: true }, hiding a production-option mutation
  • packages/core/src/config/storage.test.ts:1056 — [probe] Untyped-dirent fallback test covers only the symlink shape; the stat?.isDirectory()/stat?.isFile() disjuncts survive mutation
  • packages/core/src/config/storage.ts:432 — [probe] adoptDirectory's non-EEXIST mkdir failure escapes as a raw errno instead of the classified FatalConfigError
  • packages/core/src/config/storage.ts:386 — [probe] Base-creation catch's remediation text misdirects for EACCES/EROFS/ENOSPC — tells the operator to remove something that does not exist
  • packages/core/src/config/storage.ts:436 — [probe] adoptDirectory's post-mkdir lstatSync/chmodSync sit outside the try/catch — raw ENOENT escapes when a planter removes the component mid-window

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

中文说明

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

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows。

未探索到全部深度(达到工具调用预算):"agent 4"none — nothing was cut short.

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

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

Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.test.ts Outdated
@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 review round — PR #9776

Commit: da4d45a090fix(core): re-check landing contents in pre-return re-validation (#9776)

Feedback points and dispositions

[rv:5003994672] CHANGES_REQUESTED review body — Addressed via its inline findings

The review body itself carries disclosures (unreviewed macOS/Windows test runs) and an observation about findings recurring in storage.ts/storage.test.ts; its actionable content is the two Critical inline findings below, both now resolved in code. Its Test-Plan note (src/config/storage.test.ts — no such file or directory) is a path typo in the PR description's Test Plan: the file lives at packages/core/src/config/storage.test.ts and is run from inside packages/core (e.g. cd packages/core && npx vitest run src/config/storage.test.ts). The PR body cannot be edited from this checkout (no GitHub write access here), so the correction is recorded here.

The five items listed as "Deferred under the convergence posture (round 6, not a blocker)" were explicitly recorded-but-not-requested this round and were left untouched.

[rc:3840203224] Critical — pre-return re-validation never re-runs the content check — FIXED

Claim verified from source: the re-validation block re-ran both adoptions and the containment check but not assertAuditLandingIsClean(dir). Reproduced before fixing with a regression test that injects at the exact deterministic seam the reviewer named (the second mkdirSync(auditsDir) call, i.e. after the content check's readdir snapshot): against the unfixed code the method returned the landing holding the planted symlink child (test failed with "expected [Function] to throw an error"). Fix: re-run Storage.assertAuditLandingIsClean(dir) in the block, after the leaf re-adoption and before the final containment check. The block comment now lists the content re-check among what the re-validation covers, plus the pointer the reviewer asked for — the re-walk narrows but cannot close the TOCTOU tail of a path-returning API, so artifact writes must stay contained in the returned root. Mutation probe: deleting the new line makes the witness test fail; restoring it goes green. The witness test is committed with the fix, so it fails against the pre-round branch as the verification gate requires.

[rc:3840203230] Critical — socket test path exceeds AF_UNIX sun_path on every platform — FIXED

Claim reproduced on this runner with the test's exact path shape (os.tmpdir() + /qhXXXXXX + /audits/ + 64-hex leaf + 25-byte entry = 110 bytes): probe output bound: true / existsSync(full socketPath): false / readdir(leaf): ['2026-01-01-000000-mod.' isSocket=true] — libuv silently truncated the bind, so the test asserted refusal of a path that did not exist; on macOS the same construction fails bind() with ENAMETOOLONG. Fixed exactly as suggested: the test now plants a FIFO (spawnSync('mkfifo', …)), the identical untyped-dirent → special-file shape with no sockaddr length limit, keeping both refusal assertions and the win32 skip (mkfifo is unavailable there, same as before). The obsolete short-QWEN_HOME workaround and the net import (unused elsewhere in the file) were removed, so the fix is net-subtractive in the test file. The special-file refusal branch itself is unchanged and stays witnessed by this test.

No conflict resolution was needed (--conflict false); no merge was performed.

Verification

Commands actually run this round, in order:

  • npx vitest run src/config/storage.test.ts -t "planted after the content check snapshot" (packages/core, unfixed source) — 1 failed as expected (reproduction of rc:3840203224)
  • socket-path probe (node script replicating the test's exact path shape) — reproduced libuv truncation: bound: true, existsSync(full path): false, socket at truncated name (reproduction of rc:3840203230)
  • npx vitest run src/config/storage.test.ts (packages/core, fixed) — 93 passed (93)
  • Mutation probe: removed the new assertAuditLandingIsClean(dir) line, re-ran the witness test — failed; restored the line, re-ran the full file — 93 passed (93)
  • npm run buildpassed (exit 0)
  • npm run typecheckpassed (exit 0)
  • npm run lintpassed (exit 0)
  • npx prettier --check on both touched files — passed (CI runs Prettier as a separate Test-job step)
  • Full packages/core suite (npx vitest run) — 21037 passed, 107 failed; junit triage shows every failure is runner-environmental and unrelated to this PR: 91 fail on EACCES/ENOENT mkdir '/home/github-runner/.qwen' (this runner's real HOME is not writable; CI homes are), 7 editor tests fail because this runner is sandbox-detected, 5 worktree-sidecar integration tests and 4 workflow-snapshot tests fail on the same unwritable HOME. Grep confirms no failing file references the PR's new symbols (ensureAuditFallbackDir/assertAuditLanding*/adoptDirectory appear only in storage.ts/storage.test.ts). The same environmental split appears with ambient QWEN_HOME unset vs set; the focused storage file passes 93/93 without it.
  • Integration tests after npm run bundle — not run: the touched behavior is fully exercised by the unit suite, not only through the bundled CLI.
  • npm run generate:settings-schema — not run: no settings source changed.

CI failure notes (no GitHub credentials on this runner, so logs were unavailable; diagnosed from the workflow definition and local evidence):

  • Test (ubuntu-latest Node 22.x): this job is not just tests — it also runs lint guards, settings-schema freshness, helper-script tests, and npm run test:ci. The socket test passes on Linux (via the truncation accident, now fixed properly), and no code path in this PR is exercised by any locally failing test. All locally runnable equivalents of the job's steps pass here; the remaining failure cause is not identifiable from this runner and the workflow's independent CI remains the final gate.
  • web-shell E2E Smoke (ubuntu-latest Node 22.x): this PR touches only packages/core/src/config/storage.{ts,test.ts}; no web-shell code or dependency is in the diff, so this failure is not attributable to the PR from available evidence.
中文说明

Autofix 审查轮次 — PR #9776

提交:da4d45a090fix(core): re-check landing contents in pre-return re-validation (#9776)

反馈点与处置

[rv:5003994672] CHANGES_REQUESTED 审查正文 — 通过其行内发现项处置

审查正文本身只包含披露信息(未审查的 macOS/Windows 测试运行)以及关于发现反复出现在 storage.ts/storage.test.ts 中的观察;其可执行内容是下面两条 Critical 行内发现,均已在代码中解决。其 Test-Plan 备注(src/config/storage.test.ts — no such file or directory)是 PR 描述 Test Plan 中的路径笔误:文件实际位于 packages/core/src/config/storage.test.ts,需要在 packages/core 目录内运行(例如 cd packages/core && npx vitest run src/config/storage.test.ts)。本检出环境无 GitHub 写权限,无法编辑 PR 正文,故在此记录更正。

列为「在收敛姿态下延后(第 6 轮,非阻断)」的五条项目本轮明确为「已记录、不要求处理」,未做任何改动。

[rc:3840203224] Critical — 返回前重新校验从未重跑内容检查 — 已修复

从源码核实了该论断:重新校验块重跑了两次采纳与封闭性检查,却没有重跑 assertAuditLandingIsClean(dir)。修复前先用回归测试复现:在评审者指明的确定性缝隙(第二次 mkdirSync(auditsDir) 调用,即内容检查的 readdir 快照之后)注入——未修复代码直接返回了携带植入符号链接子项的落点(测试以 "expected [Function] to throw an error" 失败)。修复:在该块中、叶子重新采纳之后、最终封闭性检查之前,重跑 Storage.assertAuditLandingIsClean(dir)。块注释现在把内容复查列入重新校验的覆盖范围,并加入了评审者要求的指引——重走能缩小但无法关闭路径返回型 API 固有的 TOCTOU 尾部,因此产物写入自身必须保持在返回根目录之内。变异探针:删除新增行后见证测试失败;恢复后变绿。见证测试随修复一并提交,因此它在验证门禁所要求的轮前分支上会失败。

[rc:3840203230] Critical — socket 测试路径在所有平台都超过 AF_UNIX sun_path — 已修复

在本运行环境按该测试的确切路径形态复现了论断(os.tmpdir() + /qhXXXXXX + /audits/ + 64 位十六进制叶子 + 25 字节条目名 = 110 字节):探针输出 bound: true / existsSync(full socketPath): false / readdir(leaf): ['2026-01-01-000000-mod.' isSocket=true] —— libuv 静默截断了 bind,于是测试断言的是对一个根本不存在的路径的拒绝;同样的构造在 macOS 上会以 ENAMETOOLONG 使 bind() 失败。按建议修复:测试改为植入 FIFO(spawnSync('mkfifo', …)),同样是「无类型 dirent → 特殊文件」的形态且没有 sockaddr 长度限制,保留两条拒绝断言与 win32 跳过(mkfifo 在 win32 不可用,与之前一致)。废弃的短 QWEN_HOME 变通方案和 net 导入(文件中无其他使用处)被移除,因此该修复在测试文件中是净减少的。特殊文件拒绝分支本身未变,仍由该测试见证。

无需解决冲突(--conflict false);未执行任何合并。

验证

本轮实际运行的命令,按顺序:

  • npx vitest run src/config/storage.test.ts -t "planted after the content check snapshot"(packages/core,未修复源码)— 按预期失败 1 个(复现 rc:3840203224)
  • socket 路径探针(用测试的确切路径形态编写的 node 脚本)— 复现 libuv 截断:bound: trueexistsSync(完整路径): false、socket 落在截断后的名字上(复现 rc:3840203230)
  • npx vitest run src/config/storage.test.ts(packages/core,修复后)— 93 通过(93)
  • 变异探针:移除新增的 assertAuditLandingIsClean(dir) 行,重跑见证测试 — 失败;恢复该行,重跑整个文件 — 93 通过(93)
  • npm run build通过(exit 0)
  • npm run typecheck通过(exit 0)
  • npm run lint通过(exit 0)
  • 对两个改动文件运行 npx prettier --check通过(CI 在 Test 作业中将 Prettier 作为独立步骤运行)
  • packages/core 全套件(npx vitest run)— 21037 通过、107 失败;junit 分类显示所有失败均为运行环境问题、与本 PR 无关:91 个失败于 EACCES/ENOENT mkdir '/home/github-runner/.qwen'(本运行环境的真实 HOME 不可写;CI 的 HOME 可写),7 个 editor 测试因本环境被识别为沙箱而失败,5 个 worktree-sidecar 集成测试和 4 个 workflow-snapshot 测试同样失败于不可写的 HOME。Grep 确认没有任何失败文件引用本 PR 的新符号(ensureAuditFallbackDir/assertAuditLanding*/adoptDirectory 仅出现在 storage.ts/storage.test.ts 中)。无论环境 QWEN_HOME 是否设置都出现同样的环境性分裂;聚焦的 storage 文件在未设置时 93/93 全绿。
  • npm run bundle 之后的集成测试 — 未运行:改动的行为已由单元测试套件完整覆盖,并非只能通过捆绑后的 CLI 验证。
  • npm run generate:settings-schema — 未运行:未改动任何 settings 源。

CI 失败说明(本运行环境无 GitHub 凭据,无法获取日志;依据工作流定义与本地证据诊断):

  • Test (ubuntu-latest Node 22.x):该作业不只是测试——还包括 lint 门禁、settings-schema 新鲜度、辅助脚本测试和 npm run test:ci。socket 测试在 Linux 上通过(靠截断巧合,现已正确修复),且本 PR 中没有任何代码路径被本地失败的测试所覆盖。该作业各步骤在本地的可运行等价命令全部通过;从本运行环境无法确定剩余失败原因,工作流的独立 CI 仍是最终门禁。
  • web-shell E2E Smoke (ubuntu-latest Node 22.x):本 PR 只改动 packages/core/src/config/storage.{ts,test.ts};diff 中没有任何 web-shell 代码或依赖,因此从现有证据看该失败与本 PR 无关。

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

⚠️ The branch received new commits while this round ran; they were merged into this push, but this round's verification predates that merge — re-check anything that landed mid-run. · 本轮运行期间分支收到了新的提交;本次推送已将其合并,但本轮验证在合并之前完成——请复查运行期间落地的改动。

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.

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally on macOS.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally on Windows.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:455 — [probe] Mode normalization masks with 0o777 — planted setuid/setgid/sticky bits survive adoption
  • packages/core/src/config/storage.ts:540 — [probe] Hardlink refusal false-positives on hardlinking backup tools of the durable landing

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

中文说明

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

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally on macOS。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally on Windows。

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

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

Comment thread packages/core/src/config/storage.ts Outdated
)

The content check decided typed dirents' entry type from the readdir
snapshot while consulting a fresh lstat only for nlink, so a same-UID
swap of a listed entry for a symlink between the snapshot and the loop
passed every arm and returned a landing holding a symlink child. Lstat
every entry once and drive the symlink, directory, special-file, and
hardlink arms from that single fresh stat — the same single-stat shape
the unknown-dirent-type path already used, so the two paths no longer
disagree about what "validated" means.
@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 review round — PR #9776 (round 8)

One Critical inline finding this round; resolved in code with a witness test. All other feedback items were informational disclosures, reviewer-recorded deferrals explicitly not requested this round, or observations. No base-conflict merge was performed (--conflict false; the branch already carries origin/main from an earlier round).

Feedback points and decisions

[rc:3840755230] [Critical] — RESOLVED in code

Finding: the pre-return content check decides every entry type for typed dirents from the readdir snapshot taken at the top of the walk: the fresh lstatSync at the nlink arm is consulted only for .nlink (its type bits discarded), and typed directory children recurse with no lstat at all. A same-UID process can swap a listed regular file for a symlink between the snapshot and the loop reaching the entry, every arm then passes on the stale dirent, and the check returns a landing holding a symlink child — the exact escape the routine exists to prevent.

Reproduction (before any fix): added a deterministic witness test, refuses a listed file raced into a symlink inside the re-run content check. It seeds the landing with a regular report file, swaps that file for a symlink at the re-adoption mkdirSync seam (the same seam the round-6 race test uses), and feeds the re-run content check a snapshot whose dirent still says regular file. Run against the pre-fix code it FAILED with expected [Function] to throw an errorensureAuditFallbackDir returned the landing with the swapped symlink child in place. Defect reproduced.

Fix (minimal, root-cause): lstat every entry unconditionally and drive all four arms — symlink refusal, directory recursion, special-file refusal, hardlink refusal — from that single fresh stat. This removes the typed dirent-typing split and the second lstat at the nlink arm entirely: both dirent paths now share one meaning of "validated", which is also what the finding's suggested shape prescribed. Error messages unchanged. Net −8 source lines (subtractive). No new guards added, so nothing extra to witness beyond the behavior itself.

Mutation probe: negated the new symlink arm (if (stat.isSymbolicLink())if (false)) and re-ran the focused suite: the new witness test FAILED (plus its 5 sibling symlink tests, which share the guard), then restored the arm and re-ran to 94/94 green. The pre-fix failing run above is the same probe at full strength (guard removed entirely → test fails).

[rv:5004599342] review body — "Partially reviewed — gaps disclosed"

  • Not reviewed: macOS / Windows build-and-test jobs — informational disclosure of the reviewer's own coverage gaps (jobs skipped in CI, not run locally). Nothing actionable in code; the workflow's independent CI remains the final verification gate.

  • Test Plan note (not a blocker): src/config/storage.test.tsno such file or directory — the test plan path in the PR body is misnamed. The actual file is packages/core/src/config/storage.test.ts. Verified via grep that no committed artifact references the wrong path, so there is nothing to fix in code; the PR body itself is workflow-owned — flagged here so it can be corrected where it is rendered.

  • Deferred under the convergence posture (recorded, not requested this round):

    • storage.ts:455 — mode normalization masks with 0o777, so planted setuid/setgid/sticky bits survive adoption when the low bits already equal 0700.
    • storage.ts:540 — hardlink refusal false-positives on hardlinking backup tools of the durable landing.

    Disposition: recorded here, no code change this round, per the reviewer's explicit scoping. Both are in-footprint judgment calls (the first trades a normalization strictness question; the second trades the hardlink-escape defense against backup-tool usability) that the reviewer chose to defer; they remain open for a future round rather than being silently dropped.

  • Convergence observation (findings recurring on storage.ts) — observation only. Note that this round's fix removes the typed/untyped decision split that produced this finding as a sibling of the round-6 window: both dirent paths now decide from one fresh stat per entry, which eliminates the shared root cause of this family rather than patching another instance of it.

Changes

  • packages/core/src/config/storage.ts (+14/−22): the content-check loop now performs one fresh lstatSync per entry and drives the symlink, directory, special-file, and hardlink arms from that single stat; removed the stale-dirent typing branch and the duplicate nlink-arm lstat.
  • packages/core/src/config/storage.test.ts (+50): the witness test described above.

Commit: fix(core): drive landing content check from fresh per-entry lstat (#9776) (0859695).

Verification

  • npx vitest run src/config/storage.test.ts (in packages/core) — pre-fix BASE: 90 passed, new witness FAILED (defect reproduced), plus 3 unrelated failures caused by this runner exporting QWEN_HOME (they fail identically on unmodified HEAD; excluded below to measure code, not harness env). Post-fix with env -u QWEN_HOME: 94/94 passed. Stashed-HEAD baseline with env -u QWEN_HOME: 93/93 passed.
  • Mutation probe — negated stat.isSymbolicLink() to if (false): witness + 5 sibling symlink tests FAILED; restored: 94/94 green.
  • npm run build — passed.
  • npm run typecheck — passed (no TS errors).
  • npm run lint — passed.
  • npx prettier --check on the two touched files — clean.
  • Full packages/core suite (env -u QWEN_HOME npx vitest run) — 21220 passed; 109 failures in 7 files (agent-headless, workflow-snapshot, config, enter/exit-worktree.session.integ, editor, environmentContext.mcp-subagent) — verified pre-existing: the identical 109 failures reproduce on the stashed HEAD baseline; none of those files is touched by or related to this change (sandbox/editor/environment-dependent tests on this runner).
  • Integration tests — not applicable: ensureAuditFallbackDir is consumed only by these unit tests in this PR; the touched behavior is not exercised through the bundled CLI or integration harness.
  • npm run generate:settings-schema — not applicable: no settings source changed.
中文说明

Autofix 审查轮次 — PR #9776(第 8 轮)

本轮有一条 Critical 行内发现,已在代码中解决并附见证测试。其余反馈项均为信息披露、审查者明确记录为「本轮不要求修改」的延后项,或仅为观察。未执行 base 冲突合并(--conflict false;分支在早前轮次已并入 origin/main)。

反馈点与处置

[rc:3840755230] [Critical] — 已在代码中解决

发现: 返回前的内容检查对已定型的 dirent 仍以走查开始时 readdir 快照里的条目类型为准:nlink 分支处新做的 lstatSync 只读取 .nlink(类型位被丢弃),已定型的目录子项在完全不做 lstat 的情况下直接递归。同 UID 进程可以在快照之后、循环处理到该条目之前的窗口里把已列出的常规文件换成符号链接,此时所有分支都依据过期 dirent 通过,检查返回一个内含符号链接子项的落点——正是本例程要防止的逃逸。

复现(修复前): 新增确定性见证测试 refuses a listed file raced into a symlink inside the re-run content check:先在落点放入一个常规报告文件,在重新采纳(re-adoption)的 mkdirSync 缝隙处(与第 6 轮竞态测试相同的缝隙)把该文件换成符号链接,并给重跑的内容检查喂一个仍声称为常规文件的过期快照。在修复前代码上运行,该测试失败于 expected [Function] to throw an error —— ensureAuditFallbackDir 返回了仍含被换入符号链接子项的落点。缺陷复现成立。

修复(最小、根因): 对每个条目无条件执行 lstat,并让全部四个分支——符号链接拒绝、目录递归、特殊文件拒绝、硬链接拒绝——都依据这一个新鲜的 stat 判断。这同时彻底移除了 typed 定型分支与 nlink 分支处的第二次 lstat:两条 dirent 路径现在共享同一种「已校验」含义,也正是该发现建议的代码形态。错误消息不变。源码净 −8 行(消减式修改)。未新增任何守卫,因此除行为本身外无需额外见证。

变异探针: 将新的符号链接分支取反(if (stat.isSymbolicLink())if (false))后重跑聚焦测试:新见证测试失败(另有共享该守卫的 5 个兄弟符号链接测试一同失败);恢复后重跑,94/94 全绿。上述修复前的失败运行即是同强度的完整探针(守卫被整体移除 → 测试失败)。

[rv:5004599342] 审查正文 — 「部分审查,缺口已披露」

  • 未审查:macOS / Windows build-and-test 任务 —— 审查者自身覆盖缺口的信息披露(CI 中被跳过、未在本地运行)。代码层面无需处理;工作流的独立 CI 仍是最终验证关卡。

  • Test Plan 备注(非阻断):src/config/storage.test.tsno such file or directory —— PR 正文中测试计划的路径写错了,实际文件为 packages/core/src/config/storage.test.ts。已通过 grep 确认没有任何已提交的产物引用错误路径,因此代码中无可修改项;PR 正文本身由工作流管理,在此标注以便在其展示处更正。

  • 收敛姿态下延后(已记录,本轮不要求修改):

    • storage.ts:455 —— 模式归一化以 0o777 掩码判断,当低 9 位已等于 0700 时,被植入的 setuid/setgid/sticky 位会在采纳后幸存。
    • storage.ts:540 —— 硬链接拒绝会对持久落点的硬链接式备份工具产生误报。

    处置:在此记录,按审查者明确的范围界定本轮不做代码改动。两者都是落点范围内的取舍判断(前者涉及归一化严格程度的取舍;后者涉及硬链接逃逸防御与备份工具可用性之间的取舍),审查者选择延后;它们保持开放留待后续轮次,而非被静默丢弃。

  • 收敛观察(发现反复出现在 storage.ts —— 仅为观察。本轮修复恰好移除了产生本条发现(作为第 6 轮窗口的兄弟项)的定型/未定型判定分裂:两条 dirent 路径现在都以每条目一次新鲜 stat 做判断,消除的是这一族问题的共同根因,而不是再补一个实例。

变更内容

  • packages/core/src/config/storage.ts(+14/−22):内容检查循环现在对每个条目执行一次新鲜的 lstatSync,并由这一个 stat 驱动符号链接、目录、特殊文件、硬链接四个分支;移除了过期 dirent 定型分支与重复的 nlink 分支 lstat。
  • packages/core/src/config/storage.test.ts(+50):上述见证测试。

提交:fix(core): drive landing content check from fresh per-entry lstat (#9776)(08596953e6)。

验证

  • npx vitest run src/config/storage.test.ts(位于 packages/core)—— 修复前 BASE:90 通过,新见证测试失败(缺陷复现),另有 3 条与本 PR 无关的失败,由本运行器导出 QWEN_HOME 所致(在未修改的 HEAD 上同样失败;下方运行时排除该变量以度量代码而非运行器环境)。修复后以 env -u QWEN_HOME 运行:94/94 通过。以 env -u QWEN_HOME 运行的 stashed-HEAD 基线:93/93 通过。
  • 变异探针 —— 将 stat.isSymbolicLink() 取反为 if (false):见证测试及 5 个兄弟符号链接测试失败;恢复后 94/94 全绿。
  • npm run build —— 通过。
  • npm run typecheck —— 通过(无 TS 错误)。
  • npm run lint —— 通过。
  • 对两个改动文件运行 npx prettier --check —— 通过。
  • packages/core 全量测试(env -u QWEN_HOME npx vitest run)—— 21220 通过;7 个文件中 109 条失败(agent-headlessworkflow-snapshotconfigenter/exit-worktree.session.integeditorenvironmentContext.mcp-subagent)—— 已验证为既有失败:在 stash 后的 HEAD 基线上复现出完全相同的 109 条失败;这些文件均未被本次改动触及,也与改动无关(本运行器上的沙箱/编辑器/环境相关测试)。
  • 集成测试 —— 不适用:本 PR 中 ensureAuditFallbackDir 仅被这些单元测试消费;改动的行为不经由打包 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.

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally on macOS.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally on Windows.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:357 — [review] 'audits' hardcoded as a bare literal twice, against the file's named-constant convention
  • packages/core/src/config/storage.ts:507 — [probe] Vanished-entry continue branch exercised by no test — the continue→throw mutant survives the whole suite
  • packages/core/src/config/storage.ts:440 — [probe] adoptDirectory's post-mkdir lstatSync/chmodSync escape as raw errno in their own race windows instead of FatalConfigError
  • packages/core/src/config/storage.ts:438 — [probe] Non-EEXIST mkdirSync failure escapes raw — the same misconfiguration is classified or raw depending on whether the base dir exists
  • packages/core/src/config/storage.ts:521 — [probe] A directory child that vanishes between lstat and the recursive readdir aborts with a hard refusal, while the identical file-entry race is tolerated by the continue arm

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

中文说明

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

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally on macOS。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally on Windows。

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

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

Comment thread packages/core/src/config/storage.ts
Comment thread packages/core/src/config/storage.ts
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix round summary — PR #9776 (issue #9776)

Commit: fe77863b72fix(core): re-lstat audit landing after follow-based validation steps (#9776) (2 files, +151/−0)

Feedback points and decisions

[rc:3841965743] R8-1 — Critical: directory arm decides from a fresh lstat, then follows the re-resolved name — RESOLVED IN CODE

Reproduced first, per the source-blind rule: a new race test injects a deterministic seam at the recursive readdir of the FINAL content check, swapping a listed directory child for a symlink to a clean (empty) directory. On the unmodified code ensureAuditFallbackDir returns a landing still holding the symlink child — the test failed with expected [Function] to throw an error, matching the finding's BASE witness exactly.

Fix: the probe-verified narrowing suggested in the finding. After the recursion validates a directory child, the arm re-lstats the child and refuses when it is no longer a directory (a swap for a symlink-to-directory during the walk validated the link target); a child that vanished during the walk is skipped, mirroring the existing vanished-entry tolerance. The residual window shrinks to the documented post-return tail of a path-returning API. The O_NOFOLLOW/fd-relative class-closing alternative was not taken: it would rebuild the walk around a different fs surface than the suite's readdirSync seams and grow the diff far past the narrowing this round needs.

Witnesses: refuses a directory child swapped for a symlink inside the final content check (fails pre-fix, passes with the fix) and tolerates a directory child that vanishes during the final content check (pins the new vanished-child continue branch).

[rc:3841965757] R8-2 — Critical: pre-return re-validation runs the only non-following checks BEFORE the two follow-based checks — RESOLVED IN CODE

Reproduced first with two new race tests injecting at the SECOND content check, as the finding requested (the existing refuses a leaf raced into a symlink after its own adoption test injects at the first content check, where the re-adoption lstats still precede the swap). Arm A swaps the leaf for a symlink to an attacker directory; arm B swaps the audits parent, pre-creating the predictable leaf name inside the attacker directory so the follow-based checks pass instead of erroring. On the unmodified code both arms pass every check and the method returns a symlinked landing (both tests failed pre-fix), matching the finding's BASE witnesses.

Fix: the probe-verified suggestion — the two adoptDirectory calls re-run AFTER the final content and containment checks, so a swap landing inside either follow-based check is lstat-refused before return. Merely reordering clean/containment was not attempted, for the reason the finding states: both follow the root.

Witnesses: refuses a leaf raced into a symlink inside the final content check (arm A) and refuses audits raced into a symlink inside the final content check (arm B) — both fail pre-fix, pass with the fix.

[rv:5006087989] Review body — CHANGES_REQUESTED ("Partially reviewed — gaps disclosed") — ADDRESSED VIA THE INLINE FINDINGS

The actionable substance of the review is the two Criticals above; both are resolved in code. On the disclosed gaps:

  • The macOS/Windows build-and-test suites cannot run on this Linux runner; the workflow's CI remains the final gate for those platforms.
  • Test Plan note (src/config/storage.test.tsno such file or directory): the tests live at packages/core/src/config/storage.test.ts and ran green this round (98/98).

The five items listed under the convergence posture are recorded as deferred (not requested this round) and were left untouched, per critical-only mode. No code, threads, or replies were produced for them.

Mutation probes (each new guard/branch has its own witness)

  • Removed the post-recursion re-lstat guard → refuses a directory child swapped for a symlink inside the final content check FAILED, all others passed; restored → green.
  • Mutated the new vanished-child continue into a throw → tolerates a directory child that vanishes during the final content check FAILED; restored → green.
  • Removed the post-final-check re-adoptions → both "inside the final content check" arm tests FAILED; restored → green.

Conflict notes

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

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx prettier --check packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts — passed
  • npx vitest run src/config/storage.test.ts in packages/core (touched package, focused) — 98 passed (98)
    • pre-fix reproduction run: 3 failed | 95 passed — the three defect witnesses fail on the unmodified code, as required
  • Full packages/core vitest suite — 21224 passed, 109 failed in 7 files (utils/editor, agents/workflow-snapshot, utils/environmentContext.mcp-subagent, agents/runtime/agent-headless, tools/enter-worktree.session.integ, tools/exit-worktree.session.integ, config/config): stashed this round's two changed files and re-ran the same seven files at HEAD — identical 109 failures, so they are pre-existing runner-environment issues (this agent's own SANDBOX and QWEN_HOME env vars leak into the test processes), unrelated to this diff
  • Test runs use env -u QWEN_HOME because this runner exports a QWEN_HOME for the agent itself; with it leaked, three ~/.qwen path assertions in storage.test.ts fail at HEAD too
  • No settings source changed → npm run generate:settings-schema not applicable
  • The touched behavior has no production callers yet and is fully unit-exercised → no bundled-CLI/integration run needed
中文说明

Autofix 轮次总结 — PR #9776(issue #9776

提交:fe77863b72fix(core): re-lstat audit landing after follow-based validation steps (#9776)(2 个文件,+151/−0)

反馈点与处理决定

[rc:3841965743] R8-1 — Critical:目录分支先以新鲜 lstat 判定、随后以跟随语义重新解析同名路径 — 已在代码中解决

按来源盲审规则先行复现:新增竞争测试在最终内容检查的递归 readdir 处注入确定性缝隙,把已列出的目录子项换成指向干净(空)目录的符号链接。在未修改的代码上,ensureAuditFallbackDir 返回了仍含符号链接子项的落点——测试以 expected [Function] to throw an error 失败,与该发现的 BASE 证据完全一致。

修复:采用发现中经探针验证的收窄建议。递归校验完一个目录子项后,该分支对子项重新 lstat,若其不再是目录则拒绝(走查期间被换成「指向目录的符号链接」时,校验的是链接目标);走查期间消失的子项则跳过,与既有的「消失条目」容忍保持一致。残余窗口收缩到路径返回型 API 已书面承认的返回后尾部。未采用 O_NOFOLLOW/文件描述符相对的类别闭合替代方案:那需要围绕与测试套件 readdirSync 缝隙不同的 fs 面重建整个走查,且 diff 增长远超本轮所需的收窄。

证据测试:refuses a directory child swapped for a symlink inside the final content check(修复前失败、修复后通过)与 tolerates a directory child that vanishes during the final content check(钉住新增的「消失子项 continue」分支)。

[rc:3841965757] R8-2 — Critical:返回前重新校验把仅有的非跟随检查放在两次跟随型检查之前 — 已在代码中解决

按发现的要求,用两个在第二次内容检查处注入的新竞争测试先行复现(既有的 refuses a leaf raced into a symlink after its own adoption 在第一次内容检查处注入,那里重新采纳的 lstat 仍先于交换发生)。臂 A 把叶子换成指向攻击者目录的符号链接;臂 B 换掉 audits 父目录,并在攻击者目录内预建可预测的叶子名称,使跟随型检查通过而非报错。在未修改的代码上,两臂均通过全部检查且方法返回符号链接化的落点(两个测试修复前均失败),与发现中的 BASE 证据一致。

修复:采用经探针验证的建议——两次 adoptDirectory 调用在最终内容检查与封闭性检查之后再运行一次,使落在任一跟随型检查内部的交换在返回前被 lstat 拒绝。未尝试仅调换内容/封闭性检查的顺序,理由与发现所述相同:两者都跟随根路径。

证据测试:refuses a leaf raced into a symlink inside the final content check(臂 A)与 refuses audits raced into a symlink inside the final content check(臂 B)——均修复前失败、修复后通过。

[rv:5006087989] 评审正文 — CHANGES_REQUESTED(「部分评审——缺口已披露」)— 经由行内发现处理

该评审的可执行实质即上述两条 Critical,均已在代码中解决。关于披露的缺口:

  • macOS/Windows 的 build-and-test 套件无法在本 Linux runner 上运行;这些平台的最终关卡仍是工作流的 CI。
  • Test Plan 备注(src/config/storage.test.tsno such file or directory):测试位于 packages/core/src/config/storage.test.ts,本轮运行全绿(98/98)。

收敛姿态下列出的 5 条延后项已记录为「本轮不要求」,按仅 Critical 模式未做改动;未就其产生任何代码、线程操作或回复。

变异探针(每个新增守卫/分支都有自己的证据)

  • 移除递归后的重新 lstat 守卫 → refuses a directory child swapped for a symlink inside the final content check 失败,其余全部通过;恢复后全绿。
  • 把新增的「消失子项 continue」变异为 throw → tolerates a directory child that vanishes during the final content check 失败;恢复后全绿。
  • 移除最终检查后的重新采纳 → 两个「inside the final content check」臂测试均失败;恢复后全绿。

冲突说明

无(--conflict false;未执行任何合并)。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx prettier --check packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts — 通过
  • packages/corenpx vitest run src/config/storage.test.ts(所触包的聚焦运行)— 98 通过(98)
    • 修复前复现运行:3 失败 | 95 通过——三个缺陷证据测试在未修改代码上失败,满足要求
  • packages/core 完整 vitest 套件 — 21224 通过,7 个文件中 109 失败(utils/editoragents/workflow-snapshotutils/environmentContext.mcp-subagentagents/runtime/agent-headlesstools/enter-worktree.session.integtools/exit-worktree.session.integconfig/config):暂存本轮改动的两个文件后在 HEAD 上重跑同 7 个文件——同样 109 个失败,故为 runner 环境的既有问题(本 agent 自身的 SANDBOXQWEN_HOME 环境变量泄漏进测试进程),与本 diff 无关
  • 测试运行使用 env -u QWEN_HOME,因为该 runner 为 agent 自身导出了 QWEN_HOME;若任其泄漏,storage.test.ts 中三个 ~/.qwen 路径断言在 HEAD 上同样失败
  • 未改动设置源 → 不适用 npm run generate:settings-schema
  • 所触行为尚无生产调用方且已被单元测试完整覆盖 → 无需 bundle/集成运行

Deferred non-Critical feedback

Critical-only mode is active: 5 change-producing rounds are complete. 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.)

中文说明

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

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.

Partially reviewed — gaps disclosed.

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

  • chmodSync/lstatSync raw errno escape in adoptDirectory (storage.ts:460) — already reported in the round-6 and round-8 deferred lists (storage.ts:446 / storage.ts:440)
  • vanished-entry continue arm and adoptDirectory non-EEXIST re-throw untested (storage.ts:509, storage.ts:441) — already reported in the round-8 and round-6 deferred lists (storage.ts:507 / storage.ts:422)
  • vanished directory child between lstat and recursive readdir aborts with a hard refusal (storage.ts:525) — already reported in the round-8 deferred list (storage.ts:521)
  • base-creation catch's remediation text misdirects for permission/quota failures (storage.ts:389) — already reported in the round-6 deferred list (storage.ts:386)
  • non-EEXIST mkdirSync failure escapes raw between the two consecutive adoptDirectory calls (storage.ts:441) — already reported in the round-8 deferred list (storage.ts:438)

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:423 — [probe] Triple re-validation is a non-converging enumeration of race windows the path-returning API provably reopens
  • packages/core/src/config/storage.ts:534 — [probe] Post-recursion re-lstat refusal always claims 'contains a symlink' for any non-directory swap
  • packages/core/src/config/storage.ts:391 — [review] (err as Error).message casts instead of the package's getErrorMessage() convention

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

中文说明

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

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

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows。

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

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

Comment thread packages/core/src/config/storage.ts
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round — PR #9776

Critical-only mode is active (5 change-producing rounds complete), so only the
Critical finding was actionable this round.

Feedback points and dispositions

[rc:3846130622] [Critical] Containment guard bypassed on case-insensitive
filesystems when the same physical repository is spelled with different case in
the two compared inputs — RESOLVED in code.

Reproduced first, on the pre-fix code, with the two new regression tests
(platform pinned to darwin via Object.defineProperty(process, 'platform'),
the existing convention in core tests):

  • the refusal test failed with expected [Function] to throw an error — the
    method RETURNED a landing for QWEN_HOME spelled as a case-variant of the
    audited root, exactly the reported bypass;
  • the leaf test showed two distinct leaves (452… vs 0c8…) for two case
    spellings of one physical root — the reported split landings.

Fix (all inside the PR's footprint, packages/core/src/config/storage.ts):

  • new platformFoldsCase() helper (win32 or darwin — the platforms whose
    default volumes equate names differing only in case; this is the
    reviewer-endorsed "at minimum win32+darwin" direction);
  • isResolvedPathWithinDirectory now folds the case of both inputs before the
    byte-wise path.relative comparison, closing the bypass at every containment
    check site (initial, post-base-creation, and the finalCheck re-check), on
    the QWEN_HOME side as well as the root side;
  • ensureAuditFallbackDir folds the resolved root before getProjectHash, so
    case-variant spellings of one physical root hash to ONE leaf, restoring the
    "all consumers agree on one root" stability the realpath comment demands.

The reviewer also suggested folding in getProjectHash itself. That function
(and sanitizeCwd) lives in packages/core/src/utils/paths.ts, which this PR
has never touched, and extending its win32-only lowercasing to darwin would
silently re-key every existing macOS project hash (temp dirs, project dirs) —
a behavior migration far beyond this PR's purpose. The Critical defect and its
in-feature consequence (split audit leaves) are fully fixed without that; a
repo-wide darwin normalization of getProjectHash/sanitizeCwd is left as a
maintainer-judged follow-up if desired.

Regression coverage: two new tests pin the case-mismatch refusal and the
single-leaf stability. Both fail on the pre-round code (bite for the
verification gate) and pass with the fix.

Mutation probes (each guard witnessed by its own test):

  • Probe 1: negated the case fold in isResolvedPathWithinDirectory → the
    refusal test FAILED (1 failed | 99 passed) → restored, green again.
  • Probe 2: removed the pre-hash root fold in ensureAuditFallbackDir → the
    leaf-stability test FAILED (1 failed | 99 passed) → restored, green again.

[rv:5011033098] [CHANGES_REQUESTED] "Partially reviewed — gaps disclosed" —
no code action.
The review body carries no new findings of its own: it
discloses that the macOS/Windows CI legs were skipped at the reviewed commit
and that no local macOS/Windows run happened (not available on this Linux
runner either; the platform behavior is exercised here through the
pinned-platform regression tests). The 5 Suggestion-level findings it confirms
as already reported are duplicates of prior-round reports and are not repeated.
Its "Test Plan: src/config/storage.test.ts — no such file or directory" note
is a reviewer-side path resolution problem: the file exists at
packages/core/src/config/storage.test.ts and was executed as part of this
round's verification (100/100 passed).

Deferred non-Critical feedback — no action. Critical-only mode excludes it
from this round; the items remain open for human follow-up. The three
convergence-posture deferrals named in the review body were recorded, not
requested, and were left untouched.

Conflict: none (--conflict false; no merge performed).

Verification

Commands actually run this round (from the repository root unless noted;
Vitest runs used env -u QWEN_HOME -u QWEN_RUNTIME_DIR because this agent's
shell exports a QWEN_HOME that would pollute home-based assertions):

  • npx vitest run src/config/storage.test.ts (in packages/core), pre-fix
    reproduction — 2 new tests FAILED as expected, 98 passed
  • npx vitest run src/config/storage.test.ts (in packages/core), post-fix —
    100 passed (100)
  • Mutation probe 1 (containment fold negated): 1 failed | 99 passed
    (expected); restored → green
  • Mutation probe 2 (pre-hash fold removed): 1 failed | 99 passed
    (expected); restored → green
  • npx prettier --check packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts — passed
  • npm run build — passed
  • npm run typecheck — passed (all workspaces)
  • npm run lint — passed
  • npx vitest run src/config/config.test.ts -t "plans" (in packages/core) —
    6 passed (shared assertPathWithinDirectory path)
  • npx vitest run src/config/config.test.ts -t "plans" (in packages/cli) —
    3 passed
  • Integration tests: not run — the changed behavior is fully covered by the
    unit suite and is not exercised through the bundled CLI or the integration
    harness (ensureAuditFallbackDir has no consumer outside storage.ts).
  • macOS/Windows legs: not available on this Linux runner; the new tests pin
    the platform explicitly and run on every host.
中文说明

Autofix 审查轮次 — PR #9776

当前处于仅处理 Critical 的模式(已完成 5 个产生改动的轮次),因此本轮只有 Critical 发现可以处理。

反馈点及处置

[rc:3846130622] [Critical] 在大小写不敏感的文件系统上,当同一物理仓库在被比较的两个输入中以不同大小写写法出现时,封闭性防线被绕过 —— 已在代码中解决。

先在未修复的代码上复现,用的是两个新增的回归测试(通过 Object.defineProperty(process, 'platform') 将平台钉为 darwin,这是 core 测试中的既有惯例):

  • 拒绝测试以 expected [Function] to throw an error 失败 —— 当 QWEN_HOME 以被审计仓库的大小写变体写法出现时,方法返回了落点而非拒绝,正是所报告的绕过;
  • 叶子测试显示同一物理仓库的两种大小写写法产生了两个不同的叶子(452…0c8…)—— 正是所报告的落点分裂。

修复(全部位于本 PR 的足迹内,packages/core/src/config/storage.ts):

  • 新增 platformFoldsCase() 辅助函数(win32darwin —— 即默认卷会对仅大小写不同的名字等同视之的平台;这正是评审认可的「至少 win32+darwin」方向);
  • isResolvedPathWithinDirectory 现在在逐字节的 path.relative 比较之前对两个输入都做大小写折叠,从而在每一处封闭性检查点(初次检查、基目录创建后的复查、以及 finalCheck=true 的终审)关闭该绕过,无论是 QWEN_HOME 一侧还是仓库根一侧;
  • ensureAuditFallbackDirgetProjectHash 之前对已解析的仓库根做大小写折叠,使同一物理仓库的大小写变体写法哈希到同一个叶子,恢复 realpath 上方注释所要求的「所有消费方就同一个根达成一致」的稳定性。

评审还建议直接在 getProjectHash 内部做折叠。该函数(以及 sanitizeCwd)位于 packages/core/src/utils/paths.ts,本 PR 从未触碰该文件;且把它仅限 win32 的小写化扩展到 darwin,会悄无声息地重新编排所有现有 macOS 项目哈希(临时目录、项目目录)——这是一次远超本 PR 目的的行为迁移。不这样做也能完整修复 Critical 缺陷及其在本功能内的后果(审计叶子分裂);是否在整个仓库范围内对 getProjectHash/sanitizeCwd 做 darwin 归一化,留待维护者判断,作为后续跟进即可。

回归覆盖:两个新测试分别钉住「大小写不一致时拒绝」与「单叶子稳定性」。两者在轮次前的代码上都会失败(满足验证门的 bite 要求),修复后通过。

变异探针(每个守卫都有各自的测试作见证):

  • 探针 1:取反 isResolvedPathWithinDirectory 中的大小写折叠 → 拒绝测试失败1 failed | 99 passed)→ 恢复后重新变绿。
  • 探针 2:移除 ensureAuditFallbackDir 中哈希前对仓库根的折叠 → 叶子稳定性测试失败1 failed | 99 passed)→ 恢复后重新变绿。

[rv:5011033098] [CHANGES_REQUESTED]「Partially reviewed — gaps disclosed(部分审查——缺口已披露)」—— 无代码改动。 该评审正文本身不含新发现:它披露在被审查的提交上 macOS/Windows 的 CI 腿被跳过、且未在本地 macOS/Windows 上运行(本 Linux 运行器上同样不可用;此处的平台行为通过钉住平台的回归测试来演练)。它确认的 5 条建议级发现均为先前轮次已报告内容的重复,不再重复处理。其中「Test Plan: src/config/storage.test.ts — no such file or directory」的说明是评审侧的路径解析问题:该文件存在于 packages/core/src/config/storage.test.ts,并且已在本轮验证中执行(100/100 通过)。

延后的非 Critical 反馈 —— 无改动。 仅 Critical 模式将其排除在本轮之外;这些条目保持开放,留待人工跟进。评审正文中点名的 3 条收敛姿态延后项属于「已记录、本轮不要求修改」,未做触碰。

冲突:无(--conflict false;未执行合并)。

验证

本轮实际执行的命令(除特别说明外在仓库根目录运行;Vitest 运行使用了 env -u QWEN_HOME -u QWEN_RUNTIME_DIR,因为本 agent 的 shell 导出了一个 QWEN_HOME,会污染依赖家目录的断言):

  • npx vitest run src/config/storage.test.ts(在 packages/core 内),修复前复现 —— 2 个新测试按预期失败,98 通过
  • npx vitest run src/config/storage.test.ts(在 packages/core 内),修复后 —— 100 通过(100)
  • 变异探针 1(取反封闭性比较的折叠):1 failed | 99 passed(预期内);恢复后变绿
  • 变异探针 2(移除哈希前的折叠):1 failed | 99 passed(预期内);恢复后变绿
  • npx prettier --check packages/core/src/config/storage.ts packages/core/src/config/storage.test.ts —— 通过
  • npm run build —— 通过
  • npm run typecheck —— 通过(所有 workspace)
  • npm run lint —— 通过
  • npx vitest run src/config/config.test.ts -t "plans"(在 packages/core 内)—— 6 通过(共享的 assertPathWithinDirectory 路径)
  • npx vitest run src/config/config.test.ts -t "plans"(在 packages/cli 内)—— 3 通过
  • 集成测试:未运行 —— 改动的行为已被单元测试套件完整覆盖,且不经过捆绑后的 CLI 或集成测试框架演练(ensureAuditFallbackDirstorage.ts 之外没有消费方)。
  • macOS/Windows 腿:本 Linux 运行器上不可用;新测试显式钉住平台,可在任何宿主上运行。

Deferred non-Critical feedback

Critical-only mode is active: 5 change-producing rounds are complete. 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.)

中文说明

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

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.

Partially reviewed — gaps disclosed.

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

  • vanished-entry continue arm in assertAuditLandingIsClean untested — continue→throw mutant survives the whole suite (storage.ts:525) — already reported in the round-8 deferred list (storage.ts:507)

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows.

Test Plan (not a blocker): src/config/storage.test.tsno such file or directory.

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

  • packages/core/src/config/storage.ts:35 — [probe] fold in the shared containment helper loosens the plans-dir and image-gen guards on case-sensitive volumes
  • packages/core/src/config/storage.test.ts:837 — [probe] case-variant refusal test is a probabilistic oracle — fold-removal mutant survives ~1 CI run in 26
  • packages/core/src/config/storage.ts:366 — [probe] pre-hash fold keyed on platform, not volume behavior — coalesces case-variant repos and spuriously refuses safe configs on case-sensitive volumes
中文说明

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

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

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on macOS。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI at this commit and the packages/core suite did not run locally on Windows。

Test Plan(非阻断):src/config/storage.test.tsno such file or directory

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

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

No action taken this round

This round ran in Critical-only mode and the actionable sections were empty: no
reviews, no inline comments, no issue-level comments, no failed checks, and no
still-red checks. The only feedback present is the deferred non-Critical review
by the automated reviewer, which the deterministic brake excluded from this
round; it stays open for human follow-up and was not acted on.

Growth audit (required this round)

The counting window is over its growth budget (source 71 / test 413 net lines
vs budgets 400/400 — the test side is 13 lines over), so the mandated growth
audit ran before any other work and is recorded in growth-audit.json with
verdict sound (KISS: pass, minimal change: pass):

  • KISS: three structurally simpler alternatives were examined and rejected
    with evidence. A single-pass validation would delete exactly the re-checks
    that prior rounds added to close named, accepted TOCTOU findings (each has a
    dedicated injection test that fails without it). A fresh per-run leaf would
    delete most validation but changes the accepted reused-landing design.
    Helper dedup is cosmetic and changes nothing. Every remaining guard carries
    a named failure mode and a witnessing test, and the residual race tail is
    documented with its backstop rather than chased with more passes.
  • Minimal change: both changed files have been the PR's footprint since its
    first commit, and every hunk traces to the landing feature, an accepted
    review finding, or the case-folding fix in the containment helper. No
    untraceable hunks.
  • The 13-line test overage is witness coverage the repository's own policy
    mandates (every guard needs its own witness); source is at 71/400.

Result

No code changes, no commit. The branch stays at
71a6928c6f fix(core): fold case in audit landing containment on case-insensitive platforms (#9776).

中文说明

本轮未采取任何改动

本轮运行于仅处理 Critical 的模式,且可执行区域为空:没有评审、没有行内评论、没有 issue 级评论、没有失败的检查,也没有持续失败的检查。本轮唯一存在的反馈是自动化评审器(automated reviewer)的非 Critical 评审,它已被确定性刹车机制从本轮排除,保持开放留待人工跟进,未做任何处理。

增长审计(本轮必需)

计数窗口已超出增长预算(净增长 源码 71 / 测试 413 行,预算 400/400 —— 测试侧超出 13 行),因此在进行任何其他工作之前先执行了强制的增长审计,结果记录在 growth-audit.json,结论为 sound(KISS:通过;最小改动:通过):

  • KISS:考察了三种结构上更简单的替代方案,均有证据地予以否决。单遍验证会恰好删掉前几轮为关闭已被接受的具名 TOCTOU 发现而增加的重检(每个重检都有专门的注入测试,删掉后该测试即失败)。每次运行新建叶目录可以删掉大部分验证,但会改变已被接受的"复用落地目录"设计。用辅助函数去重只是表面改动,不改变任何检查顺序。其余每个守卫都有对应的具名失效模式和见证测试,剩余的竞争窗口尾部也以文档形式说明了其兜底位置,而不是继续堆叠更多守卫。
  • 最小改动:两个改动文件自本 PR 首个提交起就是 PR 的足迹范围,每个 hunk 都可追溯到落地目录功能本身、某个已被接受的评审发现,或包含性检查辅助函数中的大小写折叠修复。没有无法追溯的 hunk。
  • 测试侧超出的 13 行是仓库自身策略强制要求的见证覆盖(每个守卫必须有自己的见证测试);源码侧为 71/400。

结果

无代码改动,无提交。分支保持在
71a6928c6f fix(core): fold case in audit landing containment on case-insensitive platforms (#9776)

Deferred non-Critical feedback

Critical-only mode is active: 5 change-producing rounds are complete and the PR's diff grew src 71 / test 413 net lines beyond this counting window's baseline (budgets: 400/400). 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.)

中文说明

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

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


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

🤖 Reviewed the latest feedback — no changes needed. Every finding in this round's backlog was verified already resolved at the current head (71a6928c6f), with mutation-probe evidence rather than assumed from the diff history.

Why no change

This round's feedback re-delivered the full backlog of review rounds 1–9 (36 inline comments). Each fix already landed in a prior round's commit; the round-10 review of this exact head (at the Critical posting floor) posted zero new findings. I re-verified every claim against the code as it stands:

  • Read every guarded seam in Storage.ensureAuditFallbackDir and its helpers at HEAD.
  • Ran the focused suite to green, then ran six mutation probes: each deleted or reverted one fixed guard, and the suite went red on exactly the tests that pin it, then the code was restored byte-identical (git status clean, HEAD unchanged).

Dispositions of the 36 inline findings

Resolved in code at HEAD — 35 threads (verified, listed with their witness):

Finding Fix at HEAD Pinning witness
rc:3838295036 (C, 0300 fail-open readdir + group/other-only mode check) readdir catch fails closed; adoption normalizes the FULL mode to 0700 Probe: reverting both keeps repairs a 0300-planted landing… and refuses a landing it cannot list for validation red
rc:3838796976 (C, check→mkdir race on QWEN_HOME tail) containment re-check immediately after base creation refuses a QWEN_HOME tail raced into a repo symlink between the containment check and the base creation
rc:3838796985 (C, audits swapped between the two adoptions) pre-return re-validation re-adopts both components refuses audits raced into a repo symlink between the two adoption checks
rc:3839350634 (C, nested symlink passes — no recursion) content check recurses into directory children refuses a symlink planted inside a child directory of the landing
rc:3839350635 (C, special files accepted) entries neither file nor directory are refused refuses a landing holding a special file such as a FIFO
rc:3839350636 + rc:3839647873 + rc:3839801476 (C ×3, final containment check swallows resolution errors) finalCheck site fails closed on resolution failure Probe: removing the final re-check turns fails closed when the final containment re-check cannot resolve the landing red
rc:3840203224 (C, re-validation skips the content re-check) re-validation re-runs assertAuditLandingIsClean Probe: removing it turns five race tests red
rc:3840203230 (C, socket path exceeds AF_UNIX sun_path) test plants a FIFO via mkfifo; the net import is gone refuses a landing holding a special file such as a FIFO
rc:3840755230 (C, second content check decides from the stale snapshot) every entry gets one fresh lstat; all arms decide from it Probe: reverting the symlink arm to the stale dirent turns refuses a listed file raced into a symlink inside the re-run content check red
rc:3841965743 (C, directory arm re-resolves through follow-based recursion) post-recursion re-lstat of the child, refusal on swap, tolerance for vanishing Probe: removing the re-lstat turns refuses a directory child swapped for a symlink inside the final content check red
rc:3841965757 (C, re-adoption lstats run before the follow-based checks) both adoptDirectory calls run again after the final checks Probe: removing them turns both …raced into a symlink inside the final content check tests red
rc:3846130622 (C, case-insensitive containment bypass) case fold in the containment comparison and pre-hash on folding platforms refuses a case-variant spelling of the audited root… + lands case-variant spellings of one root at one leaf…
rc:3838295042 (S, mode-repair branch untested) adopts a pre-existing loose-mode directory and tightens it to 0700
rc:3838295043 (S, DT_UNKNOWN fallback untested) falls back to lstat when a dirent arrives untyped (also red under the stale-dirent probe)
rc:3838295044 (S, sole mutating get*) renamed to action-named ensureAuditFallbackDir; still no production callers grep: only storage.ts / storage.test.ts reference it
rc:3838295046 (S, early return skips) all POSIX-only tests use it.skipIf(process.platform === 'win32'); the 0700 test keeps its cross-platform conditional assertions, which the finding explicitly allows read-verified
rc:3838295051 (S, docstring promises an ownership check) adoptDirectory docstring now states ownership is NOT checked read-verified
rc:3838295052 (S, in-repo landing when QWEN_HOME is in-repo) containment refusal is unconditional refuses a landing that resolves inside the audited repository
rc:3838295056 (S, ENOENT for a missing base) base created recursively before adoption, matching sibling writers creates a missing QWEN_HOME base instead of failing with ENOENT
rc:3838796987 (S, bare Error refusals) every refusal throws FatalConfigError class assertions across the refusal tests
rc:3838796990 (S, ENOTDIR raw errno pre-empts the actionable message) pre-adoption containment sites fall through on resolution failure surfaces the actionable refusal when audits is planted as a regular file
rc:3839350637 + rc:3839647874 + rc:3839801477 (S ×3, final re-check unpinned) refuses an ancestor raced into a repo symlink above the adoption checks — red when only the final re-check is deleted
rc:3839350639 + rc:3839647878 + rc:3839801478 (S ×3, dangling/loop/file-link tail raw errno) base-creation try/catch classifies into FatalConfigError refuses an uncreatable QWEN_HOME tail with an actionable refusal (three tail shapes)
rc:3839350640 + rc:3839647880 + rc:3839801480 (S ×3, hoisted mocks default to bare vi.fn()) the mock factory seeds mkdirSync/readdirSync with the real implementations (the pre-existing realpathSync mock on main is out of this PR's scope) read-verified
rc:3839350642 + rc:3839647881 + rc:3839801481 (S ×3, error class unpinned at content-check sites) toThrow(FatalConfigError) asserted beside the message regex at the symlink-child, nested-symlink, hardlink, special-file, and unlistable sites read-verified

Declined — 1 thread, already recorded in-thread (no duplicate reply this round):

  • rc:3838295059 (S, win32 adoption applies no privacy enforcement) — declined in the earlier round's reply (comment 3838401068, 2026-08-23), and re-derived independently this round: refusing adoption of pre-existing components on win32 would refuse this tool's OWN landings from previous runs (the landing is deliberately reused across runs and nothing on Windows distinguishes self-created from planted), so every second /audit run per project would fail forever. The limitation is documented in the code instead (mode-repair comment + adoptDirectory docstring + POSIX-scoped purpose). The thread stays open; the earlier reply offers a creation-marker design if a maintainer wants a stronger win32 guarantee.

Recorded, not requested this round (round-10 convergence deferrals — untouched by design): the fold's effect on the plans-dir/image-gen guards, the probabilistic case-variant test oracle, and platform-keyed vs volume-keyed fold detection.

Other feedback items

  • Review bodies (rv:5001776146 … rv:5012542714): their blocking findings are the inline comments above; the repeated Test Plan (not a blocker): src/config/storage.test.ts — no such file or directory note is a path artifact of the reviewer's test-plan step — the actual file packages/core/src/config/storage.test.ts exists and passes. No code action available.
  • ic:5384547426 (serve A/B): ✅ no response changes vs base — informational.
  • ic:5384950999: historical acknowledgment of the round-1 blocker fix — no action.
  • Failed checks: none. Still-red checks: none.

Verification

Commands actually run this round (working tree left untouched — no commit):

  • cd packages/core && npx vitest run src/config/storage.test.ts — 97 passed | 3 failed; the 3 (getGlobalSettingsPath, getUserCommandsDir, getMcpOAuthTokensPath) are pre-existing environmental failures: this runner exports QWEN_HOME globally, which leaks into tests that assume it unset. Identical to the baseline the reviewer recorded in prior rounds.
  • cd packages/core && env -u QWEN_HOME npx vitest run src/config/storage.test.ts100 passed (100).
  • Six mutation probes (mutate → rerun suite → restore byte-identical, git status clean after each):
    1. Delete final containment re-check → 2 tests red (…ancestor raced…, fails closed when the final containment re-check…).
    2. Delete final re-adoptions → 2 tests red (both …inside the final content check race tests).
    3. Revert readdir catch to fail-open + mode check to group/other-only → 2 tests red (0300-planted, cannot list).
    4. Symlink arm decides from the stale dirent → 2 tests red (untyped dirent, listed file raced).
    5. Remove post-recursion child re-lstat → 1 test red (directory child swapped).
    6. Remove content re-check from re-validation → 5 tests red.
  • CI at HEAD 71a6928c6f: Test (ubuntu-latest, Node 22.x) SUCCESS (2026-08-24T19:20:45Z), Serve A/B SUCCESS, no failures; macOS/Windows legs are SKIPPED in CI at this commit (reviewer-disclosed gap in every round, CI-side, not PR code).
中文说明

🤖 已审阅最新反馈——无需改动。本轮积压中的每一项发现都已在当前头部(71a6928c6f)核实为已解决,且以变异探针为证,而非仅凭提交历史推断。

为何不做改动

本轮反馈重新递交了第 1–9 轮评审的全部积压(36 条行内评论)。每项修复都已在此前各轮的提交中落地;第 10 轮评审针对的正是当前头部(且已处于 Critical 发布下限),未发布任何新发现。我对每一条声明都按代码现状重新核实:

  • 通读了 HEAD 上 Storage.ensureAuditFallbackDir 及其助手中的每一道守卫缝隙。
  • 将聚焦测试套件跑至全绿,随后执行 6 个变异探针:每次删除或回退一道已修复的守卫,套件恰好在钉住该守卫的测试上变红,然后将代码恢复为逐字节一致(git status 干净,HEAD 不变)。

36 条行内发现的处理结果

已在 HEAD 代码中解决——35 个线程(已核实,附见证):

发现 HEAD 上的修复 钉住它的见证
rc:3838295036(C,0300 落点 readdir 失败即敞开 + 只查 group/other 位) readdir catch 改为失败即关闭;采纳时把完整模式归一为 0700 探针:回退两处后 repairs a 0300-planted landing…refuses a landing it cannot list for validation 变红
rc:3838796976(C,QWEN_HOME 末端检查→mkdir 竞争) 基础目录创建后立即复查封闭性 refuses a QWEN_HOME tail raced into a repo symlink between the containment check and the base creation
rc:3838796985(C,两次采纳之间交换 audits 返回前重新校验重新采纳两个组件 refuses audits raced into a repo symlink between the two adoption checks
rc:3839350634(C,嵌套符号链接通过——未递归) 内容检查递归进入目录子项 refuses a symlink planted inside a child directory of the landing
rc:3839350635(C,接受特殊文件) 既非常规文件亦非目录的条目被拒绝 refuses a landing holding a special file such as a FIFO
rc:3839350636 + rc:3839647873 + rc:3839801476(C ×3,最终封闭性检查吞掉解析错误) finalCheck 位点对解析失败失败即关闭 探针:移除最终复核使 fails closed when the final containment re-check cannot resolve the landing 变红
rc:3840203224(C,重新校验漏掉内容复查) 重新校验重跑 assertAuditLandingIsClean 探针:移除后 5 个竞争测试变红
rc:3840203230(C,socket 路径超出 AF_UNIX sun_path) 测试改用 mkfifo 植入 FIFO;net import 已移除 refuses a landing holding a special file such as a FIFO
rc:3840755230(C,第二次内容检查依据过期快照判定) 每个条目做一次新鲜 lstat,所有分支据此判定 探针:符号链接分支回退为读过期 dirent 后 refuses a listed file raced into a symlink inside the re-run content check 变红
rc:3841965743(C,目录分支经跟随式递归再次解析) 递归返回后对子项重新 lstat,交换即拒绝、消失即容忍 探针:移除该重 lstat 后 refuses a directory child swapped for a symlink inside the final content check 变红
rc:3841965757(C,重新采纳 lstat 先于跟随型检查运行) 两次 adoptDirectory 在最终检查之后再跑一遍 探针:移除后两个 …raced into a symlink inside the final content check 测试变红
rc:3846130622(C,大小写不敏感平台的封闭性绕过) 封闭性比较做大小写折叠,哈希前在折叠平台统一折叠 refuses a case-variant spelling of the audited root… + lands case-variant spellings of one root at one leaf…
rc:3838295042(S,模式修复分支无测试) adopts a pre-existing loose-mode directory and tightens it to 0700
rc:3838295043(S,DT_UNKNOWN 兜底无测试) falls back to lstat when a dirent arrives untyped(过期 dirent 探针下同样变红)
rc:3838295044(S,唯一会改动文件系统的 get* 已更名为动作命名的 ensureAuditFallbackDir;仍无生产调用方 grep:仅 storage.ts / storage.test.ts 引用
rc:3838295046(S,提前 return 跳过) 所有 POSIX 专属测试改用 it.skipIf(process.platform === 'win32');0700 测试保留跨平台条件断言,该发现明确允许此形态 读码核实
rc:3838295051(S,docstring 承诺属主检查) adoptDirectory docstring 已写明不检查属主 读码核实
rc:3838295052(S,QWEN_HOME 在仓库内时落点入库) 封闭性拒绝无条件生效 refuses a landing that resolves inside the audited repository
rc:3838295056(S,缺失基目录抛 ENOENT) 采纳之前递归创建基目录,与同级写入者一致 creates a missing QWEN_HOME base instead of failing with ENOENT
rc:3838796987(S,裸 Error 拒绝) 所有拒绝改抛 FatalConfigError 各拒绝测试的类别断言
rc:3838796990(S,ENOTDIR 裸 errno 抢先于可照做消息) 采纳前的封闭性调用点对解析失败失败即穿透 surfaces the actionable refusal when audits is planted as a regular file
rc:3839350637 + rc:3839647874 + rc:3839801477(S ×3,最终复核无测试钉住) refuses an ancestor raced into a repo symlink above the adoption checks——仅删除最终复核即变红
rc:3839350639 + rc:3839647878 + rc:3839801478(S ×3,悬空/环/指向文件的末端裸 errno) 基础目录创建以 try/catch 归类为 FatalConfigError refuses an uncreatable QWEN_HOME tail with an actionable refusal(三种末端形态)
rc:3839350640 + rc:3839647880 + rc:3839801480(S ×3,提升 mock 默认裸 vi.fn() mock 工厂以真实实现为 mkdirSync/readdirSync 播种(main 上既有的 realpathSync mock 不属于本 PR 范围) 读码核实
rc:3839350642 + rc:3839647881 + rc:3839801481(S ×3,内容检查位点错误类别未钉住) 符号链接子项、嵌套符号链接、硬链接、特殊文件、不可列目录五处均在消息正则旁补 toThrow(FatalConfigError) 读码核实

已拒绝——1 个线程,且此前已在线程内记录(本轮不重复回复):

  • rc:3838295059(S,win32 采纳不施加隐私强制)——已在更早一轮的回复(评论 3838401068,2026-08-23)中拒绝,本轮独立推导出相同结论:在 win32 上拒绝采纳已存在组件,会同时拒绝本工具此前运行自建的落点(落点刻意跨运行复用,Windows 上无法区分自建与植入),后果是每个项目每隔一次 /audit 运行就永远失败。代码改为如实记录该限制(模式修复注释 + adoptDirectory docstring + POSIX 限定的目的声明)。线程保持打开;早前的回复已提出「创建标记」方案,若维护者希望更强的 win32 保证可随时启用。

已记录、本轮不要求处理(第 10 轮收敛姿态延后项——按设计不动):折叠对 plans-dir/image-gen 守卫的影响、大小写变体测试的概率性预言机、按平台而非按卷行为决定折叠。

其他反馈条目

  • 评审主体(rv:5001776146 … rv:5012542714):其中的阻断项即上表的行内评论;反复出现的 Test Plan (not a blocker): src/config/storage.test.ts — no such file or directory 是评审器测试计划步骤的路径口径问题——真实文件 packages/core/src/config/storage.test.ts 存在且通过。无代码层面可执行的动作。
  • ic:5384547426(serve A/B):✅ 相对 base 无响应变化——信息性。
  • ic:5384950999:对第 1 轮阻断修复的历史性确认——无需动作。
  • 失败检查:无。持续红色检查:无。

验证

本轮实际执行的命令(工作树保持原样——无提交):

  • cd packages/core && npx vitest run src/config/storage.test.ts —— 97 通过 | 3 失败;3 个失败(getGlobalSettingsPathgetUserCommandsDirgetMcpOAuthTokensPath)为预先存在的环境性失败:本 runner 全局导出 QWEN_HOME,泄漏进假设其未设置的测试。与评审器此前各轮记录的基线一致。
  • cd packages/core && env -u QWEN_HOME npx vitest run src/config/storage.test.ts —— 100 通过(100)
  • 6 个变异探针(变异 → 重跑套件 → 恢复为逐字节一致,每次之后 git status 干净):
    1. 删除最终封闭性复核 → 2 个测试变红(…ancestor raced…fails closed when the final containment re-check…)。
    2. 删除最终重新采纳 → 2 个测试变红(两个 …inside the final content check 竞争测试)。
    3. readdir catch 回退为失败即敞开 + 模式检查回退为仅 group/other → 2 个测试变红(0300-plantedcannot list)。
    4. 符号链接分支改据过期 dirent 判定 → 2 个测试变红(untyped direntlisted file raced)。
    5. 移除递归后的子项重 lstat → 1 个测试变红(directory child swapped)。
    6. 移除重新校验中的内容复查 → 5 个测试变红。
  • HEAD 71a6928c6f 的 CI:Test (ubuntu-latest, Node 22.x) SUCCESS(2026-08-24T19:20:45Z),Serve A/B SUCCESS,无失败;macOS/Windows 分支在此提交被 CI 跳过(评审器每轮均已披露的缺口,属 CI 侧,非本 PR 代码)。

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


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

@wenshao

wenshao commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

@qewn-code /triage

@wenshao
wenshao enabled auto-merge August 25, 2026 01:44
@wenshao

wenshao commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 164 passed · 0 failed · 164 total

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

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

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

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

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

Verification report

PR 9776 Deep Verification — feat(core): add a per-project outside-repo artifact landing

Verdict: findings — 164 scripted assertions executed, 164 pass / 0 fail; one Low (non-blocking) finding: the case fold landed in a shared containment predicate and silently widens the acceptance side of two pre-existing guards (getPlansDir and image-gen workspace containment) on case-sensitive volumes of darwin/win32.

  • Verified head: 71a6928c6f8c79c88a5175cbde6d6b64e61a2826 (git rev-parse HEAD^2; matches the metadata headRefOid)
  • Control base: 22bb5e8b9ff815f2fbb5d6013bec27a67cb0b2ee (HEAD^1, the merge-ref base tip)
  • Environment: CI verify container (node:22-bookworm), node v22.23.2, uid 1000 (non-root — POSIX permission probes are real), Linux case-sensitive fs
  • Artifact dir: tmp/pr9776-verify-20260825-020250/
中文摘要

结论:findings(164 项脚本断言全部通过;1 个 Low 级、非阻塞发现)。

  • 中心论断成立(A/B)Storage.ensureAuditFallbackDir 的采纳校验是承载性的。对 7 种攻击场景,无守卫的朴素对照(mkdirSync(recursive, 0700) + 直接写产物)全部逃逸成功(写进攻击者目录 / 泄漏进仓库 / FIFO 阻塞 >3s);PR 构建全部按名拒绝,攻击者目录零残留;良性复用正常采纳,无过度拒绝(27/27,图 01-ab-naive-vs-head-27-of-27.png)。基线 HEAD^1 根本没有该函数(0 次出现),本 PR 为纯新增。
  • 测试不空洞(变异矩阵):13 个守卫逐一还原,13/13 被测试击毙、0 幸存者;控制组 100/100 绿(图 02-mutation-matrix-13-of-13-killed.png)。PR 描述自称的两条变异(删内容检查、删叶子 lstat)均已复核属实。反向验证:把折叠限定到 audit 路径的补丁版上套件仍 100/100 绿——套件对「折叠波及 plans/image-gen」这一轴完全没有钉住。
  • 周边形态探测:12/12 通过(内向符号链接、三层嵌套、悬空链接、0500/0777 模式、尾斜杠、不存在的根目录、Linux 大小写敏感语义等)。
  • 发现(Low,非阻塞)platformFoldsCase() 放在共享谓词 isResolvedPathWithinDirectory 里,除 audit 外还作用于 getPlansDir 与 image-gen 的「留在工作区内」守卫。在 darwin/win32 的可选大小写敏感卷上,大小写变体的兄弟目录现在会被这两个守卫接受(基线谓词拒绝)。默认卷(大小写不敏感)上该折叠修复的是真实的误拒绝,方向正确;审计路径上的方向是失败安全的(多拒绝)。建议评审者有意识地接受该权衡,或把折叠限定在 audit 路径。无任何测试钉住这一侧效。
  • 未覆盖:逐提交归因(浅克隆仅 3 个提交可达,元数据列 15 个);Windows 平台(套件按设计跳过,本容器无法覆盖);真实大小写不敏感文件系统(仅以 process.platform 覆盖模拟);返回路径后残留的 TOCTOU 尾部(代码注释已声明由后续写入方封闭;尚无调用者);仓库级全量测试(只跑定向门禁)。
  • 描述中「74 pass」为早期提交的旧数字:当前头部该文件共 100 个测试(34 个为本 PR 新增 describe 块),全部通过。

Central claim and A/B proof

Central claim: Storage.ensureAuditFallbackDir(projectRoot) creates/adopts a per-user, per-project landing (<QWEN_HOME>/audits/<sha256>, 0700) that refuses every static-plant escape (planted symlink leaf/parent, symlink/hardlink/special-file children, mode blinding, containment inside the audited repo) while still adopting legitimate reuse.

The base tip (HEAD^1) contains no such function (grep: 0 occurrences of AuditFallbackDir), so the control is a naive implementationmkdirSync(dir, {recursive: true, mode: 0o700}) followed by the artifact writes /audit would perform. It is constructed for this round and labeled as such; it represents the landing as it would exist without the PR's guards. Every attack cell asserts both arms: the naive arm must demonstrate the escape (expected misbehavior = proof the attack is real), the head arm must refuse by name with zero collateral writes.

# Scenario (static plant) Naive control cell Head cell
BASE function at HEAD^1 n/a absent (0 occurrences)
S1 leaf pre-planted as symlink → decoy artifact written into decoy refused not a directory; decoy empty
S2 audits parent planted as symlink whole landing relocated into attacker dir refused not a directory; attacker dir empty
S3 symlink child (*.sidecar) in leaf sidecar write escaped through the link refused contains a symlink; escape target empty
S4 hardlinked report file O_TRUNC write leaked SECRET through the twin inode refused hardlinked file
S5 FIFO child naive write blocked >3 s (SIGTERM; DoS) refused contains a special file
S6 0300-planted landing (owner w+x, no r) readdir EACCES yet write still escaped mode repaired to 0700, then refused contains a symlink
S7 QWEN_HOME inside the audited repo landing created inside the working tree refused resolves inside the audited; nothing created
S8 benign: prior-run report + sidecar dir n/a adopted (no over-refusal)

27/27 scripted assertions (ab-naive-vs-head.mjs, runs against the compiled packages/core/dist). Witness: 01-ab-naive-vs-head-27-of-27.png. Harness note: the first run reported 26/27 because of a harness sequencing bug (the naive arm polluted the shared home before the S2 head arm); fixed by giving each S2 arm its own home — the product behavior was never at fault.

Shape checks (same harness, S9): <QWEN_HOME>/audits/<64-hex> ✓, 0700 ✓, idempotent ✓, distinct per project ✓, symlinked spelling of the same root → same leaf ✓, missing QWEN_HOME base created instead of ENOENT ✓.

Corrections

  • The PR description's Reviewer Test Plan says 74 pass; at the verified head the file contains 100 tests (34 in the new ensureAuditFallbackDir block; the file grew through the branch's later hardening commits). All 100 pass. This is a stale description, not a code issue.

Findings

F1 (Low, non-blocking) — case fold is placed in the shared containment predicate; it widens getPlansDir and image-gen workspace containment on case-sensitive volumes

platformFoldsCase() is applied inside isResolvedPathWithinDirectory, which is reached by three consumers, not just the audit path (grep of assertPathWithinDirectory):

  1. getPlansDir / assertPlansDirWithinTargetDir / assertPlanFilePathWithinTargetDir (plan-file containment),
  2. packages/core/src/tools/image-gen.ts — "Generated image path must stay inside the workspace" (3 call sites),
  3. the new assertAuditLandingIsOutsideRepo (the intended consumer).

Measured on simulated darwin (process.platform override, the same technique the suite's own darwin tests use; on Linux the two spellings are physically distinct directories, exactly the semantics of an opt-in case-sensitive darwin volume):

probe base predicate (byte-wise) head
CF-A plans guard, case-variant sibling plans dir refuses (../project/plans) accepts (widening confirmed)
CF-B audit containment, case-variant repo spelling n/a refuses (fail-safe direction)
CF-C same as CF-A on linux (fold off) refuses refuses (unchanged)

Repro: node tmp/pr9776-verify-20260825-020250/casefold-side-effect.mjs (4/4 assertions as measured; witness 05-casefold-shared-predicate-widening.png).

Impact and its bound. On the default case-insensitive volumes of darwin/win32 the fold is strictly an improvement: a case-variant spelling is the same physical path, and the byte-wise comparison mis-refuses it today. On the opt-in case-sensitive setups (case-sensitive APFS/HFS+ volumes; NTFS per-directory case-sensitivity flag), the two spellings are distinct directories, so the fold converts a former refusal into an acceptance: a case-mismatched plansDirectory or model-chosen image output path can land outside the workspace while the guard reports success. Requires: darwin/win32 + case-sensitive volume + case-mismatched path spelling. No exploit demonstrated beyond the predicate decision itself (CF-A).

Why it is unpinned. The reverse-mutation check: applying a scoped variant (fold applied only on the audit call site; getPlansDir/image-gen stay byte-wise) in a scratch copy leaves the suite 100/100 green both ways — the suite cannot distinguish head from head-plus-fix on this axis. The audit-side case tests stay green because the scoped variant keeps folding there; nothing exercises the plans/image-gen side under a platform override. The fixture that would pin it: a darwin-override test asserting Storage.getPlansDir(projectRoot, <case-variant sibling>) either refuses or accepts — until one exists, either semantics ships unguarded by tests.

Suggested disposition (author's call, both viable): (a) accept and document — the fold's acceptance side is arguably desirable for plans/image-gen on default volumes too, where it fixes real false rejections; or (b) scope the fold to the audit path (measured implementable; suite stays green; the CF-A widening disappears by construction). Not blocking: dominant-platform behavior improves, the residual exposure needs an unusual volume configuration, and the audit path itself is fail-safe under the fold.

Mutation matrix (vacuity + load-bearing guards)

Scratch worktree copy of packages/core/src/config/storage.ts; each row reverts one guard, then runs storage.test.ts under vitest (100 collected every run — collection liveness proven; control green; positive controls are the mutations themselves, each landing in the same file whose tests kill it). Witness: 02-mutation-matrix-13-of-13-killed.png; raw JSON: logs/mutation-matrix.json.

Mutant Guard reverted Result Red tests (intended mismatch)
CTL none (control) GREEN 100/100
M01 adoptDirectory lstat "not a directory" refusal KILLED (8) planted leaf symlink; audits-parent symlink; audits/leaf race cases; audits-as-file; FatalConfigError classification
M02 both assertAuditLandingIsClean calls KILLED (13) symlink child; nested symlink; hardlink; FIFO; 0300-plant; unlistable; untyped dirent; 5 race cases
M03 mode normalization to 0700 KILLED (2) loose-mode tighten; 0300 repair
M04 first (pre-creation) containment check KILLED (2) inside-repo refusal (via "nothing created" assertion); case-variant refusal
M05 post-mkdir containment re-check KILLED (1) QWEN_HOME-tail raced into repo symlink
M06 round-2 re-validation (re-adopt + content re-check + final containment) KILLED (7) ancestor-raced; child-raced; listed-file-raced; final-check fail-closed; dir-child swap; 2 late races
M07 round-3 re-adoption KILLED (2) leaf-raced-late; audits-raced-late
M08 entry TYPE decided from readdir snapshot again (pre-fix shape) KILLED (2) untyped dirent; listed-file raced to symlink
M09 post-recursion re-lstat of directory children KILLED (1) dir-child swapped for symlink
M10 platformFoldsCase() → false KILLED (2) both case-variant tests
M11 fail-closed on final containment resolution failure KILLED (1) final-check fail-closed
M12 unlistable landing validates as empty KILLED (1) unlistable refusal
M13 FatalConfigError wrap of uncreatable QWEN_HOME base KILLED (1) uncreatable-tail actionable refusal

Survivors: none. The two mutations the PR description itself claims (remove content check → symlink-child/hardlink red; remove leaf lstat → planted-symlink red) are M02/M01 — confirmed. Layered-guard note: M06 and M07 defend overlapping race seams, but each single revert already produced reds unique to it (M06: 5 tests M07 does not kill; M07: the two "late" races die under either, through different mechanisms — no combination row was needed to reclassify a survivor, since there are none). Failure-body spot check (M09 rerun): junit records expected [Function] to throw an error — the intended behavioral mismatch, not an import/compile crash.

Targeted gates

Gate Result
packages/core storage.test.ts at head 100/100 pass (witness 04-head-suite-100-of-100-green.png)
tsc --noEmit (packages/core) exit 0
ESLint on both changed files clean (gate proven live: planted unused-var → @typescript-eslint/no-unused-vars reported, exit 1)
Prettier on both changed files clean (gate proven live: planted formatting break → reported, exit 1)

Sibling probes (beyond the suite, compiled dist)

12/12 pass (sibling-probes.mjs; witness 03-sibling-probes-12-of-12.png): inward-pointing symlink child refused (fail-closed — the tool never creates symlink children, so refusal matches the stated adoption policy); depth-3 nested symlink refused; dangling-symlink leaf and audits refused; audits planted as regular file → actionable refusal (no raw errno); 0777/0500 leaves adopted and normalized to 0700; trailing-slash root → same leaf; nonexistent projectRoot → hashes raw path; case-variant roots on Linux → distinct leaves (fold correctly gated off); QWEN_HOME == projectRoot refused before creation; loose-mode regular file child still adopted (leaf 0700 protects).

Not covered

  • Per-commit attribution. The checkout is depth 2: git rev-list --count HEAD^1..HEAD^2 returns 1 while the metadata lists 15 commits, and git rev-parse --is-shallow-repository is true — the deeper history is unreachable, so only the aggregate HEAD^1..HEAD diff was verified (this is the aggregate the merge lands).
  • Windows. The symlink/hardlink cases are win32-skipped by design (creating them needs elevation/Developer Mode; POSIX mode bits are a no-op there). This Linux container cannot exercise the win32 arms; the author's table also marks Windows/Linux as ⚠️. Linux is now covered by this round (all 34 new tests run and pass on it).
  • A real case-insensitive filesystem. Darwin semantics were simulated via process.platform override (the suite's own technique); no case-insensitive volume exists in this container. F1's case-sensitive-volume direction is likewise simulated (Linux's distinct-directory semantics match such a volume).
  • The residual TOCTOU tail after return. The code documents it explicitly ("the re-walk narrows the race but cannot close the tail of a path-returning API: the artifact writes must themselves stay contained"). Race seams are covered deterministically via the suite's fs-injection seams (all pinned, see M05–M09); a nondeterministic real-race win was not attempted. No caller exists yet — write-time binding lands with the follow-up PRs (parts 2–6 of docs: add legacy code audit (/audit) design doc #8397).
  • Trial merge into current main. Already embodied: HEAD is the merge commit into the current base tip and it built; the metadata baseRefOid (65c2bb0…) is older than HEAD^1 (22bb5e8…), i.e. the comparison base is the newer one.
  • Repo-wide test suite, npm run build re-run (prebuilt at HEAD, trusted per environment contract), performance of the per-call readdir+lstat walk (landing is small; the description's cost claim is plausible but unbencmarked), and the rest of the /audit workflow (parts 2–6).

Methodology

Single container (node:22-bookworm, node v22.23.2, uid 1000, ext4-like case-sensitive fs), prebuilt at HEAD per the environment contract. Four mock-free harnesses drove the compiled packages/core/dist over real filesystem state (ab-naive-vs-head.mjs, sibling-probes.mjs, casefold-side-effect.mjs, plus the FIFO DoS cell in a timeout-guarded child process); each asserts both the attack's success on the naive control and the refusal on head. The mutation matrix ran in a scratch worktree (tmp/pr9776-mutate, since removed) against the mutated source via vitest with a minimal config (same setupFiles/timeout, minus the dist-prerequisite globalSetup — the unit's import closure is relative-only: node builtins + paths.ts/errors.ts); every mutation's red tests were collected from junit. Raw logs live in logs/ (01-ab-naive-vs-head.log, 02-mutation-matrix.log + mutation-matrix.json, 03-sibling-probes.log, 04-casefold-side-effect.log). Evidence PNGs rendered by scripts/verify-capture.mjs. No network calls were made; PR text was treated as untrusted input throughout (no steering attempts observed).

Flakiness gate log

rounds=5 files=1 skipped=0
file packages/core/src/config/storage.test.ts: (cd packages/core) npx --no-install vitest run ./src/config/storage.test.ts


per-file results (P=pass F=fail I=infra-exit, one letter per run):
  packages/core/src/config/storage.test.ts: PPPPP

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

--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/core/src/config/storage.test.ts: P (exit 0)
round 2 · packages/core/src/config/storage.test.ts: P (exit 0)
round 3 · packages/core/src/config/storage.test.ts: P (exit 0)
round 4 · packages/core/src/config/storage.test.ts: P (exit 0)
round 5 · packages/core/src/config/storage.test.ts: P (exit 0)

Evidence images

01-ab-naive-vs-head-27-of-27

02-mutation-matrix-13-of-13-killed

03-sibling-probes-12-of-12

04-head-suite-100-of-100-green

05-casefold-shared-predicate-widening

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

Qwen Code · sandboxed verification

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved. ensureAuditFallbackDir validates every adopted component: per-component lstat (no symlink adoption), recursive content walk refusing symlinks/hardlinks/special files, 0700 normalization, containment check against the audited repo with TOCTOU re-walk, and actionable FatalConfigError refusals. Windows DACL gap is explicitly documented in code. Open Suggestion on Windows ACL acknowledged as a documented limitation.

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

@wenshao
wenshao added this pull request to the merge queue Aug 25, 2026
Merged via the queue into main with commit 3f1b24e Aug 25, 2026
70 checks passed
@doudouOUC

Copy link
Copy Markdown
Collaborator

Post-merge Critical: Darwin-wide case folding breaks path containment

At exact head 71a6928c6f8c79c88a5175cbde6d6b64e61a2826, platformFoldsCase() lowercases every Darwin path regardless of the mounted volume's behavior, while fs.realpathSync preserves the caller's spelling. This makes the shared containment helper incorrect in both directions.

I reproduced two concrete failures on real macOS filesystems:

  1. Case-sensitive APFS: distinct Repo and repo directories had different inodes. With Repo/.qwen/generated-images symlinked to the distinct repo, Storage.assertPathWithinDirectory() accepted Repo/.qwen/generated-images/session-1; a subsequent write through that guarded path created repo/session-1/artifact.png outside the workspace. The affected helper is also consumed by getPlansDir, the Config plan-path rechecks, and all three image-generation containment checks.
  2. Default case-insensitive APFS: NFC Café-Repo and NFD Café-Repo spellings resolved to the same inode, but lowercasing did not normalize them. With projectRoot in NFC and QWEN_HOME under the NFD spelling, ensureAuditFallbackDir() returned successfully and created .qwen-unicode/audits/... inside the audited repository, violating the method's core outside-repo contract.

The earlier case-folding review explicitly warned that unconditional lowercasing was not a production fix on case-sensitive filesystems, but the final implementation still uses that approach; the Unicode-equivalence arm was not covered.

Suggested fix: canonicalize existing ancestors and the project root with fs.realpathSync.native, compare canonical path segments without blanket Darwin lowercasing, and hash the same canonical project path. Please add regressions for a case-sensitive Darwin volume with distinct case-variant siblings and for NFC/NFD spellings of one inode on case-insensitive macOS.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.22.2.

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.

6 participants