Skip to content

feat(triage): add sandboxed /verify deep-verification lane#7710

Open
wenshao wants to merge 14 commits into
mainfrom
feat/triage-verify-lane
Open

feat(triage): add sandboxed /verify deep-verification lane#7710
wenshao wants to merge 14 commits into
mainfrom
feat/triage-verify-lane

Conversation

@wenshao

@wenshao wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds an on-demand deep-verification lane to the triage workflow: commenting @qwen-code /verify on a PR now runs a maintainer-grade evidence round against the PR's real build — an A/B load-bearing proof against the base side, a vacuity check on new tests, mock-free wire-oracle harnesses, and targeted workspace gates — and publishes the report back to the PR as one upserted comment (live "running" status → final report). The report is explicitly advisory evidence for human reviewers: it is never a review, an approval, or a CI check.

Concretely: two new jobs in qwen-triage.yml (verify executes the PR inside the same isolation contract as the existing /tmux job — container, no GitHub token in the agent env, model key behind a loopback proxy that only allows POST /chat/completions, gated on write permission from both the PR author (whose code runs) and the commenter (who spends a scarce runner slot plus a model budget); publish-verify posts the report from a clean hosted runner that never checks out PR code), plus a new verify-pr skill encoding the methodology and artifact contract, and a Stage 2c update so the static triage agent recommends /verify when a PR's central claim needs behavioral evidence.

Hardening built in from the start: the agent's skill is pinned from the base branch via git archive HEAD^1 so the tree under test can never rewrite its own verifier; PR-committed tmp/*-verify-* directories are deleted after checkout so a PR cannot pre-plant a fake report that the artifact collector would publish; the persistent self-hosted workspace gets the same git exec-vector sweep (config allowlist + hook removal) the triage job already uses; and the agent-written verdict is allowlisted (merge-ready|findings|blocked|inconclusive) before it touches workflow outputs.

The second commit folds in patterns from recent hand-run verification rounds (#7632 round 2, #7656): re-running /verify is a follow-up round — the resolve step snapshots the previous report before overwriting it, and the skill re-checks each prior finding at the new head (fixed/stands/superseded); harnesses prefer configuration seams (a baseUrl, an env var) over module interception with the fake peer encoding the upstream's real semantics; multi-commit PRs get per-commit load-bearing tables; workflow/CI PRs get embedded-script replay against real data, the repo's own lint gates, and day-one trigger cost math from real event history; blockers enumerate their blast radius and carry a collapsed minimal suggested fix.

The third commit adds image evidence, borrowing the layout and hosting conventions from image-bearing PRs and rounds (#7265, #7471, #7686 round 2): the agent may save evidence/*.png (kebab-case filenames that double as claim-binding captions; before/after pairs preferred), and publish-verify hosts them on the pr-assets branch under verify/pr<N>-<run>-<attempt>/ and renders them below the escaped report. Untrusted-payload discipline throughout: strict filename allowlist, 8-image / 2 MB caps, racing-push retry, and any hosting failure degrades to a text-only comment. It also encodes the quantified-verification rules from #7686 round 2: follow-up rounds lead with a previous-finding status table and re-measure instead of diffing the old report; size/perf claims get measured-metric Δ tables with every residual delta accounted for; unreachable branches get the configuration that reaches them constructed; defensive guards get their accept path verified against real production artifacts, not just mocked rejects.

Why it's needed

The triage agent is static-analysis-only by design — its environment carries a write PAT, so it must never execute PR code, and its test evidence is limited to reading the PR's own CI. The only behavioral lane today, /tmux, is scoped to TUI surfaces and text captures. Maintainers currently produce deep verification rounds (A/B against base, wire oracles, load-bearing proofs — e.g. the round-3 verification on #7586) entirely by hand. This PR makes that style of evidence available on demand in CI, with the isolation guarantees the hand-run version doesn't need to think about, and without widening the existing approval surface: the verify check-runs ride the issue_comment event, which the finalize workflow's event == "pull_request" universe structurally excludes from both the CI table and the deferred-approval gate.

Reviewer Test Plan

How to verify

Static/replay verification (all reproducible locally):

  • node scripts/lint.js --actionlint and yamllint with the repo config pass; the only shellcheck classes actionlint reports (SC2016/SC2129) are in the lint script's explicit ignore set and pre-exist in the cloned tmux blocks.
  • All 13 run: blocks belonging to this lane (authorize, verify, publish-verify), extracted from the YAML, pass bash -n and shellcheck -S warning; the embedded loopback-proxy JS passes node --check. The independent Linux replication extended this to all 29 blocks in the workflow.
  • The publish-verify script was executed (not just read) across all six terminal branches — cancelled, infra-failure, skipped, n/a, prepare-fail, report — with a stubbed gh; the rendered bodies are correct and report content containing </code></pre></details>, @everyone, and <img onerror=…> stays fully entity-escaped inside the <details><pre><code> block.
  • The verdict allowlist rejects junk/injection strings (PWNED @everyone, findings; rm -rf / → discarded); the assertions jq coerces non-numeric JSON ({"pass":"<script>"}) to zeros; the docs-only decision grep was replayed against mixed/docs-only/empty file lists with GNU grep semantics.

Live end-to-end run (local replica of the CI job, faithful to every contract knob — merge-ref worktree of #7547 at depth-2 parents, .qwen pinned from this branch, QWEN_VERIFY_CONTEXT metadata snapshot, credential-less gh, isolated QWEN_HOME): the agent (qwen3.8-max-preview) completed in 25 turns / 3.5 minutes API time, produced every artifact in the contract, and returned verdict merge-ready with 318/318 assertions. The numbers were then audited adversarially: 318 = 304 real vitest tests (23+68+213 across three targeted gate files, log-verified) + 13 A/B assertions + 1 vacuity check; re-running the agent's own ab-harness.mjs reproduced 13/13; reverting the PR's fix and re-running that same harness went exactly 7/13 (the 3 PR-side and 3 flip assertions failed), and restoring returned 13/13 — proving the A/B senses the fix rather than comparing a file to itself. The agent made zero gh invocations. Feeding the real artifacts through the actual publish-verify script rendered the exact 4.7 KB comment CI would post.

Evidence (Before & After)

Agent's A/B harness, rerun by hand at head and under mutation (fix reverted, then restored):

=== A/B SUMMARY: 13 passed, 0 failed, 13 total ===   # head, as the agent reported
=== A/B SUMMARY: 7 passed, 6 failed, 13 total ===    # fix reverted → harness goes red
=== A/B SUMMARY: 13 passed, 0 failed, 13 total ===   # fix restored

Publish rendering of the real run's artifacts (headline of the comment CI would post):

**Sandboxed verification: merge-ready (agent verdict)** - [workflow run](…)
Scripted assertions: 318 passed · 0 failed · 318 total

Tested on

OS Status
🍏 macOS
🪟 Windows N/A
🐧 Linux ✅ static/replay · ⚠️ live run

Linux detail: the static and replay layer (YAML parse, 36/36 workflow tests, all 29 extracted run: blocks through bash -n, both proxy heredocs through node --check, and the verdict-allowlist replay) was independently replicated on Linux at c25afbd8 with zero failures. What stays untested there is the live path — the jobs running on a real Actions runner with the runner secrets — which nothing before merge can cover.

Environment (optional)

macOS 15 / Node 22 / qwen CLI 0.20.1; agent model qwen3.8-max-preview (DashScope); verification worktree built with a real npm ci + npm run build from the PR lockfile.

Risk & Scope

  • Main risk or tradeoff: the workflow jobs themselves have not yet executed on a live Actions runner (Linux row above: the static/replay layer is independently replicated there, the live path is not) — the lane is opt-in comment-triggered, per-PR concurrency-isolated, and every failure mode (skip, docs-only, install/build failure, infra error, cancel) publishes an explicit comment instead of silence, so a bad first run is visible and contained. The loopback-proxy/agent machinery is duplicated from the tmux job rather than extracted; a shared-steps refactor is a deliberate follow-up to keep this change additive.
  • Not validated / out of scope: live ECS/container execution; screenshot publishing to pr-assets (v1 ships text + run artifacts); the adjacent pre-existing gap that the tmux job's *-tmux-* artifact collection can likewise be spoofed by PR-committed directories — same attack class fixed here for verify, left for a separate PR on the tmux side.
  • Breaking changes / migration notes: none; purely additive (new comment command, new skill, one new recommendation sentence in the triage skill).

Linked Issues

The methodology this encodes is the hand-run deep-verification style used on recent PRs (e.g. the round-3 verification comment on #7586). No issues closed.

中文说明

本 PR 做了什么

为 triage workflow 增加一条按需触发的深度验证车道:在 PR 上评论 @qwen-code /verify,即可对该 PR 的真实构建执行一轮维护者级别的证据验证——与 base 侧的 A/B load-bearing 对照、新增测试的空测检查、无 mock 的 wire-oracle harness、以及受影响 workspace 的定向门禁——并把报告以单条评论("运行中"状态 → 最终报告原位升级)发回 PR。报告明确定位为供人类评审者参考的证据:它永远不是 review、不是批准、也不是 CI 检查。

具体实现:qwen-triage.yml 新增两个 job(verify 在与现有 /tmux 完全相同的隔离契约下执行 PR 代码——容器、agent 环境无任何 GitHub token、模型 key 藏在只放行 POST /chat/completions 的 loopback 代理后、要求 PR 作者(其代码被执行)评论者(其消耗稀缺 runner 与模型预算)双方都具有写权限;publish-verify 在干净的 hosted runner 上发布报告,绝不 checkout PR 代码),加上一个新的 verify-pr skill 固化方法论与产物契约,以及 Stage 2c 的更新,使静态 triage agent 在 PR 的核心声明需要行为证据时主动推荐 /verify

内置的安全加固:agent 的 skill 通过 git archive HEAD^1 从 base 分支 pin 取,被测代码树无法改写自己的验证器;checkout 后立即删除 PR 预埋的 tmp/*-verify-* 目录,杜绝伪造报告被产物收集器发布;持久 self-hosted workspace 沿用 triage job 的 git exec-vector 清扫(config 白名单 + hook 清除);agent 写出的 verdict 经白名单(merge-ready|findings|blocked|inconclusive)过滤后才进入 workflow 输出。

第二个提交把近期手工验证轮次(#7632 第 2 轮、#7656)的模式固化进车道:重复触发 /verify 即为后续轮次——resolve 步骤在覆盖前快照上一份报告,skill 在新 head 上逐项复核既往发现(已修复/仍存在/已被取代);harness 优先使用配置级 seam(baseUrl、环境变量)而非模块拦截,且伪造对端需编码上游的真实语义;多 commit PR 逐 commit 出 load-bearing 表;workflow/CI 类 PR 用真实数据回放内嵌脚本、跑仓库自身 lint 门禁、并用真实事件历史做上线首日成本测算;阻断级发现需枚举影响面并附保持原提交意图的最小修复建议(折叠展示)。

第三个提交增加图片证据能力,借鉴带图 PR 与验证轮次(#7265#7471#7686 第 2 轮)的版式与托管惯例:agent 可产出 evidence/*.png(kebab-case 文件名即绑定断言的图注;优先 before/after 成对),publish-verify 将其托管到 pr-assets 分支 verify/pr<N>-<run>-<attempt>/ 目录并在转义报告下方渲染。全程按不可信载荷处理:严格文件名白名单、8 张 / 单张 2 MB 上限、竞争推送重试、托管失败一律降级为纯文本评论。同时固化 #7686 第 2 轮的量化验证规则:后续轮次以既往发现状态表开篇并重新测量(而非对比旧报告);体积/性能类声明用带 Δ 列的实测指标表且残差必须解释;默认配置下不可达的分支要构造出能触达它的配置;防御性 guard 的接受路径要用真实生产产物验证,而非只测被 mock 的拒绝路径。

为什么需要

triage agent 在设计上只做静态分析——其环境携带写权限 PAT,绝不能执行 PR 代码,测试证据只能来自读取 PR 自己的 CI。目前唯一的行为验证车道 /tmux 仅覆盖 TUI 表面和文本捕获。维护者现在完全靠手工产出深度验证轮次(对 base 的 A/B、wire oracle、load-bearing 证明——例如 #7586 上的第 3 轮验证)。本 PR 把这种证据风格变成 CI 里按需可得的能力,自带手工验证无需操心的隔离保证,并且不扩大现有审批面:verify 的 check-run 挂在 issue_comment 事件上,finalize workflow 的 event == "pull_request" 过滤在结构上将其排除在 CI 表格与延迟审批门禁之外。

评审验证方案

如何验证

静态/回放验证(均可本地复现):node scripts/lint.js --actionlint 与仓库配置的 yamllint 通过;从 YAML 抽出的、属于本车道的全部 13 个 run: 块(authorize、verify、publish-verify)通过 bash -nshellcheck -S warning(第三方 Linux 复现进一步覆盖了整个 workflow 的 29 个块);内嵌 loopback 代理 JS 通过 node --checkpublish-verify 脚本用 stub gh 在全部六种终态分支上真实执行过,含 </code></pre></details>@everyone<img onerror=…> 的报告内容在 <details><pre><code> 中保持完全实体转义;verdict 白名单拒绝注入串;assertions jq 把非数字 JSON 强制为 0;docs-only 判定 grep 用 GNU grep 语义在混合/纯文档/空文件列表上回放。

真实端到端运行(本地忠实复刻 CI job 的全部契约:#7547 的 merge-ref worktree、depth-2 父提交、.qwen 从本分支 pin、QWEN_VERIFY_CONTEXT 元数据快照、无凭证 gh、隔离 QWEN_HOME):agent(qwen3.8-max-preview)25 turns / API 3.5 分钟完成,产物契约全部满足,verdict merge-ready,318/318 断言。随后对数字做了对抗式审计:318 = 304 个真实 vitest 测试(23+68+213,日志核对)+ 13 个 A/B 断言 + 1 个空测检查;亲手复跑 agent 的 ab-harness.mjs 得到 13/13;回退 PR 修复后复跑同一 harness 精确变为 7/13(恰为 3 个 PR 侧断言 + 3 个 flip 断言失败),恢复后回到 13/13——证明 A/B 真实感知修复而非同文件自比。agent 全程 0 次 gh 调用。把真实产物喂给真正的 publish-verify 脚本,渲染出 CI 将要发布的 4.7 KB 评论。

证据(Before & After)

见英文部分的 harness 复跑与变异测试输出,以及发布渲染的评论头部。

测试平台

macOS ✅;Windows N/A;Linux:静态与回放层 ✅——YAML 解析、36/36 workflow 测试、29 个抽取的 run: 块过 bash -n、两处代理 heredoc 过 node --check、verdict 白名单回放,均已由第三方在 c25afbd8独立复现且零失败;实际运行层仍 ⚠️(workflow 尚未在真实 Actions runner 上带 secret 执行,这部分在合并前无法由任何复现覆盖)。

环境

macOS 15 / Node 22 / qwen CLI 0.20.1;agent 模型 qwen3.8-max-preview(DashScope);验证 worktree 用 PR lockfile 真实 npm ci + npm run build 构建。

风险与范围

  • 主要风险/权衡:workflow job 本身尚未在真实 Actions runner 上跑过(上表 Linux 行:静态/回放层已被第三方独立复现,实际运行层尚未)——该车道为评论触发的 opt-in、按 PR 并发隔离,且所有失败模式(skip、纯文档、安装/构建失败、infra 错误、取消)都会发布显式评论而非沉默,首次运行即使出问题也可见且可控。loopback 代理/agent 机制从 tmux job 复制而未抽取公共步骤——为保持本次改动纯增量,共享步骤重构留作后续。
  • 未验证/范围外:真实 ECS/容器执行;截图发布到 pr-assets(v1 只有文本 + run artifacts);相邻的既有缺口——tmux job 的 *-tmux-* 产物收集同样可被 PR 预埋目录伪造(与本 PR 为 verify 修复的是同一攻击类),留待 tmux 侧单独 PR。
  • 破坏性变更/迁移说明:无;纯增量(新评论命令、新 skill、triage skill 一句推荐语)。

关联 Issue

本 PR 固化的方法论即近期 PR 上手工执行的深度验证风格(如 #7586 的第 3 轮验证评论)。不关闭任何 issue。

@qwen-code /verify on a PR now runs a local-verification-style evidence
round in the isolated /tmux sandbox contract (container, token-free agent
env, loopback model proxy, author-write gate) and publishes the report via
a separate PR-code-free job:

- new verify job: merge-ref checkout at depth 2 (base tip + PR head for
  A/B), skills pinned from base so the tree under test can never rewrite
  its own verifier, PR-planted tmp/*-verify-* artifacts dropped, git
  exec-vector sweep for the persistent workspace, agent verdict
  allowlisted before it reaches workflow outputs
- new publish-verify job: upserts one marker comment (running status ->
  final report), HTML-escapes the untrusted report, reports skip/na/
  prepare-fail/infra outcomes explicitly since /verify is always an
  explicit request
- new verify-pr skill: A/B load-bearing proof, vacuity check on new
  tests, mock-free wire-oracle harnesses, targeted gates, fixed report/
  verdict/assertions artifact contract, counts-are-sacred rules
- triage skill Stage 2c now names /verify (not just /tmux) as the trigger
  to recommend when a PR's central claim needs behavioral evidence

The verify check-runs ride the issue_comment event, which the finalize
workflow's event == "pull_request" universe structurally excludes, so
they cannot pollute the CI table or the deferred-approval gate.
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Qwen Triage finished — CI landed green on 9dde0ce and the deferred approval was posted. finalize run

Qwen Triage 已完成 —— 9dde0ce 的 CI 全绿,延迟审批已提交。查看 finalize 运行

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed workflow gap — maintainers currently produce deep verification rounds (A/B against base, wire oracles, load-bearing proofs) entirely by hand, with specific examples cited (#7632 round 2, #7656, #7586 round 3). This is a real, recurring cost, not a theoretical concern.

Direction: aligned. The project has been building toward deeper verification for a while (local PR verification gate in #6873, review Step 4/5 evidence in #6965, triage verification scaling in #7648). A sandboxed on-demand lane is the natural next step, and it stays within the existing triage/CI infrastructure scope. CHANGELOG references confirm the trajectory.

Size: no core paths touched — all changes are in .github/workflows/ and .qwen/skills/. 1134 additions across 3 files; the 1000+ advisory applies, but this is a single cohesive CI lane (workflow jobs + skill definition + triage reference update) — splitting would fragment the isolation contract across PRs and make each harder to review in isolation.

Approach: the scope feels right. The verify job mirrors the existing /tmux isolation contract (container, no token, loopback proxy, author-gated), and the publish-verify split keeps the write PAT away from PR code — same architecture as publish-tmux. The skill file encodes the methodology without over-specifying. One question worth thinking about: the loopback proxy JS and the configure_qwen_network shell function are duplicated between the tmux and verify jobs — if a third lane ever appears, extracting those into a shared step or action would reduce drift. Not a blocker for this PR.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的工作流缺口——维护者目前完全手工执行深度验证轮次(与 base 的 A/B 对照、wire oracle、承重证明),PR 中引用了具体案例(#7632 第 2 轮、#7656#7586 第 3 轮)。这是真实的、反复出现的成本,不是理论性问题。

方向:对齐。项目一直在向更深层的验证能力演进(#6873 的本地 PR 验证门禁、#6965 的 review Step 4/5 证据、#7648 的 triage 验证深度扩展)。沙箱化的按需验证通道是自然的下一步,且保持在现有 triage/CI 基础设施范围内。CHANGELOG 引用确认了这一轨迹。

规模:未触及核心路径——所有改动在 .github/workflows/.qwen/skills/ 中。3 个文件共 1134 行新增;1000+ 大 PR 建议适用,但这是一个内聚的 CI 通道(工作流 job + skill 定义 + triage 引用更新)——拆分会将隔离契约分散到多个 PR,每个都更难独立审查。

方案:范围合理。verify job 复用了现有 /tmux 的隔离契约(容器、无 token、回环代理、作者权限门控),publish-verify 的拆分使写入 PAT 远离 PR 代码——与 publish-tmux 架构一致。skill 文件编码了方法论但没有过度指定。一个值得思考的问题:回环代理 JS 和 configure_qwen_network shell 函数在 tmux 和 verify job 之间是重复的——如果出现第三个通道,将它们提取为共享 step 或 action 可以减少漂移。不阻塞本 PR。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal: for an on-demand sandboxed verification lane, I'd add a /verify trigger to the existing authorize gate, create a verify job that reuses the /tmux isolation contract (container, no token, loopback proxy, author-gated), pin the agent's skill from the base branch so the tree under test can't rewrite its own verifier, and split publication into a clean-runner publish-verify job. Plus a skill file encoding the methodology and a Stage 2c reference update.

Comparison: the PR matches this approach almost exactly. The architecture is the established tmux pattern applied to a new lane — same container, same proxy, same publish split, same concurrency model. No simpler path was missed.

No critical blockers found. Specific observations:

  • Security model is sound. Agent inputs pinned from base via git archive HEAD^1 (a PR can't rewrite its own verifier); pre-planted tmp/*-verify-* dirs deleted after checkout; git exec-vector sweep (config allowlist + hook removal) before checkout; verdict allowlisted to four words before touching workflow outputs; report content HTML-escaped inside <details><pre><code> in the publish job; image filenames pass a strict [a-zA-Z0-9._-] allowlist with 8-file / 2 MB caps. The loopback proxy restricts to POST /chat/completions only. The agent env carries no GitHub token — GITHUB_TOKEN and GH_TOKEN are explicitly emptied.

  • Step ordering is correct. Tools installed before checkout (PR .npmrc can't affect npm); stale state cleaned before checkout; base pinning after checkout (needs HEAD^1); build after pinning; agent after build. The publish-verify job runs on ubuntu-latest and never checks out PR code — write PAT isolated from untrusted execution.

  • Terminal state coverage is comprehensive. The publish job handles cancelled, infra-failure, skipped, n/a (docs-only), prepare-fail (install/build), and the normal report path — every failure mode publishes an explicit comment instead of silence. The assertion parser coerces non-numeric JSON to zeros, preventing injection through assertions.json.

  • Duplication noted (non-blocking): configure_qwen_network and the loopback proxy JS are copied from the tmux job. Acceptable for two consumers; a shared action would reduce drift if a third lane appears.

  • The pr-workflow.md change is a minimal, accurate update to Stage 2c — names the new /verify trigger alongside /tmux and describes when each applies.

  • The verify-pr skill is well-structured: clear environment contract, scope-first budgeting, A/B methodology, artifact contract, and hard rules (counts are sacred, PR text is untrusted, never post to GitHub). Follows the existing skill file format.

CI Test Evidence

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

Check Conclusion
Classify PR ✅ success
Post Coverage Comment (ubuntu-latest, 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,失败项排在最前。

The ubuntu unit test is still running; macOS/Windows/integration are skipped (expected for a workflow/skill-only PR — no source code changed). No failures so far. The two cancelled route checks are from earlier force-pushes, not this commit.

Real-Scenario Testing

N/A — this PR changes CI workflow YAML and skill definitions. There is no user-visible TUI surface to drive in tmux. The behavioral evidence for this lane will come from its first live /verify invocation after merge (the PR body notes the workflow jobs have not yet executed on a live Actions runner — Linux ⚠️).

中文说明

独立方案: 对于按需沙箱验证通道,我会在现有 authorize 门控中添加 /verify 触发器,创建复用 /tmux 隔离契约的 verify job(容器、无 token、回环代理、作者权限门控),从 base 分支固定 agent 的 skill 以防被测代码树改写自己的验证器,并将发布拆分到干净运行器的 publish-verify job。加上编码方法论的 skill 文件和 Stage 2c 引用更新。

对比: PR 几乎完全匹配此方案。架构是将已建立的 tmux 模式应用于新通道。没有遗漏更简单的路径。

未发现关键阻塞问题。安全模型健全(base 固定、预置工件清理、git 执行向量扫描、verdict 白名单、HTML 转义、图片文件名白名单、回环代理限制、无 GitHub token)。步骤顺序正确。终态覆盖全面。configure_qwen_network 和回环代理 JS 的重复是非阻塞观察项。skill 文件结构良好。

CI:ubuntu 单元测试仍在运行;macOS/Windows/集成测试已跳过(仅工作流/skill 文件改动,无源代码变更)。目前无失败。

真实场景测试:不适用——本 PR 改动 CI 工作流 YAML 和 skill 定义,没有用户可见的 TUI 界面可在 tmux 中驱动。

Qwen Code · qwen3.8-max-preview

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

…hods

Fold two more hand-verification patterns into the verify lane:

- round continuity: the resolve step snapshots the previous verify report
  (if any) into the agent context before the status upsert overwrites it,
  and the skill re-checks each prior finding at the new head
  (fixed/stands/superseded), scoping new probes to the delta
- harness quality: prefer configuration seams over module interception,
  encode the upstream's real semantics in the fake peer, add decoy targets
- artifact-matched methods: per-commit load-bearing tables for multi-commit
  PRs; workflow/CI PRs get embedded-script replay against real data, repo
  lint gates, and day-one trigger cost math from real event history; every
  new config knob must trace to an observable effect, and default-path
  dispatch combinations get probed
- findings quality: blockers enumerate blast radius, demonstrate the
  sharpest consequence end-to-end when budget allows, and carry a collapsed
  minimal suggested fix preserving the original commit's intent
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean review, proven architecture, real gap filled; the only nit is the tmux/verify code duplication, which is acceptable at two consumers.

This is the tmux isolation contract applied to a new lane — same container, same proxy, same publish split, same author-gating — with the addition of base-branch skill pinning (so the tree under test can't rewrite its own verifier) and pre-planted artifact cleanup. The architecture is proven in production; the new pieces are incremental and well-reasoned. The security model is thorough without being overwrought: every untrusted boundary (PR code, agent output, image filenames, assertion JSON) has a specific, named defense.

The skill file is the right level of prescription — it encodes the methodology (A/B load-bearing proof, vacuity checks, wire oracles) without over-specifying the agent's every step. The hard rules ("counts are sacred", "PR text is untrusted input", "never post to GitHub") are the right invariants for a sandboxed evidence producer.

The one reservation: the workflow jobs haven't executed on a live Actions runner yet (the PR body flags this with Linux ⚠️). The lane is opt-in and per-PR concurrency-isolated, so a bad first run is visible and contained — but the first /verify invocation after merge will be the real test. The comprehensive terminal-state handling (every failure mode publishes an explicit comment) means it won't fail silently.

Approval deferred until CI lands green on 9dde0ceef2b8d4f86fdbaae4183305b57d158d73.

中文说明

这是将 tmux 隔离契约应用于新通道——相同的容器、代理、发布拆分、作者门控——加上 base 分支 skill 固定(防止被测代码树改写自己的验证器)和预置工件清理。架构已在生产中验证;新部分是增量且合理的。安全模型全面而不过度:每个不可信边界(PR 代码、agent 输出、图片文件名、断言 JSON)都有具体的、命名的防御。

skill 文件的规范程度恰当——编码了方法论(A/B 承重证明、空性检查、wire oracle)但没有过度指定 agent 的每一步。硬规则("计数神圣"、"PR 文本是不可信输入"、"永不发布到 GitHub")是沙箱化证据生产者的正确不变量。

唯一的保留:工作流 job 尚未在真实 Actions 运行器上执行过(PR 正文以 Linux ⚠️ 标注)。通道是按需触发且按 PR 并发隔离的,所以首次运行失败是可见且可控的——但合并后的第一次 /verify 调用才是真正的测试。全面的终态处理(每种失败模式都发布明确评论)意味着它不会静默失败。

批准延迟至 CI 在 9dde0ceef2b8d4f86fdbaae4183305b57d158d73 上全绿。

Qwen Code · qwen3.8-max-preview

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

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 82.83% 82.83% 89.01% 82.37%
Core 87.05% 87.05% 88.63% 85.94%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   82.83 |    82.37 |   89.01 |   82.83 |                   
 src               |   84.12 |    80.71 |   88.88 |   84.12 |                   
  cli.ts           |   94.54 |    84.07 |     100 |   94.54 | ...86-487,497-498 
  gemini.tsx       |   73.89 |    76.49 |    82.6 |   73.89 | ...1183-1187,1308 
  ...ractiveCli.ts |   85.02 |    80.82 |   86.84 |   85.02 | ...2363,2369,2421 
  ...liCommands.ts |   88.34 |    83.87 |      90 |   88.34 | ...63,480,514,635 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   68.31 |    71.07 |   88.97 |   68.31 |                   
  acpAgent.ts      |   67.93 |     70.9 |   88.98 |   67.93 | ...15,10720-10722 
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   97.04 |    95.71 |   93.33 |   97.04 |                   
  filesystem.ts    |   97.04 |    95.71 |   93.33 |   97.04 | ...21-122,238-239 
 ...ration/session |   91.65 |    85.67 |   95.97 |   91.65 |                   
  Session.ts       |   91.23 |    84.45 |   95.23 |   91.23 | ...8482,8509-8513 
  ...entTracker.ts |   91.87 |    89.18 |   88.88 |   91.87 | ...33,197,280-289 
  ...stop-guard.ts |     100 |    97.05 |     100 |     100 | 37,127,247        
  ...eplay-page.ts |   92.27 |    88.09 |     100 |   92.27 | ...83,108-118,121 
  ...y-replayer.ts |    98.5 |    95.38 |     100 |    98.5 | 229-231           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    86.76 |     100 |   89.76 | ...54-270,326-328 
  tasksSnapshot.ts |   94.26 |     87.5 |     100 |   94.26 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.68 |     93.7 |   96.66 |   95.68 |                   
  ...ageEmitter.ts |   95.34 |    94.11 |     100 |   95.34 | 52-59             
  PlanEmitter.ts   |     100 |    83.33 |     100 |     100 | 59                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   99.17 |    97.43 |     100 |   99.17 | 352-353           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/commands      |   88.74 |    73.18 |   64.51 |   88.74 |                   
  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        |   97.77 |      100 |      50 |   97.77 | 56                
  serve.ts         |   86.44 |     67.3 |     100 |   86.44 | ...08-611,625-629 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   86.91 |    87.02 |   90.44 |   86.91 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   79.31 |    84.61 |      80 |   79.31 | 35-38,47-50,61-64 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.85 |    96.29 |     100 |   95.85 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |    94.2 |    85.09 |   97.82 |    94.2 | ...1155,1162-1163 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.49 |    96.51 |     100 |   98.49 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |   72.85 |      100 |      50 |   72.85 | 22-28,57-68       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   81.42 |    87.71 |     100 |   81.42 | ...70-174,234-236 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |   75.05 |    73.17 |   76.92 |   75.05 | ...31,537-540,552 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.82 |    87.64 |   87.09 |   88.82 |                   
  consent.ts       |   72.53 |       90 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |      75 |    53.84 |     100 |      75 | ...27-131,133-137 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.17 |    84.39 |   83.33 |   90.17 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   92.59 |    83.87 |      80 |   92.59 | ...62-164,180-181 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   79.88 |    86.45 |   80.15 |   79.88 |                   
  agent-prompt.ts  |   90.88 |    92.78 |      96 |   90.88 | ...1256,1726-1795 
  capture-local.ts |   72.16 |     90.9 |      75 |   72.16 | 101-105,152-174   
  ...k-coverage.ts |   48.38 |    14.28 |   66.66 |   48.38 | ...21-226,239-249 
  cleanup.ts       |   64.28 |    45.45 |      50 |   64.28 | ...33-138,140-141 
  ...ose-review.ts |   95.42 |    92.13 |   91.66 |   95.42 | ...1099,1127-1143 
  fetch-pr.ts      |   24.78 |      100 |    12.5 |   24.78 | ...27-326,367-369 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  parse-args.ts    |   99.25 |       96 |     100 |   99.25 | 341,413           
  plan-diff.ts     |    67.9 |      100 |   66.66 |    67.9 | 121-148           
  pr-context.ts    |   84.02 |    76.37 |   91.66 |   84.02 | ...22-903,932-934 
  presubmit.ts     |   74.32 |       82 |   85.71 |   74.32 | ...46-347,399-429 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  submit.ts        |   74.44 |    80.82 |      80 |   74.44 | ...48-584,586-587 
  test-efficacy.ts |   80.68 |    69.41 |    92.3 |   80.68 | ...93-594,602-622 
 ...nds/review/lib |   95.46 |    92.65 |   94.81 |   95.46 |                   
  agent-briefs.ts  |   98.68 |      100 |       0 |   98.68 | 493-494           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  coverage.ts      |   95.37 |    94.08 |   95.45 |   95.37 | ...98,335,429-446 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    92.93 |     100 |   98.73 | ...41,264,290-291 
  gh.ts            |   85.27 |     87.5 |   69.23 |   85.27 | ...01,238-239,266 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |    92.3 |    83.33 |   83.33 |    92.3 | 76-77             
  prompt-record.ts |   94.73 |    88.23 |     100 |   94.73 | ...28,151-152,156 
  report.ts        |   92.13 |    86.66 |     100 |   92.13 | 170-171,173-177   
  roster.ts        |     100 |    92.85 |     100 |     100 | 104,118,163       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.27 |    93.18 |     100 |   96.27 | ...83,269-270,294 
  workspaces.ts    |   97.76 |     91.3 |     100 |   97.76 | 186-187,212-213   
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.51 |    88.67 |    95.5 |   94.51 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   88.32 |    88.21 |   84.84 |   88.32 | ...2379,2381-2389 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |    94.2 |    89.47 |   94.73 |    94.2 | ...24-628,644-645 
  ...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.74 |     100 |     100 | 47,160,220        
  keyBindings.ts   |   97.38 |       50 |     100 |   97.38 | 234-237           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.96 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.65 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |    90.6 |    91.84 |   89.65 |    90.6 | ...61,963,965-966 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   94.46 |    95.68 |     100 |   94.46 | ...53-354,390-401 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.83 |    81.92 |   89.65 |   85.83 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |      80 |    76.31 |   81.35 |      80 |                   
  session.ts       |   84.08 |    75.27 |   93.61 |   84.08 | ...1007,1016-1026 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...24-625,628-629 
 ...active/control |   76.11 |    89.09 |      80 |   76.11 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.79 |    92.45 |   88.88 |   91.79 | ...49-367,387,390 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |   39.78 |    63.24 |   47.22 |   39.78 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   49.11 |    62.96 |   54.54 |   49.11 | ...63-568,570-575 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.14 |     94.4 |   95.23 |   98.14 |                   
  ...putAdapter.ts |   98.09 |    93.65 |   98.07 |   98.09 | ...1319,1422-1423 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 84-85,125-126     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |   88.11 |    83.99 |   91.36 |   88.11 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |    93.4 |    92.95 |     100 |    93.4 | ...19-320,323-325 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    97.82 |     100 |     100 | 620               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  ...nt-service.ts |   93.65 |    86.02 |     100 |   93.65 | ...52-454,461,463 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   85.85 |    91.78 |   95.83 |   85.85 | ...94-206,366-369 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   91.42 |    86.72 |     100 |   91.42 | ...26,732-736,748 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   96.49 |    86.37 |   96.72 |   96.49 | ...1253,1307-1311 
  ...e-grouping.ts |     100 |    94.11 |     100 |     100 | 69,132            
  ...ub-session.ts |   92.04 |    77.77 |     100 |   92.04 | ...36-445,470,508 
  daemon-logger.ts |    82.2 |    77.26 |   91.76 |    82.2 | ...1720,1747-1753 
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.37 |    90.06 |     100 |   98.37 | ...1037,1039-1040 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |    91.3 |       80 |     100 |    91.3 | ...24-127,205-212 
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.41 |    88.75 |     100 |   94.41 | ...24,702,718,728 
  fast-path.ts     |    91.3 |    81.98 |   95.45 |    91.3 | ...65-474,540-541 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...27-128,139-140 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   85.03 |    80.64 |   73.27 |   85.03 | ...5788,5793-5794 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   95.04 |    87.62 |     100 |   95.04 | ...07,511-512,552 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   94.83 |    92.55 |   78.68 |   94.83 | ...1857,1877-1880 
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.34 |    76.57 |     100 |   93.34 | ...17,820,833-835 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |    86.66 |     100 |   91.07 | ...79-182,216-219 
  ...ace-agents.ts |   64.79 |    71.33 |   91.66 |   64.79 | ...2125,2135-2145 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ace-memory.ts |   82.19 |    75.28 |     100 |   82.19 | ...82-489,549-556 
  ...ers-status.ts |   98.52 |       79 |     100 |   98.52 | 94,122,162,165    
  ...tion-store.ts |   89.63 |    88.27 |   92.59 |   89.63 | ...91-400,411-414 
  ...e-registry.ts |   91.26 |     90.8 |     100 |   91.26 | ...93-294,300-301 
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...e-remember.ts |   97.94 |    94.33 |     100 |   97.94 | ...00,304-309,350 
  ...te-runtime.ts |   93.14 |    87.71 |     100 |   93.14 | ...-88,92,145-150 
  ...management.ts |   71.84 |    71.67 |      96 |   71.84 | ...65-866,873-877 
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
  ...lls-status.ts |     100 |    94.73 |     100 |     100 | 109               
 ...serve/acp-http |   75.83 |     78.3 |   93.85 |   75.83 |                   
  ...r-registry.ts |     100 |    95.45 |     100 |     100 | 191               
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |   98.19 |    88.55 |     100 |   98.19 | 1015,1037-1048    
  dispatch.ts      |   69.34 |    74.79 |     100 |   69.34 | ...4525,4573-4579 
  index.ts         |   82.04 |    78.69 |   89.58 |   82.04 | ...2197,2228-2230 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |   85.68 |    80.06 |     100 |   85.68 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |     73.6 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.32 |    89.18 |     100 |   90.32 | 142-150           
  ...ile-system.ts |   85.19 |     78.6 |     100 |   85.19 | ...2094,2104-2105 
 src/serve/routes  |   85.65 |    79.98 |    96.2 |   85.65 |                   
  a2ui-action.ts   |   99.49 |    94.52 |    87.5 |   99.49 | 250               
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   85.22 |       88 |     100 |   85.22 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.45 |    83.33 |     100 |   85.45 | 98-105            
  goals.ts         |    98.8 |    88.46 |     100 |    98.8 | 134               
  health-demo.ts   |   94.17 |    83.33 |     100 |   94.17 | 62-66,143         
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   86.02 |    83.52 |     100 |   86.02 | ...-939,1069-1070 
  ...on-runtime.ts |     100 |     87.5 |     100 |     100 | 43,79             
  session.ts       |   86.23 |    82.28 |      95 |   86.23 | ...4211,4213-4214 
  sse-events.ts    |   84.45 |     87.5 |   77.77 |   84.45 | ...36,453-456,485 
  usage-stats.ts   |     100 |    95.65 |     100 |     100 | 116               
  ...space-auth.ts |    83.7 |       75 |     100 |    83.7 | ...23,328,340-344 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   89.29 |    75.72 |     100 |   89.29 | ...91-392,411-412 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |    82.1 |    77.17 |      90 |    82.1 | ...1000,1006,1009 
  ...extensions.ts |   87.44 |    72.76 |   95.74 |   87.44 | ...1788,1830-1831 
  ...-file-read.ts |   92.32 |       80 |     100 |   92.32 | ...94-595,598-599 
  ...file-write.ts |   84.44 |    64.13 |     100 |   84.44 | ...73-275,355-357 
  ...e-git-diff.ts |   94.11 |    91.89 |     100 |   94.11 | ...54-155,201-206 
  ...ce-git-log.ts |     100 |    92.68 |     100 |     100 | 51,76,182         
  workspace-git.ts |   64.77 |       85 |     100 |   64.77 | 74-84,90-110      
  ...github-prs.ts |      97 |    91.66 |     100 |      97 | 133-135           
  ...-lifecycle.ts |   96.85 |       75 |     100 |   96.85 | 130-131,161-162   
  ...management.ts |   87.43 |    85.13 |     100 |   87.43 | ...1441,1461-1466 
  ...cp-control.ts |   71.29 |       67 |     100 |   71.29 | ...67-573,582-583 
  ...ace-models.ts |   95.87 |    92.42 |     100 |   95.87 | 38-39,136-141     
  ...ermissions.ts |   74.66 |    69.23 |     100 |   74.66 | ...25-233,254-271 
  ...e-settings.ts |   72.81 |     69.9 |     100 |   72.81 | ...85-589,594-604 
  ...tup-github.ts |   77.58 |    70.27 |   84.21 |   77.58 | ...88,310,354-355 
  ...ace-skills.ts |   69.87 |    78.12 |     100 |   69.87 | ...59-284,290-324 
  ...ace-status.ts |   75.41 |    63.51 |     100 |   75.41 | ...35-336,360-361 
  ...pace-tools.ts |   74.82 |    69.23 |     100 |   74.82 | ...41-146,175-176 
  ...pace-trust.ts |   76.08 |       50 |   66.66 |   76.08 | ...01-206,214-215 
  ...pace-voice.ts |   91.45 |    82.35 |     100 |   91.45 | ...21-624,627-629 
 src/serve/server  |   90.68 |    89.51 |   95.23 |   90.68 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    86.95 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.14 |    71.42 |     100 |   97.14 | 16                
  ...r-response.ts |    85.4 |    76.16 |     100 |    85.4 | ...91,708,771-780 
  fs-factory.ts    |     100 |    92.59 |     100 |     100 | 33,41,100,156     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.11 |    95.09 |     100 |   95.11 | ...65-167,422-427 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |    94.4 |       92 |     100 |    94.4 | 162-168           
  ...on-archive.ts |   89.61 |    90.38 |   88.23 |   89.61 | ...36-441,513-523 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   98.72 |    97.39 |     100 |   98.72 | ...26-628,769-771 
 src/serve/voice   |   85.15 |     93.1 |   90.47 |   85.15 |                   
  ...ice-config.ts |   96.77 |       30 |     100 |   96.77 | 85-86             
  voice-ws.ts      |   77.97 |    96.39 |   83.33 |   77.97 | ...55,470,508-510 
  ...oordinator.ts |     100 |    98.11 |     100 |     100 | 171               
 ...kspace-service |   89.53 |     83.4 |   89.47 |   89.53 |                   
  index.ts         |   89.05 |     82.9 |   87.87 |   89.05 | ...1158-1162,1165 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   91.96 |    88.38 |   97.81 |   91.96 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 104-117           
  ...killLoader.ts |   97.14 |    87.87 |     100 |   97.14 | 140,151-152       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   77.36 |    85.52 |   83.33 |   77.36 | ...43,168,210-211 
  ...mandLoader.ts |   97.36 |    92.68 |     100 |   97.36 | 153,160-161       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    93.75 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.29 |    86.11 |     100 |   88.29 | ...91-196,229-230 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.5 |    81.81 |     100 |    90.5 | ...37-438,445-446 
  ...-args-file.ts |   93.54 |    90.47 |    87.5 |   93.54 | 201-203,217-223   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.71 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   88.14 |    87.69 |     100 |   88.14 | ...80,287,352-357 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   90.46 |    82.11 |      96 |   90.46 | ...66-668,671-673 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |    86.29 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.24 |   94.73 |   88.28 | ...1352,1356-1363 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.04 |    83.33 |      80 |   94.04 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   71.09 |    72.95 |   66.66 |   71.09 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   72.22 |    69.85 |   66.66 |   72.22 | ...4022,4026-4030 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.22 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   62.73 |    47.22 |   66.66 |   62.73 | ...95-296,313-318 
  ...inePresets.ts |   96.27 |    83.87 |     100 |   96.27 | ...97,402,410-412 
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   58.53 |    66.18 |   51.06 |   58.53 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.21 |    70.73 |   57.69 |   60.21 | ...90,794,803,806 
  useAuth.ts       |    94.6 |    73.52 |     100 |    94.6 | ...21-222,241-247 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   81.36 |    83.13 |   89.37 |   81.36 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |    92.1 |     84.9 |     100 |    92.1 | ...4-69,94-99,178 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   68.28 |    70.14 |   84.61 |   68.28 | ...66-599,610-611 
  copyCommand.ts   |   98.49 |    95.78 |     100 |   98.49 | ...80,280,321,327 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   82.97 |    78.57 |     100 |   82.97 | 47-52,67-70,91-96 
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   91.13 |    83.72 |      90 |   91.13 | ...81-184,196-199 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   93.45 |    89.06 |     100 |   93.45 | ...68-169,196-206 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.27 |    83.01 |     100 |   86.27 | ...22-935,969-974 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   89.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |    90.6 |    77.95 |     100 |    90.6 | ...91-694,785-792 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.43 |      100 |      50 |    6.43 | 31-330            
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |   69.56 |    78.17 |   75.92 |   69.56 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   97.29 |     87.5 |   66.66 |   97.29 | 49                
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   86.72 |       88 |     100 |   86.72 | ...00-302,355-359 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-72,84,139,153 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-597             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   75.11 |     61.4 |      50 |   75.11 | ...48-253,271-275 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   83.33 |    76.92 |     100 |   83.33 | 24-30             
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   78.45 |    64.28 |     100 |   78.45 | ...98,501,504-510 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   82.49 |    80.33 |      80 |   82.49 | ...2178,2204,2278 
  ...Shortcuts.tsx |   20.65 |      100 |       0 |   20.65 | ...7,50-52,68-126 
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.82 |    92.53 |      50 |   95.82 | ...97,440-444,447 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   83.41 |    71.65 |     100 |   83.41 | ...69,971,976-992 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |    5.91 |      100 |       0 |    5.91 | 25-218            
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   92.97 |    83.87 |     100 |   92.97 | ...43,246,273-275 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  ...criptView.tsx |   98.27 |    84.21 |     100 |   98.27 | 45,53             
  TrustDialog.tsx  |     100 |    81.81 |     100 |     100 | 71-86             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   53.72 |    70.87 |   42.85 |   53.72 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   64.78 |    29.41 |   33.33 |   64.78 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |    82.2 |    81.36 |    90.9 |    82.2 |                   
  ...sksDialog.tsx |   77.53 |     76.9 |   80.76 |   77.53 | ...1781,1803-1809 
  ...TasksPill.tsx |   67.03 |     86.2 |     100 |   67.03 | ...02-122,130-138 
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.14 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.28 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |   50.97 |    52.38 |   20.83 |   50.97 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.56 |      100 |       0 |    9.56 | 40-67,70-158      
 ...mponents/hooks |   86.99 |    81.37 |   91.89 |   86.99 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.04 |    61.53 |   70.58 |   40.04 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   89.85 |       86 |   86.86 |   89.85 |                   
  ...ionDialog.tsx |   89.23 |    84.27 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.79 |     100 |     100 | 37,41,43,289,365  
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   96.71 |    97.77 |   91.66 |   96.71 | 223-233           
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   76.52 |     42.1 |   66.66 |   76.52 | ...00,102,125,156 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   89.75 |     79.1 |     100 |   89.75 | ...33-635,642-644 
  ...upMessage.tsx |   98.32 |    95.16 |     100 |   98.32 | 184-187,414       
  ToolMessage.tsx  |   92.43 |    84.84 |   93.33 |   92.43 | ...56-961,988-990 
 ...ponents/shared |   85.73 |    82.05 |   94.05 |   85.73 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.86 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   88.51 |    85.11 |   81.81 |   88.51 | ...51-779,792,887 
  text-buffer.ts   |   85.94 |    81.73 |   97.91 |   85.94 | ...2651,2749-2750 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-678             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   69.81 |    72.64 |   61.11 |   69.81 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   83.34 |     80.5 |   85.91 |   83.34 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   92.45 |    62.79 |      50 |   92.45 | ...69-270,272-276 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |    85.1 |    84.53 |     100 |    85.1 | ...1583-1585,1591 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   78.68 |    73.77 |   91.66 |   78.68 | ...86-389,398-401 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 151-152           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 234-235           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   84.84 |    82.47 |   89.57 |   84.84 |                   
  ...dProcessor.ts |      84 |    84.12 |     100 |      84 | ...41-873,920-921 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...86-287,292-293 
  ...dProcessor.ts |   85.21 |     66.4 |   81.81 |   85.21 | ...1407,1428-1432 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      42 |       75 |     100 |      42 | 42-44,53-59,62-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.08 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.73 |    76.59 |     100 |   94.73 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   94.85 |    80.76 |     100 |   94.85 | ...54,229,292-295 
  ...ompletion.tsx |   96.81 |    81.81 |     100 |   96.81 | ...90-291,301-302 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   78.53 |    88.57 |     100 |   78.53 | ...96-104,112-113 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |     97.7 |     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 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   85.51 |    81.02 |   96.15 |   85.51 | ...3891,4053-4061 
  ...BranchName.ts |     100 |    91.66 |     100 |     100 | 30                
  ...oryManager.ts |   98.01 |    98.36 |     100 |   98.01 | 139-142           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |    96.77 |     100 |     100 | 75                
  ...delCommand.ts |     100 |       95 |     100 |     100 | 53                
  ...ouseEvents.ts |   94.31 |    97.43 |   83.33 |   94.31 | 76-80             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   91.16 |     90.9 |     100 |   91.16 | ...35-338,453-463 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...tleRepaint.ts |     100 |      100 |     100 |     100 |                   
  ...umeCommand.ts |   94.67 |    74.28 |     100 |   94.67 | ...19,174,233-238 
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.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.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   53.06 |       50 |   66.66 |   53.06 | ...53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |      100 |     100 |     100 |                   
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    91.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   85.77 |    84.63 |    94.6 |   85.77 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   68.83 |    70.14 |      50 |   68.83 | ...52-254,274-293 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.68 |    82.35 |   95.23 |   92.68 | ...34-737,790-795 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   52.52 |    73.25 |   91.66 |   52.52 | ...23,626-635,638 
  commandUtils.ts  |    96.1 |    88.77 |     100 |    96.1 | ...73,175-176,320 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |    95.4 |    98.41 |     100 |    95.4 | 123-126           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |      96 |    97.05 |     100 |      96 | 102-105           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   69.47 |       75 |   66.66 |   69.47 | ...24-129,157-158 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.59 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    73.77 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   96.85 |    95.45 |     100 |   96.85 | 71-73,201-203     
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   71.08 |    79.03 |   93.75 |   71.08 | ...03-525,656-657 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   95.97 |    93.22 |   94.44 |   95.97 | ...21-322,482-483 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   89.65 |       92 |     100 |   89.65 | ...83-184,217-218 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |      75 |    59.89 |   94.59 |      75 |                   
  collect.ts       |   71.21 |    65.81 |      96 |   71.21 | ...88-631,653-654 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   80.94 |    72.69 |   80.55 |   80.94 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   89.72 |    65.33 |   93.75 |   89.72 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |    68.42 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.01 |    86.88 |    92.3 |   81.01 |                   
  ...p-profiler.ts |   98.39 |    90.56 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       95 |     100 |     100 | 72                
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   96.96 |    97.95 |     100 |   96.96 | 123-125           
  commentJson.ts   |   91.37 |    94.87 |     100 |   91.37 | 67-76             
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.73 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...59,376-377,422 
  languageUtils.ts |   98.88 |    97.01 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   89.05 |    76.38 |     100 |   89.05 | ...86,302-303,340 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   74.38 |    69.56 |     100 |   74.38 | ...92-103,105-116 
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.67 |    56.93 |   76.92 |   45.67 | ...1034,1046-1069 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |     87.5 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   91.63 |    91.02 |      95 |   91.63 |                   
  cleanup.ts       |   95.77 |    95.83 |     100 |   95.77 | 70-72             
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |   91.91 |    90.47 |    87.5 |   91.91 | 58-62,73,131-135  
  throttledOnce.ts |   86.66 |     86.2 |     100 |   86.66 | ...99,105,137-138 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.05 |    85.94 |   88.63 |   87.05 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   89.96 |    83.92 |   94.02 |   89.96 |                   
  ...transcript.ts |   88.09 |    85.71 |     100 |   88.09 | ...97,605,611-615 
  ...ent-resume.ts |   84.53 |    76.01 |   78.26 |   84.53 | ...1674-1678,1681 
  ...ound-tasks.ts |   96.14 |     90.1 |   98.76 |   96.14 | ...1728,1748-1751 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   95.65 |    89.28 |     100 |   95.65 | ...12-413,485-489 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.27 |    67.71 |   78.94 |   76.27 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.05 |    64.51 |   78.57 |   75.05 | ...1881,1887-1888 
  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.02 |    85.19 |   76.28 |   78.02 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.8 |    85.24 |   93.33 |    90.8 | ...64,666,668-669 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |    90.2 |    85.29 |   87.28 |    90.2 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   84.17 |    73.43 |   76.47 |   84.17 | ...2138,2192-2194 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    88.09 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.95 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.79 |    87.79 |   82.35 |   91.79 | ...1774,1823-1826 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...ow-sandbox.ts |   96.87 |    94.51 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   81.81 |    83.99 |    87.5 |   81.81 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   83.61 |    86.66 |   72.88 |   83.61 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   82.76 |    86.29 |   70.79 |   82.76 | ...7396,7400-7401 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.11 |    91.95 |      88 |   94.11 | ...25-426,429-430 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   91.48 |    87.96 |   92.67 |   91.48 |                   
  baseLlmClient.ts |   88.28 |    82.48 |   81.81 |   88.28 | ...47,660,666-668 
  client.ts        |   91.17 |    86.84 |   90.27 |   91.17 | ...3233,3329-3330 
  ...tGenerator.ts |   85.81 |     85.5 |   80.95 |   85.81 | ...23-424,469-475 
  ...lScheduler.ts |   89.79 |     86.1 |   95.83 |   89.79 | ...5296,5324-5335 
  geminiChat.ts    |   91.86 |    89.26 |   95.69 |   91.86 | ...4072,4120-4121 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |    95.83 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...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.33 |    83.33 |      50 |   93.33 | 46-47             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   95.19 |    89.47 |     100 |   95.19 | ...44-245,290-291 
  prompts.ts       |   93.39 |    91.42 |   82.35 |   93.39 | ...1125,1328-1329 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |   96.89 |    80.88 |   88.23 |   96.89 | ...10,117-118,123 
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-123        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...allIdUtils.ts |   98.41 |    93.02 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.49 |    91.17 |     100 |   98.49 | ...94,622-623,669 
 ...ntentGenerator |   96.18 |    87.11 |   95.38 |   96.18 |                   
  ...tGenerator.ts |   97.09 |    86.94 |   94.44 |   97.09 | ...1322,1351,1362 
  converter.ts     |   96.04 |    87.15 |     100 |   96.04 | ...,931,1086-1088 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   95.19 |    86.46 |    92.3 |   95.19 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |    95.1 |     85.4 |   91.89 |    95.1 | ...1164-1165,1193 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.57 |    90.11 |   95.23 |   91.57 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.03 |    89.12 |   96.87 |   91.03 | ...1909,2078-2093 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   96.61 |    90.87 |     100 |   96.61 | ...1094,1102,1197 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |    92.2 |     92.4 |     100 |    92.2 | ...15-516,536-539 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.73 |    89.76 |   98.27 |   96.73 |                   
  dashscope.ts     |   97.48 |    91.91 |      95 |   97.48 | ...85-386,528-529 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   86.11 |    83.09 |   92.19 |   86.11 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   78.32 |    71.83 |     100 |   78.32 | ...1122,1168-1169 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |   80.39 |     87.5 |     100 |   80.39 | 50-59             
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.82 |    86.11 |   97.82 |   90.82 | ...1215-1221,1265 
  ...ionManager.ts |   80.59 |    78.06 |   80.23 |   80.59 | ...2577,2599-2600 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    84.61 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   88.55 |    82.13 |     100 |   88.55 | ...58,948-949,959 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    83.78 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |    80.61 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |   77.38 |    79.84 |    90.9 |   77.38 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   65.26 |    62.63 |   71.42 |   65.26 | ...17-618,625-626 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 97                
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   93.15 |    86.93 |   95.91 |   93.15 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  goal-evidence.ts |   87.01 |    84.26 |   95.65 |   87.01 | ...86-587,610-613 
  ...projection.ts |   89.41 |    72.22 |   66.66 |   89.41 | ...28,131,135-137 
  ...ersistence.ts |   83.96 |       76 |      80 |   83.96 | ...0,93-94,97-106 
  goal-protocol.ts |     100 |      100 |     100 |     100 |                   
  goal-reducer.ts  |   91.24 |    81.14 |     100 |   91.24 | ...68,381,432-436 
  goal-runtime.ts  |   98.71 |    92.69 |     100 |   98.71 | ...38-639,662-663 
  goal-verifier.ts |   91.72 |    89.47 |     100 |   91.72 | ...63-166,179-181 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-27              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   87.41 |    85.82 |   88.38 |   87.41 |                   
  ...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.43 |     83.5 |   94.59 |   95.43 | ...1010-1011,1021 
  hookPlanner.ts   |    87.5 |    85.36 |   86.66 |    87.5 | ...21-225,232-243 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.48 |    72.04 |   66.66 |   62.48 | ...67-768,777-778 
  hookSystem.ts    |    87.5 |      100 |   70.21 |    87.5 | ...43-744,750-751 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   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     |   77.22 |    86.74 |     100 |   77.22 | ...57,261-267,273 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.24 |    96.09 |   88.88 |   94.24 | ...42-543,628-632 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.12 |    82.74 |   90.29 |   87.12 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.11 |    95.72 |   96.29 |   97.11 | ...85-287,361-362 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    81.81 |     100 |     100 | 126,136           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   91.48 |    75.75 |     100 |   91.48 | ...99,118-121,189 
  ...entPlanner.ts |   91.51 |    76.19 |     100 |   91.51 | ...04,113-116,290 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   82.27 |    77.92 |   83.33 |   82.27 | ...66,285,292-298 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   94.73 |    95.94 |     100 |   94.73 | ...35-336,357-358 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    86.79 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   89.85 |    82.92 |     100 |   89.85 | ...54-155,162-163 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    89.79 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   71.68 |    65.51 |   68.75 |   71.68 | ...90-394,397,403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   79.38 |    78.33 |   81.81 |   79.38 | ...58-272,286-291 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.53 |    88.91 |   91.13 |   92.53 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,260           
  modelsConfig.ts  |   89.36 |    86.77 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.54 |    91.01 |   70.71 |   83.54 |                   
  autoMode.ts      |   97.64 |    93.13 |     100 |   97.64 | ...78-585,631,708 
  ...transcript.ts |      98 |    84.61 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.53 |    89.57 |      80 |   86.53 | ...1095,1201-1205 
  rule-parser.ts   |   94.14 |    91.89 |     100 |   94.14 | ...1335,1369-1371 
  ...-semantics.ts |   70.36 |    91.04 |   46.66 |   70.36 | ...2237,2300-2303 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.58 |    84.87 |   96.28 |   89.58 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.66 |    85.71 |     100 |   97.66 | ...95,118,487-488 
  ...ionService.ts |   96.71 |    95.79 |     100 |   96.71 | ...83,699,832-840 
  ...ingService.ts |   87.48 |     81.4 |   89.83 |   87.48 | ...1840,1867-1868 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.05 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.12 |    90.45 |      98 |   94.12 | ...1323,1726-1727 
  cronTasksFile.ts |   96.21 |    91.58 |     100 |   96.21 | ...06,331-332,477 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   92.07 |    85.93 |    90.9 |   92.07 | ...09,211,323-330 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |   74.05 |       69 |   95.74 |   74.05 | ...2170,2198-2199 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.88 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.22 |    97.32 |     100 |   98.22 | ...63-664,711-712 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.47 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |   97.27 |    91.22 |     100 |   97.27 | ...50-451,606-607 
  ...ttachments.ts |   97.74 |     90.8 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |   98.38 |    93.75 |   88.88 |   98.38 | 63-64             
  ...ipt-reader.ts |   94.49 |    89.16 |   97.95 |   94.49 | ...1038,1049-1050 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   76.81 |    73.71 |    92.1 |   76.81 | ...15-816,820-827 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.73 |     83.5 |    97.1 |   88.73 | ...2401,2471-2491 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |   84.21 |    78.27 |   97.14 |   84.21 | ...2452,2458-2463 
  ...pInhibitor.ts |   97.42 |    92.68 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    86.66 |     100 |     100 | 96-97             
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.56 |      100 |   33.33 |   14.56 | 58-185            
  ...ionService.ts |   87.98 |    86.84 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.06 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.06 |     100 |   99.41 | 244-245,677       
 ...s/visionBridge |    98.6 |    94.11 |     100 |    98.6 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.32 |    92.64 |     100 |   98.32 | ...23,647,660-661 
 src/skills        |   88.37 |    87.22 |   90.16 |   88.37 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   83.78 |    82.63 |   82.35 |   83.78 | ...1218,1225-1229 
  skill-paths.ts   |   89.65 |    86.95 |     100 |   89.65 | ...11-112,117-118 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |       98 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.28 |    88.63 |   96.42 |   87.28 |                   
  ...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 |   83.55 |    85.01 |   94.59 |   83.55 | ...1501,1578-1579 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   80.49 |    83.44 |   84.06 |   80.49 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.07 |    80.95 |     100 |   99.07 | 183,197           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |     100 |    90.47 |     100 |     100 | 49,76             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   55.35 |    71.56 |   63.46 |   55.35 | ...1350,1367-1387 
  metrics.ts       |   78.44 |    79.62 |   79.66 |   78.44 | ...1079,1082-1093 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,478-479,495 
  sdk.ts           |   79.22 |    89.18 |   63.63 |   79.22 | ...57-161,199-221 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.38 |    89.22 |   96.66 |   90.38 | ...1611,1642-1645 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |      82 |    94.48 |   85.71 |      82 | ...1328,1332-1339 
  uiTelemetry.ts   |   93.07 |    92.59 |   83.33 |   93.07 | ...62,290,410-411 
 ...ry/qwen-logger |   73.62 |    81.08 |   69.49 |   73.62 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   73.62 |     80.9 |   68.96 |   73.62 | ...1095,1133-1134 
 src/test-utils    |      94 |    98.24 |   78.94 |      94 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   92.57 |      100 |   75.75 |   92.57 | ...63,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   85.56 |    84.51 |   88.07 |   85.56 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |   94.94 |    85.29 |     100 |   94.94 | ...09-313,332,366 
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   83.21 |    86.66 |   80.95 |   83.21 | ...65-666,716-717 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.24 |    92.85 |     100 |   99.24 | 44                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   81.63 |       79 |   85.41 |   81.63 | ...3221,3223-3224 
  mcp-client.ts    |   79.83 |    85.09 |   89.47 |   79.83 | ...2233,2237-2240 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   95.43 |    93.89 |     100 |   95.43 | ...79-780,830-831 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.74 |    84.28 |   88.46 |   91.74 | ...93,606,804-809 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    90.24 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   95.65 |    88.88 |   86.66 |   95.65 | ...80,495,567-568 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |    90.9 |    86.71 |    87.5 |    90.9 | ...13-414,428-440 
  ripGrep.ts       |    95.9 |     88.4 |   94.73 |    95.9 | ...61-662,668-669 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |    81.2 |    89.74 |    62.5 |    81.2 | ...80-286,369-377 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   78.68 |    83.81 |   91.83 |   78.68 | ...4979,5042-5043 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.06 |    93.33 |   89.47 |   91.06 | ...71,475,520-542 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   93.92 |    83.13 |   92.85 |   93.92 | ...86-391,413-414 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.06 |    78.83 |   82.22 |   78.06 | ...37-938,946-947 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   92.74 |    91.52 |    91.3 |   92.74 | ...63-564,580-586 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.53 |    83.57 |      80 |   90.53 | ...1007,1065-1068 
  write-file.ts    |   85.66 |    85.04 |   85.71 |   85.66 | ...53-756,793-828 
 src/tools/agent   |   85.09 |    85.09 |   86.66 |   85.09 |                   
  agent.ts         |   84.92 |    84.84 |   86.17 |   84.92 | ...4092,4114-4124 
  fork-subagent.ts |   88.32 |       90 |    90.9 |   88.32 | ...05-123,200-201 
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   87.46 |    79.41 |   85.71 |   87.46 |                   
  workflow.ts      |   87.46 |    79.41 |   85.71 |   87.46 | ...51-652,664-667 
 src/utils         |   92.37 |    89.61 |   96.53 |   92.37 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.76 |    93.36 |     100 |   94.76 | ...30-531,634-638 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.11 |    89.47 |     100 |   91.11 | ...46-147,154-155 
  ...n-branches.ts |   95.81 |    93.95 |      95 |   95.81 | ...91-492,504-517 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    91.66 |     100 |     100 | 15,43,57          
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.06 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   82.23 |     92.9 |    61.9 |   82.23 | ...56-372,376-382 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  fileUtils.ts     |   95.29 |    92.06 |   96.15 |   95.29 | ...1768,1793-1794 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |   81.81 |       75 |     100 |   81.81 | 15-16             
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,331-336 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  gitDiff.ts       |   95.12 |    81.03 |     100 |   95.12 | ...1073,1390-1391 
  gitDirect.ts     |   98.46 |    90.17 |     100 |   98.46 | 148,268,352       
  ...noreParser.ts |   94.59 |    92.59 |     100 |   94.59 | ...05-106,140-141 
  gitUtils.ts      |      75 |    88.88 |   83.33 |      75 | ...,78-79,103-154 
  github-prs.ts    |    99.3 |    90.62 |     100 |    99.3 | 204               
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |    93.25 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   93.77 |    89.15 |     100 |   93.77 | ...13-319,406-407 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.61 |     100 |     100 | 206               
  pathReader.ts    |   97.77 |       90 |     100 |   97.77 | 93,121            
  paths.ts         |   93.95 |    92.79 |     100 |   93.95 | ...78-479,481-483 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   59.15 |    76.92 |     100 |   59.15 | ...5,89-90,96-101 
  ...noreParser.ts |   92.63 |    91.52 |     100 |   92.63 | ...72-173,192-193 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   97.73 |    93.24 |     100 |   97.73 | 85-86,107,262-263 
  readManyFiles.ts |   96.29 |     87.5 |     100 |   96.29 | 225,275,286-290   
  retry.ts         |   95.93 |    92.23 |     100 |   95.93 | ...33,524-525,543 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.65 |    96.96 |     100 |   97.65 | ...00,250-251,277 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   50.94 |    85.71 |      70 |   50.94 | ...54-255,268-346 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.61 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   94.77 |     94.2 |     100 |   94.77 | ...41-42,96,98-99 
  ...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.72 |    92.12 |     100 |   91.72 | ...36-539,615-616 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |     83.8 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.05 |    88.59 |     100 |   86.05 | ...2251,2258-2262 
  ...lAstParser.ts |   98.16 |    91.91 |     100 |   98.16 | ...1244-1246,1256 
  ...ContextEnv.ts |     100 |    90.47 |     100 |     100 | 46-48             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |    90.82 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |    59.09 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.11 |    96.33 |     100 |   96.11 | ...22-327,329-334 
  ...pt-records.ts |   85.78 |    83.63 |     100 |   85.78 | ...84-388,418-433 
  truncation.ts    |   90.44 |    89.09 |     100 |   90.44 | ...18-426,463-469 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.68 |    80.38 |   94.69 |   83.68 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   82.47 |    76.22 |      95 |   82.47 | ...1525,1559-1560 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

…rules

Borrow the image-evidence and quantified-verification patterns from
hand-run rounds (#7265, #7471, #7686 r2 and the pr-assets convention):

- publish-verify now hosts agent-produced evidence/*.png on the pr-assets
  branch (verify/pr<N>-<run>-<attempt>/) and appends them below the
  escaped report. Untrusted-payload discipline: strict filename allowlist,
  8-image / 2 MB caps enforced in the find predicates, racing-push retry,
  and every failure degrades to a text-only comment. VERIFY_ASSETS_REMOTE
  is a test seam; the block was dry-run against a local bare remote
  covering hosting, hostile filenames, oversize files, dotfiles, missing
  branch, and no-image runs
- skill: evidence images are named as kebab-case captions binding image to
  claim, before/after pairs over lone after-shots; follow-up rounds lead
  with a previous-finding status table (fixed/stands/superseded/declined,
  with adjudication) and re-measure instead of diffing the old report;
  size/perf claims get measured-metric Δ tables with residual deltas
  accounted for; unreachable branches get the configuration that reaches
  them constructed; defensive guards get their accept path checked against
  real production artifacts, not just mocked rejects

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.

— qwen3.7-max via Qwen Code /review

Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md
- skill: local invocation resolves --repo and passes it to every gh call
- skill: call out the dependency confound when the base A/B side reuses
  the PR-installed node_modules and the PR touches package.json/lockfile
- workflow: document the pin step's bootstrap logic — issue_comment jobs
  run the default branch's YAML, so base always carries the verify-pr
  skill by the time this job exists
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship — CI landed green after the review. ✅

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

No issues found. LGTM! ✅

中文说明

未发现问题。LGTM!✅

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Review: feat(triage): add sandboxed /verify deep-verification lane

Overview

Adds an on-demand @qwen-code /verify lane to qwen-triage.yml: a verify job that executes the PR's real build in a container on the ECS pool (token-free agent env, loopback model proxy, author-write gate), and a publish-verify job on a clean hosted runner that upserts the report back to the PR. Plus a new verify-pr skill encoding the methodology/artifact contract and a one-paragraph Stage 2c update so triage recommends the trigger.

The isolation design is the strongest part: .qwen pinned from HEAD^1 so the tree under test can't rewrite its own verifier, depth-2 checkout giving the token-free agent a local base side for A/B, the git exec-vector sweep the tmux job lacks, verdict allowlisting before $GITHUB_OUTPUT, and every terminal state publishing an explicit comment. Escaping discipline in publish-verify is correct — I re-checked emit_block against </code></pre></details>, @everyone and <img onerror> payloads and they stay inert.

I independently replicated the PR's static claims (they hold):

  • actionlint with the repo's exact flag set (scripts/lint.js:97) → clean on the head file.
  • All 9 new run: blocks extracted from verify + publish-verifybash -n clean, shellcheck -S warning clean with the repo's ignore set.

Below are the things I'd want addressed. Nothing here is a correctness blocker for the happy path; items 1–4 are the ones I'd fix before merge.


1. Any GitHub user can trigger a 45-minute self-hosted job + a full model budget — Medium/High

.github/workflows/qwen-triage.yml:115 resolves the principal for /verify to $ISSUE_AUTHOR only. The commenter is never checked. On a public repo that means any authenticated account — a brand-new drive-by — can comment @qwen-code /verify on any open PR authored by a write-holder and consume:

  • up to 45 min on the shared ecs-qwen pool (:1417), cancel-in-progress: false,
  • a full npm ci + npm run build + 25 min of agent time + the model spend behind REVIEW_OPENAI_API_KEY.

Concurrency is keyed per-PR, so N open maintainer PRs → N queued jobs. /tmux has the same property, but its cost profile is a fraction of this one, so inheriting the gate verbatim changes the abuse economics materially.

The author gate is right for whose code runs; it just isn't a gate on who may spend the budget. Suggest requiring both: author has write (code-execution gate, unchanged) and commenter is a collaborator/write (spend gate). That's a few lines in the existing perm step and doesn't touch the /tmux semantics if you scope it to /verify.

2. The escaped report can exceed GitHub's comment limit → no comment at all — Medium

:2233 caps the report block at 50,000 raw bytes, then emit_block HTML-escapes it. Escaping is expansive (<→4×, &→5×), and the check runs before expansion. GitHub's issue-comment cap is 65,536 characters; gh api -F body=@… returns 422, set -euo pipefail kills the step, and nothing is posted — leaving the "🔬 Sandboxed verification is running" comment on the PR permanently while the run is long dead.

Measured, not theoretical:

$ head -c 50000 report-code.md | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g' | wc -c
70253      # 50,000 raw bytes of TS-generics-heavy lines → 70,253 chars > 65,536

Overflow starts at roughly 10.4 % </> density (extra = 3·(#< + #>) + 4·#&, need > 15,536), before the ~1.2 KB of fixed framing and the evidence section. A report quoting JSX, TS generics, XML/HTML wire payloads, or a diff of this very workflow gets there. publish-tmux uses 20 KB + 30 KB and shares the mechanism, but the single 50 KB block here is the most exposed instance.

Fix is one line — escape first, then truncate, so the cap is a cap on what actually ships:

content="$(html_escape < "$file" | head -c "$max")"   # and drop $max to ~45000

3. -size -2M is really a 1 MiB cap, and over-cap images vanish silently — Medium

:2082 uses find … -size -2M. find rounds size up to the unit, so -2M matches only files whose rounded size is < 2 MiB — i.e. ≤ 1,048,576 bytes. Verified:

1048576 b.png   → matched
1048577 c.png   → NOT matched
1500000 d.png   → NOT matched

So the "8 images, 2 MB each" contract in SKILL.md, the workflow comment at :2071, and the PR body all overstate the real limit by 2×. A Playwright full-page capture routinely lands between 1 and 2 MB and would be dropped.

Worse than the off-by-one: the drop is completely silent. No ::warning::, no note in the comment — meanwhile report.md prose still references 01-bundle-ab-base-vs-head.png by name (the skill mandates exactly that), so the reader sees a caption pointing at nothing. Same for the head -8 truncation.

Suggest -size -2049k (or -2M documented honestly as 1 MiB), plus counting found vs hosted and appending _N image(s) exceeded the size/count cap — see run artifacts._ to the evidence section whenever they differ.

4. The planted-artifact fix covers pre-commit but not run-time — Medium

The tmp/*-verify-* sweep at :1626 closes the pre-committed-directory variant, and that's a good catch. But the same forgery is still reachable during the run:

  • :1905 chowns $RUNNER_TEMP/verify-results to node before the agent starts, and PR code executes as node. A test or build script can drop verify-results/report.md directly.
  • :2189-2190 select with find verify-results -name 'report.md' … | head -1 — unordered readdir, and a top-level plant sorts ahead of the real verify-results/pr<n>-verify-<ts>/report.md in typical traversal.
  • verdict.txt is likewise read from a workspace path (:1965) that is chowned to the agent user at :1639.

Given the author already holds write, this isn't an escalation so much as a truth-in-labelling issue: a PR under verification can author its own "merge-ready" headline, and the comment block at :1617-1624 reads as if the sweep closed that. Two cheap improvements:

find verify-results -mindepth 2 -path '*-verify-*/report.md' | sort | head -1

(the -mindepth 2 -path pin plus sort for determinism, same for assertions.json), and a sentence in that comment saying the sweep hardens the pre-commit vector while run-time output is inherently agent-authored and only ever advisory.

5. npm install -g runs against the previous PR's .npmrc — Low/Medium

:1557 carries the comment "Install before checkout so PR-controlled .npmrc cannot affect npm." On a persistent self-hosted workspace that reasoning inverts: at that point the workspace still holds the previous run's checked-out PR tree — actions/checkout (:1592) hasn't run yet, and Clean stale agent state (:1572) only sweeps git config/hooks/tmp. run steps default to cwd = $GITHUB_WORKSPACE, and npm reads the project .npmrc from cwd even for -g.

--registry=… overrides the registry, but not script-shell, ignore-scripts, cafile, prefix, or //…/:_authToken — and this install runs as root. Same pattern exists at :811 in the tmux job.

One-line fix that removes the whole question: run the global install from outside the workspace.

( cd "${RUNNER_TEMP:-/tmp}" && npm install -g --registry=https://registry.npmjs.org '@qwen-code/qwen-code@latest' )

6. skip / n-a / cancelled bodies overwrite a previous real report — Low/Medium

All six terminal branches upsert on the same <!-- qwen-triage:verify --> marker. So: PR gets a full verification round → later marked draft, or picks up a conflict, or someone re-triggers on a docs-only follow-up → the prior evidence comment is replaced by "Sandboxed verification: not run". The resolve step deliberately snapshots the previous report for the agent's follow-up round; it'd be a shame to lose it from the PR itself. Consider posting skip/na/cancelled as a new comment (they're transient states), or preserving the prior report in a collapsed <details> below the skip notice.

7. Smaller items

  • git pull --rebase misses the identity its siblings carry (:2116). Every other git call in that block passes -c user.name -c user.email; the rebase retry doesn't, and rebase needs a committer ident. Where the runner's ident can't be auto-detected, the racing-push retry aborts and degrades to text-only — i.e. the retry never fires in exactly the case it exists for. Cleanest fix is to set it once after clone (git -C "$clone_dir" config user.name …) and drop the four repeated -c pairs.
  • No feedback when the ECS pool is unavailable. The 👀 reaction and the "running" status comment both live inside the verify job (:1424ff), which needs the scarce self-hosted runner. If the pool is saturated or MAINTAINER_ECS_RUNNER_DISABLED is set — which :1417 hardcodes past, unlike :79/:202 — the user gets total silence, publish-verify never runs, and the job sits queued. That's the one hole in the PR's "an explicit request never gets silence" goal; acking from the hosted authorize side would close it.
  • Duplicate-filename collision. Two artifact dirs each containing evidence/01-foo.png sanitize to the same safe name: the second cp overwrites the first, hosted counts 2, and the render loop emits the same image twice. Prefix with the index, or de-dup.
  • No PNG validation + unbounded pr-assets growth. Bytes are attacker-supplied and only the extension is checked. raw.githubusercontent.com's CSP/sandbox headers make this low-risk, but a head -c 8 | cmp against the PNG magic is nearly free, and the branch accumulates 8 MB/run forever with no retention story.
  • head -c can split a UTF-8 char at the 50 KB cut, and the skill mandates a 中文摘要 section. On GNU tr the invalid bytes pass through and gh renders one U+FFFD (cosmetic; BSD tr would error instead). iconv -c -f UTF-8 -t UTF-8 after the cut makes it exact.
  • Double chown -R $GITHUB_WORKSPACE:1639 (pre-npm ci) then :1905 (post-npm ci, so ~50k+ node_modules files). The second one is mostly redundant work on the critical path.
  • SKILL.md worktree guidance is inaccurate. It says to keep worktrees under tmp/ "so the workflow's cleanup finds them", but every cleanup globs *-verify-*tmp/base-tree matches none of them and survives until the next checkout's git clean. Either name the worktree to match the glob or have the cleanup handle git worktree list output.
  • Worth confirming: verify and tmux use disjoint concurrency groups, so /tmux and /verify on the same PR can run simultaneously. That's fine if the ECS pool gives each runner its own _work, but the tmux job's own comment ("would share the same self-hosted runner workspace") suggests otherwise — if that premise holds, a shared {workflow}-sandbox-{pr} group prefix is safer.

Test coverage

There is no automated coverage for either job — expected for workflow YAML, and the PR compensates with a genuinely thorough manual round (six-branch stubbed-gh replay, injection-escaping proof, verdict-allowlist and assertions-jq replay, plus a full local E2E of the agent against #7547 with an audited 318/318 and a 13→7→13 mutation A/B). That's the right evidence for this artifact type. The honest ⚠️ on Linux stands: the jobs themselves have never run on a real Actions runner, and items 2, 3 and 5 above are exactly the class of thing that only shows up there — all three degrade visibly rather than silently corrupting, which matches the PR's stated containment argument.

Verdict

Approach and isolation model are sound, and the skill is the most valuable artifact here — it encodes real methodology rather than platitudes. I'd fix 1 (spend gate), 2 (escape-then-truncate) and 3 (image cap + silent drop) before merging, since 2 and 3 both produce a wrong or missing published comment on the first real run. 4–7 are follow-up-able.

中文说明

整体设计(容器隔离、.qwen 从 base pin 取、depth-2 本地 A/B、git exec-vector 清扫、verdict 白名单、六种终态均发评论)是这个 PR 最扎实的部分;转义纪律我复核过,</details>@everyone<img onerror> 均保持惰性。仓库 lint 声明我独立复现通过:repo 精确参数的 actionlint 干净,9 个新 run:bash -n + shellcheck -S warning 全绿。

建议合并前处理的三项:

  1. 任何 GitHub 用户都能触发 45 分钟自建 runner 作业 + 全额模型预算:115)。principal 只取 PR 作者,评论者完全不校验。公开仓库上任意路人账号即可在任一 write 用户的开放 PR 上评论 /verify,按 PR 并发排队消耗 ECS 池与模型额度。/tmux 虽同样如此,但成本量级差一个数量级。建议对 /verify 同时要求「作者有 write(代码执行门禁)」+「评论者是 collaborator(花费门禁)」。
  2. 转义后的报告可能超出 GitHub 65,536 字符评论上限:2233)。50,000 字节上限是在转义之前判定的,而 <→4 倍、&→5 倍。实测:50,000 字节的 TS 泛型密集内容转义后 70,253 字符,超限 → gh api 422 → set -e 杀掉步骤 → 一条评论都发不出,PR 上永远停在"运行中"。约 10.4% 的尖括号密度即触发。改法一行:先转义再 head -c,上限降到 ~45000。
  3. -size -2M 实际是 1 MiB 上限,且超限图片静默丢弃:2082)。find 向上取整,实测 1048577 字节即不匹配,与 SKILL/注释/PR 描述宣称的 2 MB 差一倍;Playwright 整页截图常在 1–2 MB。更关键的是丢弃无任何提示,而 report.md 仍按文件名引用该图,读者会看到指向空的图注。建议改 -size -2049k,并在 found != hosted 时在证据区追加一行说明。

其余(可后续处理):4 预埋产物防护只覆盖「提交时预埋」,运行期仍可伪造(verify-results 在 agent 运行前已 chown 给 node,且 find … | head -1 无序)——建议 -mindepth 2 -path '*-verify-*/report.md' | sort | head -1 并在注释中说明该产物本质是 agent 自述、仅作参考;5 npm install -g 的 cwd 仍是持久 workspace 中上一次运行留下的 PR 树,其 .npmrc 对这次 root 全局安装生效(--registry 覆盖不了 script-shell 等),改为在 $RUNNER_TEMP 下执行即可;6 skip/n-a/cancelled 会按 marker 覆盖掉此前真实的验证报告;7 若干小项:retry 里的 git pull --rebase 缺少同伴命令都带的身份配置、ECS 池不可用时零反馈(👀 与状态评论都在稀缺作业内部,且 :1417 绕过了 MAINTAINER_ECS_RUNNER_DISABLED)、同名图片覆盖后重复渲染、PNG 未校验魔数且 pr-assets 无限增长、head -c 可能截断多字节字符、重复 chown -R、SKILL 中"worktree 放 tmp/ 以便 cleanup 找到"与 *-verify-* glob 不符。

结论:方向与隔离模型成立,skill 本身价值最高。建议先修 1/2/3(后两项会直接导致首次真实运行发出错误或发不出评论),4–7 可作为后续。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

中文说明

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

— qwen3.8-max-preview via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
…g per review

Address review round 5078770575 items 1-3 plus the cheap follow-ups:

- authorize: /verify now requires write from BOTH the PR author (whose
  code runs) and the commenter (who spends a scarce runner slot + model
  budget) — a drive-by account can no longer burn 45 minutes of ecs-qwen
  on someone else's PR; duplicates check once; /tmux and /triage gates
  unchanged. Replayed 8 principal scenarios against a stubbed gh
- authorize acks /verify with the eyes reaction from the always-hosted
  job, so a queued/saturated sandbox pool no longer means total silence
- publish: emit_block escapes FIRST and caps the escaped size (45 KB for
  the report) — a raw-side cap let dense <>& content inflate past
  GitHub's 65,536-char comment limit, 422 the post, and strand the
  running status with no report at all; iconv -c keeps a UTF-8 sequence
  split by the byte cut (likely, given the mandated 中文 summary) from
  shipping broken; replayed: 50 KB dense report -> 45,873-byte body
- publish: image cap is byte-exact (-size -2097153c; find's -2M rounds
  sizes UP to MiB, silently making the documented 2 MB cap 1 MiB), bytes
  must carry the PNG magic (extension is attacker-choosable), duplicate
  sanitized names dedupe instead of overwriting + double-rendering, and
  dropped images are reported in the comment instead of vanishing
- publish: weak terminal notices (cancelled/infra/skipped/n-a) only
  replace this run's own running status; a previous round's real report
  survives as the marker comment and the notice posts fresh
- publish: report.md/assertions.json lookups pin the artifact-dir shape
  and sort (bare find -name order is filesystem-dependent); the verify
  job's verdict.txt lookup sorts likewise
- verify: global npm install runs from RUNNER_TEMP (the persistent
  workspace still holds the PREVIOUS run's tree, whose .npmrc would
  apply to a root install); both cleanup passes remove leftover tmp/
  worktrees (git worktree prune alone only drops metadata); the run step
  no longer re-chowns 50k node_modules files; pr-assets clone sets its
  committer identity once so the racing-push rebase retry can commit
- skill: worktree guidance now tells the agent to remove its base tree
  itself, with the workflow sweep as backstop only
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Response to the review round (comment) — all three pre-merge items fixed in 1db0136cd

Every fix below was replayed locally before pushing (stubbed gh, local bare pr-assets remote, extracted run-blocks through bash -n + shellcheck -S warning, repo-exact actionlint/yamllint).

# Finding Resolution
1 Any GitHub user can trigger a 45-min self-hosted job + model budget Fixed. /verify now requires write from both the PR author and the commenter; duplicates check once; any API error or non-write denies. Replayed 8 principal scenarios (drive-by deny, both-write allow, author-without-write deny, self-comment dedupe, 404 fail-closed, /tmux+/triage unchanged) — 8/8.
2 Escaped report can exceed the 65,536 comment cap → 422 → no comment Fixed. emit_block escapes first, then caps the escaped size (report cap 45,000; 400 KB input bound on the escape itself); iconv -c drops a UTF-8 sequence split by the byte cut. Replayed: the 50 KB dense <>& report that previously assembled to >65k now produces a 45,873-byte body with a truncation note, valid UTF-8; a 中文-heavy report cut at the cap decodes clean.
3 -size -2M is a 1 MiB cap; over-cap images vanish silently Fixed. Byte-exact -size -2097153c (verified: exactly-2-MiB accepted, +1 byte rejected); bytes must carry the PNG magic (extension is attacker-choosable); duplicate sanitized names dedupe instead of overwrite-and-render-twice; dropped images are now counted in the comment ("N additional image(s) did not pass the hosting checks…") instead of vanishing.
4 Run-time forgery: unordered find -name report.md Hardened. report.md/assertions.json/verdict.txt lookups pin the *-verify-*/ dir shape, add -mindepth 2, and sort. Full run-time forgery by a steered agent remains inherently in-scope of the agent's own powers — the report is advisory and labeled as such; noted as a residual, not closable by lookup discipline alone.
5 npm install -g under the previous PR's .npmrc Fixed for the verify lane: the global install runs from RUNNER_TEMP. The identical pattern in the tmux job is pre-existing and left for the follow-up PR.
6 skip/n-a/cancelled overwrite a previous real report Fixed. Weak terminal notices only PATCH the marker comment when it is this run's own "running" status; over a previous round's real report they post fresh. Replayed all three arms of the matrix.
7a rebase retry lacks committer identity Fixed — identity set once on the clone; the per-command -c pairs are gone.
7b Total silence when the ECS pool is saturated Improved — the 👀 ack moved to the always-hosted authorize job, so an accepted request is acknowledged even while the sandbox job queues. The runs-on fallback question (hardcoded ECS vs MAINTAINER_ECS_RUNNER_DISABLED) is deferred: it mirrors the tmux job's deliberate ECS-only choice and deserves its own decision.
7c Duplicate-filename collision Fixed (dedupe, see #3).
7d No PNG validation / unbounded pr-assets growth Magic check fixed (see #3). Retention policy for pr-assets is a repo-level decision (the hand-run rounds have the same growth) — deferred to the follow-up.
7e UTF-8 split at the cut Fixed (see #2).
7f Double chown -R $GITHUB_WORKSPACE Fixed — the run step now chowns only the two RUNNER_TEMP dirs.
7g Worktree guidance inaccurate Fixed — the skill now has the agent git worktree remove its own base tree, and both workflow cleanup passes sweep leftover tmp/ worktrees via git worktree list --porcelain (prune alone only drops metadata).
7h Disjoint verify/tmux concurrency groups Confirmed safe, no change: a self-hosted runner instance executes one job at a time and each instance owns its own _work directory, so /tmux and /verify running concurrently land on different instances with separate workspaces. The tmux comment's "same workspace" concern applies to two runs of the same job family on the same instance over time, which each lane's own per-PR group already serializes.

Deferred to the follow-up PR (tmux-side siblings, as the review suggested): tmux's *-tmux-* planted-artifact sweep, its raw-side emit_block caps, its .npmrc-exposed global install, and the pr-assets retention story.

中文说明

针对本轮 review 的处理(修复提交 1db0136cd,推送前全部经本地回放验证):

  • 1(任意账号可触发 45 分钟 self-hosted job)已修/verify 现要求 PR 作者与评论者双方均具写权限,重复主体只查一次,API 错误或权限不足一律拒绝;8 个场景回放全过(路人拒绝、双写放行、作者无写拒绝、自评去重、404 fail-closed、/tmux/triage 行为不变)。
  • 2(转义后报告超 65,536 上限 → 422 → 无评论)已修emit_block 先转义再按转义后大小截断(报告上限 45,000),iconv -c 处理被字节切割劈开的 UTF-8 序列;50 KB 高密度 <>& 报告现在产出 45,873 字节评论体 + 截断注記,中文重载报告切割后解码无损。
  • 3(-2M 实为 1 MiB 上限、超限图片静默消失)已修:字节级精确 -size -2097153c(实测恰 2 MiB 收、+1 字节拒);字节必须带 PNG magic;重名去重;被丢弃图片在评论中显式计数。
  • 4 查找已钉死目录形态并排序;被劫持 agent 的运行时伪造属其固有能力范围,报告本身即标注为参考性证据。
  • 5 verify 侧全局安装已移至 RUNNER_TEMP 执行;tmux 同款问题留后续 PR。
  • 6(弱终态覆盖旧报告)已修:cancelled/infra/skipped/n-a 只替换本轮的"运行中"状态;旧报告存活,弱通知另发新评论;三臂矩阵回放通过。
  • 7 系列:rebase 身份、👀 移至 hosted authorize、重名碰撞、PNG magic、UTF-8 切割、双重 chown、worktree 指引与清扫均已修;verify/tmux 并发组经分析确认安全(单 runner 实例同时只跑一个 job,各实例 _work 独立);ECS runs-on 回退与 pr-assets 保留策略留待后续决策。

后续 PR 待办(review 建议的 tmux 侧同款问题):*-tmux-* 预埋产物清扫、emit_block 原始侧上限、.npmrc 暴露的全局安装、pr-assets 保留策略。

Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
Comment thread .github/workflows/qwen-triage.yml
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Review — feat(triage): add sandboxed /verify deep-verification lane (round 2, head 1db0136cd)

Overview

Adds a comment-triggered deep-verification lane: verify (self-hosted, containerized, token-free agent behind a loopback model proxy) executes the PR's real build and runs the new verify-pr skill; publish-verify (hosted, no PR checkout, write PAT) upserts the report back as one comment. The isolation contract is a faithful clone of /tmux with three deliberate upgrades — fetch-depth: 2 for a local A/B base, .qwen pinned from HEAD^1 so the tree under test can't rewrite its own verifier, and an allowlisted agent verdict. The round-1 fixes all landed and hold up: dual author+commenter gate, escape-then-cap emit_block, byte-exact -size -2097153c, PNG-magic + name dedupe, npm -g from RUNNER_TEMP, weak-body upsert guard, 👀 moved to the hosted authorize job.

Verified locally (not just read)

  • Repo-exact actionlint (-shellcheck= -pyflakes= -ignore SC2002/SC2016/SC2129 … from scripts/lint.js) on the head workflow → clean (only the expected "reusable workflow not found" from my isolated copy).
  • All 11 run: blocks of authorize/verify/publish-verify, extracted with PyYAML → bash -n clean, shellcheck -S warning clean under the repo's ignore set.
  • Mergeability retry loop ([ "$mergeable" != "UNKNOWN" ] && break as the last command under set -euo pipefail) → replayed: does not trip errexit, so the UNKNOWN-after-retries branch is reachable as intended. ✅
  • emit_block escape-then-cap → replayed with a 250 KB report at max=45000. The truncation pipeline does die of SIGPIPE (141) under pipefail, but esc="$(A)" || esc="$(B)" is accidentally self-healing: A already assigned the 45 000-byte partial capture, so B re-truncates the short value and exits 0. Step survives, body = 45 130 B. ✅ (I chased this specifically because a set -e death there would resurrect exactly the stranded-"running"-comment bug round 1 fixed.)

Findings

1. (High) A runtime-planted tmp/*-verify-* dir beats the agent's real one — and sort makes the win deterministic

The planted-artifact sweep runs in Pin agent inputs from base (:1657), i.e. before Install and build PR app (:1669). That step runs npm ci and npm run build, both of which execute PR-controlled code — this repo's root package.json already wires postinstall: patch-package, prepare: node scripts/prepare.js, build: node scripts/build.js, and a PR can edit any of them. Anything they create under tmp/*-verify-* is still there when the collector runs at :1987.

All three selections then take the lexicographically first match:

  • :2008 VERDICT_FILE="$(find tmp … -path '*-verify-*/verdict.txt' | sort | head -1)"
  • :2278 REPORT="$(find verify-results … -path '*-verify-*/report.md' | sort | head -1)"
  • :2279 ASSERTIONS_FILE=… | sort | head -1

So a dir named tmp/0000-verify-x/ deterministically outranks the skill's tmp/pr<n>-verify-<ts>/. Replayed with the exact commands from the head revision (planted 0000-verify-planted alongside a real pr7710-verify-20260725-101010):

--- verify job verdict selection ---
picked: tmp/0000-verify-planted/verdict.txt -> merge-ready
--- publish-verify selection ---
report picked: verify-results/0000-verify-planted/report.md
# FABRICATED REPORT
All good, ship it.
assertions picked: verify-results/0000-verify-planted/assertions.json
{"pass":999,"fail":0,"total":999}

Result: the bot posts "Sandboxed verification: merge-ready (agent verdict) · 999 passed · 0 failed · 999 total" with attacker-authored prose, while the agent's real blocked report is discarded. The escaping and the "advisory, not a review" framing bound the blast radius to fabricated content — no HTML injection, no approval — but a forged bot attestation is precisely the attack this PR already hardens against for the pre-commit variant, so the gap is worth closing on the same commit. Note the round-1 sort fix (added for determinism) is what upgrades this from "nondeterministic race" to "guaranteed attacker win".

Suggested minimal fix

Re-sweep immediately before launching the agent, at the top of Run verification agent (:1716), after install/build has run:

# Install/build executed PR code; re-sweep so nothing it planted can be
# collected as the agent's report.
find tmp -maxdepth 2 -type d -name '*-verify-*' -exec rm -rf {} + 2>/dev/null || true

Fuller closure (also covers code the agent executes): let the workflow own the path instead of globbing for it — export QWEN_VERIFY_ARTIFACT_DIR="$RUNNER_TEMP/verify-out/pr${PR_NUMBER}-verify-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" into the agent env, have the skill write there, and collect exactly that path. A dir under $RUNNER_TEMP is outside the tree that build scripts roam, and the run-scoped name isn't guessable from a committed script.

2. (Medium) /verify on an outside contributor's PR is completely silent

The dual gate requires the PR author to hold write. For a fork PR from a non-collaborator — the majority case on this repo — a maintainer's @qwen-code /verify produces:

  • no 👀: the ack step (:173) is gated on steps.perm.outputs.should_run == 'true';
  • no run: verify.if requires needs.authorize.outputs.should_run == 'true';
  • no comment: publish-verify.if is always() && needs.verify.result != 'skipped' (:2055), and a job whose if is false reports skipped.

issue_comment runs don't surface on the PR's checks tab either, so the only trace is a step-summary line in a run nobody links to. This contradicts the PR's own stated principle — "/verify is always an explicit request, so silence would read as a lost run" — and it fires on the exact PRs where deep verification is most valuable. /tmux has the same shape, but /tmux never promised a receipt.

Suggested fix (keeps the gate, avoids opening a spam vector): have the perm step emit a deny_reason output plus a commenter_ok flag, and add a hosted step that posts a one-liner only when the commenter themself has write — e.g. "/verify needs write access for both the requester and the PR author (@author has read); the sandbox executes the author's code." Everything needed is already computed in that loop.

3. (Low, hardening — shared with the pre-existing /tmux collector) symlinks in the collected artifact tree

find tmp … -exec cp -r {} "$RUNNER_TEMP/verify-results/" (:1987, and :1179 for tmux) copies a directory that node fully controls, and the cp itself runs as root — the same process boundary that separates the agent from /proc/<proxy-pid>/environ, where REVIEW_OPENAI_API_KEY lives for the proxy's lifetime. GNU cp -R on bookworm does not dereference symlinks found during traversal, so this is not exploitable as written; but attacker-created symlinks do land in the upload directory, and actions/upload-artifact resolves symlinks when zipping — on a public repo those artifacts are world-downloadable. One line after the copy removes the whole question:

find "$RUNNER_TEMP/verify-results" -type l -delete 2>/dev/null || true

Nits

  • Free text after /verify is accepted and dropped. startsWith(body, '@qwen-code /verify ') triggers the lane, but the prompt is fixed (/verify-pr N --repo R), so @qwen-code /verify focus on the SSE retry path silently verifies whatever the skill picks. Same as /tmux today, so consistent — but worth either forwarding it as an explicitly-untrusted "requested focus" line or saying in the skill/docs that the suffix is ignored.
  • verify hardcodes runs-on: ['self-hosted', …, 'ecs-qwen'] (:1450) instead of the vars.MAINTAINER_ECS_RUNNER_DISABLED fallback that authorize/triage honor. Matches tmux-testing, and moving 👀 to the hosted job softens it, but with the pool off the requester gets 👀 and then nothing until the queue expires. Worth a comment noting it's intentional.
  • emit_block latent empty-render: in the truncation branch, if iconv were absent the first || arm captures nothing and the fallback re-truncates the now-empty esc, emitting an empty <pre><code> plus "...truncated". Unreachable on ubuntu-latest (glibc), so latent only.
  • pr-assets growth: every image-bearing run adds a permanent verify/pr<N>-<run>-<attempt>/ dir with no retention story. Bounded by the write-gate, but the branch only grows.

Verdict

The security architecture is sound and the round-1 fixes are real — I re-derived the two I was most suspicious of (SIGPIPE in the new cap path, errexit in the retry loop) and both hold. #1 is the one I'd want fixed before merge: it's a two-line change, it's the same threat class the PR already invested in, and shipping it means the lane's first published report can be forged by any PR that edits a build script. #2 is a UX gap that will be hit within days of merge. Everything else is optional.

中文说明

结论

整体架构可靠,第一轮的修复均已落地并经复核(我特意重跑了两处最可疑的:新的「先转义后截断」路径的 SIGPIPE 行为,以及 mergeability 重试循环里 [ … ] && break 是否触发 set -e——两者都没问题)。

本地实测(非仅阅读)

  • 仓库同款 actionlint 通过;authorize/verify/publish-verify 的全部 11 个 run: 块经 PyYAML 抽出后 bash -nshellcheck -S warning 全绿。
  • 重试循环 fall-through 到 UNKNOWN 分支可达 ✅。
  • emit_block:250 KB 报告 + max=45000 实测,截断管道确实因 SIGPIPE 返回 141,但 esc="$(A)" || esc="$(B)" 恰好自愈(A 已把 45000 字节部分输出赋给 esc,B 再截短即成功),步骤存活,body 45 130 字节 ✅。

发现

  1. (高)运行期预埋的 tmp/*-verify-* 目录会击败 agent 的真实产物,且 sort 让攻击者稳赢。 预埋清扫在 Pin agent inputs from base:1657)执行,而其后的 npm ci / npm run build:1669)会运行 PR 可控代码(本仓库根 package.json 已有 postinstall/prepare/build 脚本)。三处选取(:2008:2278:2279)都是 sort | head -1,因此 tmp/0000-verify-x/ 必然排在 tmp/pr<n>-verify-<ts>/ 之前。用 head 版本的原命令实测:伪造的 merge-ready + 999/999 + 假 report.md 全部被选中,真实的 blocked 报告被丢弃。转义与「仅供参考」的定位限制了危害范围(无 HTML 注入、不构成批准),但伪造 bot 背书正是本 PR 已为「预提交」变体加固的同一攻击类。最小修复:在 Run verification agent:1716)开头再清扫一次;更彻底的做法是由 workflow 指定 QWEN_VERIFY_ARTIFACT_DIR$RUNNER_TEMP 下含 run id 的路径)并只收集该路径。

  2. (中)对外部贡献者的 PR 执行 /verify 完全无声。 双方写权限门要求 PR 作者有写权限;fork PR 的作者通常没有,于是:无 👀(:173 要求 should_run == 'true')、job 被 skip、publish-verify:2055needs.verify.result != 'skipped')同样被 skip,且 issue_comment 的 run 不出现在 PR 检查列表 —— 与本 PR 自己的原则「显式请求绝不应得到沉默」相悖,且恰好命中最需要深度验证的那类 PR。建议:perm 步骤输出 deny_reasoncommenter_ok,仅当评论者本人有写权限时由 hosted 步骤回一句说明(避免被滥用刷评论)。

  3. (低,加固;与既有 /tmux 收集器共有) cp -r:1987)以 root 身份复制 node 完全可控的目录,而 root 正是能读到 /proc/<proxy-pid>/environ(其中有 REVIEW_OPENAI_API_KEY)的一侧。bookworm 的 GNU cp -R 默认不解引用,所以当前不可利用;但符号链接仍会进入上传目录,而 actions/upload-artifact 打包时会解引用,公开仓库的产物任何人可下载。复制后加一行 find "$RUNNER_TEMP/verify-results" -type l -delete 即可。

次要项

/verify 后的自由文本被接受但丢弃(与 /tmux 一致);verifyruns-on 硬编码绕过 MAINTAINER_ECS_RUNNER_DISABLED 回退(与 tmux job 一致);emit_blockiconv 缺失时会静默渲染空块(ubuntu-latest 上不可达);pr-assets 分支只增不减,缺少留存策略。

建议

#1 建议合并前修复(两行改动,且属于本 PR 已投入加固的同一威胁类:若不修,该车道发布的第一份报告就可能被任何改动构建脚本的 PR 伪造);#2 合并后数日内必然遇到;其余可选。


Reviewed at 1db0136cdd5ed2b0231dc8302c6648c818026d7b. Local evidence: repo-exact actionlint, 11 extracted run: blocks under bash -n + shellcheck -S warning, and replays of the artifact-selection, errexit-retry, and emit_block truncation paths.

…erify

Address review round 2 (comment 5079157987) and the CHANGES_REQUESTED
round on the verify lane:

- run step re-sweeps tmp/*-verify-* AFTER npm ci/build and before the
  agent starts: the pin step's sweep runs before PR lifecycle scripts
  (postinstall etc.), which could re-plant a fake artifact dir whose
  zeroed timestamp deterministically wins the sorted collector. From the
  sweep on, only the agent writes those dirs; a steered agent forging its
  own artifacts remains the documented advisory-report residual
- RUNNER_TEMP verify-results/verify-context are rm'd before mkdir: the
  pool is persistent and runner temp hygiene is runner-managed — a stale
  report or previous-report.md from ANOTHER PR must never ride along
- symlinks are stripped from verify-results before upload:
  actions/upload-artifact dereferences them, so a node-planted link would
  exfiltrate whatever it points at into the artifact
- a trusted commenter invoking /verify on a PR whose author lacks write
  now gets an explanation comment from the hosted authorize job instead
  of total silence (the commenter is checked first; drive-by accounts and
  API errors still get nothing); job timeout 45->60 so a slow install can
  never let the JOB limit kill the agent past its own graceful 25m budget
- stale tmp/base-tree (skill's canonical scratch worktree) is removed by
  name at job start — a plain dir isn't git-registered, so the worktree
  sweep alone misses it and the next worktree add would fail
- scripts/tests/qwen-triage-workflow.test.js gains a verify-lane describe
  block: an 8-arm stub-gh replay of the dual principal gate (drive-by
  deny, author-without-write deny + explain flag, self-comment dedupe,
  404 fail-closed, /tmux and /triage unchanged) plus guards for the
  post-prepare sweep placement, the symlink strip, and the RUNNER_TEMP
  resets — the replay found this commit's sweep edit had silently not
  applied, which is exactly the regression class it exists to catch
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Response to review round 2 (comment) — all three findings fixed in 844469dbc

Finding Resolution
High — runtime-planted artifact deterministically wins the collector (lifecycle scripts run after the pin sweep; 00000000 sorts ahead of real timestamps) The run step now re-sweeps tmp/*-verify-* after npm ci/npm run build and immediately before the agent launches — from that point only the agent writes those dirs, so the sorted selectors can no longer meet a plant. sort stays for determinism. The alternative (workflow-owned artifact dir under $RUNNER_TEMP) was considered and set aside: verify-results is node-writable during the agent phase anyway, so it offers the same trust envelope as a swept workspace dir at more plumbing. Residual: a steered agent forging its own artifacts — inherent to its power envelope, which is why the report is advisory and never a review. Placement is regression-tested (sweep must precede start_openai_proxy).
Medium — /verify on an untrusted-author PR is totally silent The gate now checks the commenter first; when the author check is what fails, the hosted authorize job posts a bilingual explanation ("author lacks write; the sandbox executes the author's code; use /triage instead"). Drive-by commenters and API-error denials stay silent — nothing is owed there, and it avoids handing an unauthenticated account a comment-trigger oracle. Covered by the replay test (explain flag asserted on exactly the trusted-commenter/untrusted-author arm).
Low — upload-artifact dereferences node-planted symlinks find "$RUNNER_TEMP/verify-results" -type l -delete runs between collection and upload; guarded by test.

Also from this round's overlap with the CHANGES_REQUESTED pass: $RUNNER_TEMP/verify-{results,context} are flushed before reuse (stale-run leakage on the persistent pool), job timeout 45→60 so the agent's graceful 25m budget survives slow installs, and the authorize principal routing got the 8-arm stub-gh replay test — which promptly caught an edit in this very commit that had silently failed to apply.

中文说明

第 2 轮三项发现已全部在 844469dbc 修复:

  • High(生命周期脚本可在 pin 清扫后重新预埋伪造产物目录,00000000 时间戳在排序下必胜):run 步骤在 npm ci/build 之后、agent 启动之前二次清扫 tmp/*-verify-*,此后只有 agent 会写这些目录;sort 保留用于确定性。评估过"workflow 专属 $RUNNER_TEMP 产物目录"方案后搁置——agent 阶段该目录同样是 node 可写的,信任包络相同而管线更复杂。残余风险(被劫持的 agent 自伪造产物)属其固有能力范围,报告因此定位为参考证据而非评审。清扫位置有回归测试。
  • Medium(作者无写权限时 /verify 完全静默):门禁改为先查评论者;当失败方是作者时,由常驻 hosted 的 authorize job 发布双语说明(作者缺写权限、沙箱执行作者代码、请改用 /triage)。路人评论者与 API 错误仍保持静默。回放测试断言 explain 标志只在"可信评论者 + 不可信作者"场景出现。
  • Low(upload-artifact 解引用 symlink):收集与上传之间删除全部符号链接,配测试。

另与 CHANGES_REQUESTED 轮重叠的修复:$RUNNER_TEMP 两目录复用前冲洗、job 超时 45→60、8 场景 stub-gh 回放测试守卫双主体门禁(该测试当场抓到本提交中一处未生效的编辑)。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Downgraded from Request changes to Comment: self-PR. Reviewed. Suggestions are inline. Not reviewed: reverse audit — five-round hard cap reached before two consecutive dry rounds.

— Codex GPT-5 via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: coverage — no plan was given, so this run cannot show that any of the diff was read.

— qwen3.7-max via Qwen Code /review

Comment thread scripts/tests/qwen-triage-workflow.test.js

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Downgraded from Request changes to Comment: self-PR. Reviewed. Suggestions are inline.

中文说明

⚠️ 已从请求修改降级为评论:self-PR。 已审查。 建议见行内评论。

— qwen3.8-max-preview via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml
… in /verify

Address the Codex /review round (19 findings) and the bot's follow-up.
Each fix was replayed locally; the proxy fix has a decisive A/B.

Gate and routing:
- the shell command match is case-insensitive: GitHub Actions expression
  comparisons ignore case, so `@QWEN-CODE /VERIFY` reached the step and
  fell through to the commenter-only branch — running the PR author's
  code with the author never checked
- the verify ack and denial notice require github.event.issue.pull_request:
  /verify on a plain issue was acknowledged but could never report
- publish-verify joins the verify job's per-PR concurrency group, and a
  failed PATCH falls back to posting fresh instead of going silent

Untrusted-input paths:
- the model proxy binds an EPHEMERAL port, reports it through a
  root-owned file, and its health check must echo a per-run nonce with
  the recorded PID alive. A/B with a squatter on 8787: the old code's
  proxy dies EADDRINUSE yet still reports enabled and points qwen at the
  squatter; the new code comes up unaffected on an ephemeral port
- worktree-scoped git config is deleted before hooksPath is resolved:
  `extensions.worktreeConfig` is allowlisted and .git/config.worktree is
  invisible to `git config --local`, so a prior run could set
  core.hooksPath=/ and make the hook sweep's recursive delete walk / as
  root (verified locally). The sweep now also refuses any hooks path
  outside the repository's git dir
- marker-comment lookups accept only bot-owned comments that START with
  the marker: any user can paste the marker and divert the bot into
  PATCHing a stranger's comment
- the upload staging dir is re-flushed after npm lifecycle scripts

Honest verdicts:
- the docs-only classifier no longer uses a pipeline (grep -q made the
  writer take SIGPIPE, so under pipefail a long file list with an early
  code file classified a code PR as docs-only and skipped verification),
  and executable markdown/YAML (.qwen, .github/workflows, scripts) is
  classified as behavioral before the extension rule
- tee's status is checked alongside qwen's: a full results volume made a
  truncated evidence stream publish as pass
- 137 is split by elapsed budget into watchdog timeout vs crash/OOM
- the agent's verdict is honored only for VERDICT=pass with a report and
  zero failed assertions; otherwise the process outcome headlines and
  the scope paragraph says the run did not complete
- verdict.txt is read through a bounded prefix (SIGPIPE under pipefail)

Skill contract corrections: per-commit tables only when the commits are
reachable at depth 2 (else aggregate + Not covered); internal workspace
symlinks must have their realpaths asserted before a base control is
trusted; repo lint gates and event-history cost math are qualified to
what the token-free container can actually run; --repo is never inferred
from `origin` (a fork holds a different PR under the same number).

Tests: 9 new guards, all mutation-verified (reverting each fix turns one
red), including an executable escaping/size-cap/UTF-8 test for the
publisher's own emit_block and a fix to the earlier command-file test,
which matched the tmux job's identically named step.
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Response to the Codex review round + bot follow-up — all 22 threads addressed in b92ebfc3c

Every inline thread has a per-item reply. Summary of what changed, and the two findings that turned out to be exploitable exactly as written:

Proven exploitable, now fixed with an A/B:

  • Fixed proxy port 8787. With a squatter listening (which PR lifecycle code can arrange, since it runs first), the control arm's real proxy dies EADDRINUSEand still reports openai_proxy=enabled (http://127.0.0.1:8787/v1), pointing the agent at the squatter's chat completions. The agent would then have authored its own "verification". Now: ephemeral port, published through a root-owned file, readiness requiring PID liveness + a per-run nonce echoed by /__health. New arm comes up on :53693 unaffected.
  • extensions.worktreeConfigcore.hooksPath=/. Reproduced locally: the key is invisible to git config --local --name-only --list, the extension itself is on the keep-list, and git rev-parse --git-path hooks duly returns / — pointing the hook sweep's recursive delete at the filesystem root as root. Now the worktree config file is deleted and the extension unset before hooksPath is resolved, and any hooks path that does not canonicalize under the repo's git dir is warned about, never swept.

Also fixed: case-insensitive command matching in the shell gate (GHA expressions ignore case, so @QWEN-CODE /VERIFY was reaching the commenter-only branch and running the author's code unchecked); docs-only classifier SIGPIPE (reproduced: 60k-entry list with an early code file → n/a) plus executable markdown/YAML classified as behavioral; tee status checked alongside qwen's; 137 split by elapsed budget into watchdog-timeout vs crash; agent verdict honored only for a clean, evidenced run, with a partial-run scope paragraph otherwise; marker comments matched by bot ownership + prefix with a post-fresh fallback; run-start status no longer overwrites a previous report; publish-verify in the verify job's per-PR concurrency group; PR-only guards on the ack and denial steps; bounded verdict read; unguarded evidence find; upload staging re-flushed after lifecycle scripts.

Skill contract corrections: per-commit tables only when the commits are reachable at depth 2; internal workspace symlink realpaths asserted before a base control is trusted; lint gates and event-history cost math qualified to what a token-free container can actually run; --repo never inferred from origin.

Deferred (recorded, not silently dropped): the head-controller-vs-opener TOCTOU (same shape /tmux has carried since it shipped; a real fix pins the head SHA through the job), and the tmux-side siblings — *-tmux-* planted artifacts, raw-side emit_block caps, the .npmrc-exposed global install, its own fixed-port proxy, and pr-assets retention.

Tests: 9 new guards, every one mutation-verified — reverting each fix turns exactly one test red — including an executable escaping/size-cap/UTF-8 test for the publisher's own emit_block, and a fix to the earlier command-file test, which had been matching the tmux job's identically named step (the same helper shadowing the review flagged). 27/27 pass; prettier, eslint, repo-exact actionlint and yamllint clean.

中文说明

Codex 轮 + bot 后续共 22 条线程已全部在 b92ebfc3c 处理,逐条均有行内回复。其中两条经复现确属可利用:

  • 固定代理端口 8787:PR 生命周期脚本先于代理运行,可先行占位。对照实验显示旧代码代理 EADDRINUSE 死亡却仍报告 enabled 并把 agent 指向占位进程——等于让攻击者撰写"验证结果"。现改为临时端口 + root 专属端口文件 + PID 存活 + 每轮 nonce 三重就绪判定,新代码在同场景下于 :53693 正常启动。
  • extensions.worktreeConfigcore.hooksPath=/:已本地复现——该键对 git config --local 不可见、扩展本身在保留白名单内、rev-parse --git-path hooks 确返回 /,使 hook 清扫的递归删除以 root 身份指向文件系统根。现在先删 worktree 配置文件并 unset 扩展再解析 hooks,且拒绝清扫无法规范化到仓库 git 目录内的路径。

其余已修:shell 门禁大小写不敏感(GHA 表达式忽略大小写,@QWEN-CODE /VERIFY 此前落入仅查评论者分支)、docs-only 判定的 SIGPIPE(已复现)与可执行文档判定、tee 状态检查、137 按耗时区分看门狗与崩溃、agent verdict 仅在干净且有证据的运行中采信(否则输出"未完成"表述)、标记评论按 bot 归属与前缀匹配且 PATCH 失败回退新发、起跑状态不再覆盖旧报告、publish-verify 并入按 PR 并发组、👀 与拒绝说明的 PR 限定、verdict 限长读取、evidence find 守卫、生命周期脚本后二次清空上传暂存目录。

Skill 契约修正:逐 commit 表格仅在 depth 2 可达时给出;base 对照需断言内部 workspace 依赖 realpath;lint 门禁与事件历史成本测算按无凭证容器实际能力限定;--repo 不再从 origin 推断。

明确顺延(非静默忽略):head 控制者与 opener 不一致的 TOCTOU(与 /tmux 同源,需将 head SHA 贯穿 job);tmux 侧同款问题(预埋产物、emit_block 原始侧上限、.npmrc 全局安装、其自身固定端口代理、pr-assets 保留策略)。

测试:新增 9 条守卫,全部经变异验证(逐一回退修复各使一条测试变红),含发布侧 emit_block 的可执行转义/限长/UTF-8 测试;并修正了上一轮那条实际匹配到 tmux 同名步骤的测试。27/27 通过,prettier、eslint、仓库同款 actionlint 与 yamllint 全绿。

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Downgraded from Request changes to Comment: self-PR; CI failing: route. Reviewed. Suggestions are inline. Not reviewed: reverse audit — five-round hard cap reached before two consecutive dry rounds. Not reviewed: build-and-test — CI full-profile checks were skipped after route failed; Agent 7 selected no build/test command for the non-workspace files (the targeted workflow test was run separately: 27 passed).

— Codex GPT-5 via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
Comment thread .qwen/skills/verify-pr/SKILL.md Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml
Comment thread .qwen/skills/verify-pr/SKILL.md
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread scripts/tests/qwen-triage-workflow.test.js

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Not reviewed: Invariant agent A: state, timers, collections — .github/workflows/qwen-triage.yml, Invariant agent B: counters, return values, error taxonomies — .github/workflows/qwen-triage.yml, Invariant agent C: config fields, early returns — .github/workflows/qwen-triage.yml — its prompt was built, but no agent on record was launched with it.

— qwen3.7-max via Qwen Code /review

Third review round (31 findings). The unifying defect: everything the
lane pinned or swept happened BEFORE npm ci/build executed PR-authored
lifecycle scripts as node, so each control could be undone afterwards.

Trust boundary, rebuilt in order before the agent starts:
- kill every process owned by the build user and fail the step if any
  survives — a detached postinstall child could otherwise wait out each
  one-shot sweep and re-plant afterwards
- re-pin .qwen from the base commit again, now root-owned and read-only:
  the prepare step chowns the workspace to node, so a lifecycle script
  could rewrite the very skill that defines /verify-pr
- give the agent a fresh HOME/QWEN_HOME: qwen loads user-scope file
  commands from $HOME/.qwen, and /home/node belongs to the build user,
  so a planted commands/verify-pr.toml could shadow the pinned skill
- the model proxy now requires a per-run bearer token, closing the
  blind-localhost-scan path to an unauthenticated signer for the real
  model credential (a command the agent itself launches still inherits
  it — documented residual, not closed)

Authorization and lifecycle:
- re-verify the PR author's write permission at execution time and pin
  the authorized head OID; refuse if the checked-out HEAD^2 differs, so
  a push during the runner wait cannot smuggle in unreviewed code
- validate each principal separately: an empty author vanished in word
  splitting and left only the commenter checked
- honor MAINTAINER_ECS_RUNNER_DISABLED with an explicit notice instead
  of queueing forever against a disabled pool
- status comments carry a machine state marker; inferring 'running' from
  prose let a report quoting that sentence be overwritten
- previous-report.md snapshots the newest substantive report, never a
  weak/cancelled notice, so prior findings survive into the next round
- bot-identity lookup failures fail closed instead of widening the
  ownership filter to every user's comments
- publish-verify uses a per-run concurrency group: a per-PR group holds
  only one pending job, so a second /verify could cancel a completed
  run's pending publisher

Correctness:
- install/build failures are classified: signals, ENOSPC, registry and
  network errors are infra-error, not a PR verdict
- watchdog classification measures the child's own elapsed time, not
  shell-global $SECONDS which includes proxy setup
- assertions.json must be three non-negative integers with a positive
  total and total == pass + fail before it counts as evidence
- the proxy keeps its upstream deadline armed until the body ends and
  aborts upstream when the client disconnects
- cleanups remove .qwen/tmp itself: PR code can make it a symlink, and
  globbing below it deleted the target's contents as root (verified)
- emit_block materializes the escaped text and truncates on a character
  boundary via node — iconv -c passes an incomplete trailing sequence
  through on BSD (measured), which the new test caught

Skill: local mode requires the same isolation CI provides and must not
assume HEAD^1/HEAD^2 on a plain head checkout; shallow boundaries make
rev-list counts unreliable for per-commit claims; never run
scripts/lint.js with no arguments (it runs prettier --write and rewrites
the tree under the harnesses); a vacuity check must fail the intended
assertion, not the import. pr-workflow.md now says both sandboxed lanes
need the author to have write, so triage stops recommending a
guaranteed denial on external PRs.

Tests: 9 more guards, all mutation-verified, including executable
replays of the docs-only classifier (SIGPIPE + executable-markdown
cases), the uppercase-command gate, the empty-principal deny, and the
untrusted-image hosting path against a bare pr-assets remote.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. 3 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Unresolved, please confirm: [Critical] .github/workflows/qwen-triage.yml:2203 — Build-time artifact planting (comment 3650594856): body truncated, could not read full mechanism before ruling [Critical] .github/workflows/qwen-triage.yml:2238 — RUNNER_TEMP not cleaned between runs (comment 3650457730): body truncated, could not read full mechanism before ruling [Critical] .github/workflows/qwen-triage.yml:2251 — Publication outside serialization boundary (comment 3650561671): body truncated, could not read full mechanism before ruling [Critical] .github/workflows/qwen-triage.yml:2422 — Completed-method claim for non-validated results (comment 3650561689): body truncated, could not read full mechanism before ruling [Critical] .qwen/skills/verify-pr/SKILL.md — CI checkout per-commit requirement (comment 3650561667): body truncated, could not read full mechanism before ruling [Critical] .qwen/skills/verify-pr/SKILL.md — CI event history for cost math (comment 3650561677): body truncated, could not read full mechanism before ruling [Critical] .qwen/skills/verify-pr/SKILL.md — Repository selected by origin (comment 3650561683): body truncated, could not read full mechanism before ruling [Critical] .qwen/skills/verify-pr/SKILL.md — Workflow gates unavailable in container (comment 3650561684): body truncated, could not read full mechanism before ruling [Critical] .qwen/skills/verify-pr/SKILL.md:85 — Lockfile not enough for clean base control (comment 3650561675): body truncated, could not read full mechanism before ruling

— qwen3.8-max-preview via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Third review round (31 findings) — fixed in 3c5a0082f, 65 of 66 threads resolved

Every thread has a per-item reply. One is deliberately left open: 3650694817 (the loopback proxy is an unauthenticated relay for the model credential). It is partly fixed — a per-run bearer token now closes the blind-localhost-scan path — but a command the agent itself launches still inherits the token, and closing that properly means moving the model client outside the agent's process namespace. That is a larger change than this PR, so the thread stays open rather than being resolved on a partial fix.

The unifying defect this round found

Almost every finding was the same shape: the lane pinned and swept things before npm ci/npm run build executed PR-authored lifecycle scripts. Each control could simply be undone afterwards. 3650694849 (a detached postinstall can outlive its step and wait out any one-shot sweep) is what reframed it — a sweep racing a live process is not a control at all.

So the trust boundary is now rebuilt, in order, immediately before the agent starts: kill every process owned by the build user and fail closed if any survives → re-pin .qwen from the base commit again, now root-owned and read-only → sweep planted artifact dirs → create a fresh HOME/QWEN_HOME → launch. Ordering is asserted by test, and removing the process-cleanup block turns it red.

Confirmed by reproduction

  • .qwen/tmp symlink (3650694840): replacing it with a symlink makes rm -rf .qwen/tmp/* delete the target's contents as root. Both cleanups now remove the entry itself.
  • node scripts/lint.js with no arguments (3650694837): it calls prettier --write ., so the instruction I added last round would have rewritten the PR tree underneath the A/B and replay harnesses. Now --setup plus individual non-mutating checks, with the no-arg form explicitly forbidden.
  • iconv -c on BSD passes an incomplete trailing sequence through unchanged — found because the escaping test from 3650594862 failed. Truncation now goes through node and cuts on a character boundary.

One finding I could not reproduce

3650694835 (printf | head SIGPIPE aborting the publisher): replayed under set -euo pipefail at 58 KB, 200 KB and 399 KB raw (≈2 MB escaped) — all returned 0. The reason is accidental: the first capture already holds the truncated 45,000-byte value, so the || fallback re-truncates something short and never reaches the pipe-buffer threshold. Correct by accident is not worth keeping, so the escaped text is now materialized to a file and head reads the file.

Everything else

Authorization: execution-time re-verification of the author's write permission with the authorized head OID pinned and asserted after checkout (3650694851, which also closes the TOCTOU I deferred last round); per-principal validation so an empty author cannot vanish in word splitting; MAINTAINER_ECS_RUNNER_DISABLED answered with a notice instead of an indefinite queue. Comment lifecycle: a machine state marker instead of prose, substantive-report-only snapshots for the follow-up round, identity failures failing closed, and a per-run publisher concurrency group so no publisher can be displaced. Correctness: install/build failures classified as infra vs PR, watchdog timing measured on the child, full assertions.json validation, and the proxy deadline kept armed through the response body.

Skill and triage-skill corrections: local mode needs the same isolation CI provides and must not assume HEAD^1/HEAD^2; shallow boundaries make rev-list --count unreliable for per-commit claims; a vacuity check must fail the intended assertion, not the import; and pr-workflow.md now says both sandboxed lanes require the PR author to have write, so triage stops recommending a guaranteed denial on external PRs.

Tests: 9 more guards, all mutation-verified (36/36 green), including executable replays of the docs-only classifier (SIGPIPE and executable-markdown cases), the uppercase-command gate, the empty-principal deny, and the untrusted-image hosting path against a bare pr-assets remote.

Recorded as follow-ups, not silently dropped: full process-namespace isolation for the build phase; the model client outside the agent's namespace (3650694817); and the tmux-side siblings this lane's fixes do not cover.

中文说明

第 3 轮 31 条已在 3c5a0082f 修复,66 条线程中 65 条已 resolve,逐条均有行内回复。

刻意留开的 1 条是 3650694817(loopback 代理是模型凭证的无认证中继):已部分修复——每轮 bearer token 封堵了盲扫 localhost 的路径——但 agent 自己启动的命令仍会继承该 token,彻底修复需把模型客户端移出 agent 的进程命名空间,超出本 PR 范围,因此不以"部分修复"来 resolve。

本轮找到的共性缺陷:几乎所有问题都是同一形状——车道的 pin 与清扫都发生在 npm ci/npm run build 执行 PR 生命周期脚本之前,因此所有控制都能在之后被撤销。3650694849(detached postinstall 可存活并等过一次性清扫)促使我重构整段逻辑:与活进程赛跑的清扫根本不算控制。现在在 agent 启动前按序重建信任边界:终止构建用户全部进程且有残留即失败 → 再次从 base 重新 pin .qwen 并设为 root 只读 → 清扫预埋产物 → 新建 HOME/QWEN_HOME → 启动;顺序由测试断言,删除进程清理块即变红。

经复现确认.qwen/tmp 符号链接会让 rm -rf .qwen/tmp/* 以 root 删除链接目标内容;无参数 node scripts/lint.js 会执行 prettier --write .,会改写 PR 工作树;BSD 上 iconv -c 会原样输出截断的尾部序列(由上一轮新增的转义测试发现)。

未能复现的 1 条3650694835printf | head SIGPIPE 中断发布),在 58 KB / 200 KB / 399 KB 三种规模下均返回 0——原因是首次捕获已持有截断后的短值,回退分支达不到管道缓冲阈值。这属于"碰巧正确",仍已改为落盘后由 head 读文件。

其余修复涵盖执行时重新授权与 head OID 绑定、逐主体校验、kill switch 说明、状态标记与实质性报告快照、身份失败 fail closed、按 run 的发布并发组、安装/构建失败分类、看门狗计时、断言对象整体校验、代理响应体超时;以及 skill 与 triage skill 的多处契约修正。新增 9 条守卫测试,全部经变异验证(36/36 通过)。

已记录的后续项:构建阶段的完整进程命名空间隔离、把模型客户端移出 agent 命名空间(3650694817)、以及本车道修复未覆盖的 tmux 侧同款问题。

The new docs-only classifier replay passed on macOS and failed on CI
with `Cannot read properties of undefined (reading 'trim')`: its
60,001-entry fixture is ~889 KB and was passed as a single argv element.
Linux caps one argument at MAX_ARG_STRLEN (128 KB), so the spawn failed
with E2BIG and stdout was undefined; macOS has no per-argument limit and
only a ~1 MB total, so the same call succeeded locally (verified both).

Write the list to a temp file and pass the path. The harness now also
asserts the spawn succeeded, so a future spawn failure reports itself
instead of surfacing as a TypeError on undefined output.
@gwinthis

Copy link
Copy Markdown
Collaborator

Independent Linux replication report (static/replay battery + isolation-invariant audit)

Verdict: every locally-reproducible claim in the Reviewer Test Plan replicates on Linux, and each isolation invariant the description promises is present in the tree exactly as stated. This fills the PR's "Linux ⚠️" gap for the static/replay layer.

(Method note: GitHub's git endpoint was unreachable from this host mid-review, so the tree was fetched as an API tarball of head c25afbd8 — same content, no git metadata; none of the checks below need it.)

Replication results (Linux, Node 22-workspace toolchain)

Check Result
qwen-triage.yml parses (js-yaml)
scripts/tests/qwen-triage-workflow.test.js 36/36 passed
All 29 run: blocks extracted from the YAML → bash -n ✅ 0 syntax failures
Both embedded loopback-proxy heredocs → node --check
Verdict allowlist replay (exact extraction pipeline: head -c 4096 | tr -d [:space:] | cut -c1-32 + case allowlist) merge-ready/findings (incl. padded) accepted; PWNED @everyone, findings; rm -rf /, blocked<img onerror=…>, mergeready all rejected to empty

The bounded-read comment in the verdict step is worth its bytes: head -c before the pipeline so an oversized file SIGPIPEs the producer harmlessly under pipefail — a small thing done precisely.

Isolation-invariant audit (each claim located in the tree)

  • Verifier can't be rewritten by the tree under test: .qwen staged via git archive 'HEAD^1' (present at both clone sites).
  • Pre-planted report defense: find tmp -maxdepth 2 -type d -name '*-verify-*' -exec rm -rf runs after checkout and after staging.
  • No token in the agent's reach: the agent step sets GITHUB_TOKEN: '' / GH_TOKEN: '' and launches through runuser … env -u GITHUB_OUTPUT -u GITHUB_STATE …; zero TOKEN/PAT references inside the agent launch block.
  • Model key behind the proxy: both proxy instances enforce POST + /chat/completions only, and the new PROXY_TOKEN bearer closes the localhost blind-scan path — with an honest comment about what it does not protect against (children of the agent inherit the env). That comment is the right kind of security writing.
  • No approval-surface widening: qwen-triage-finalize.yml gates on workflow_run.event == 'pull_request', so issue_comment-borne verify runs are structurally outside both the CI table and the deferred-approval gate, as claimed.
  • Untrusted image payloads: hosting caps (8 images, ≤2 MB) with explicit degradation copy when nothing passes; assets namespaced under verify/pr<N>-<run>-<attempt>/.

Scope of this replication

The live end-to-end agent round (real model, merge-ref worktree, artifact contract, A/B mutation audit) was not re-run here — it needs the runner secret wiring, and the PR's own adversarial audit of it (318-assertion decomposition, 13/13→7/13→13/13 mutation triplet) is the most rigorous self-verification I've seen in this repo. The static/replay layer above is exactly the part that was untested on Linux, and it is clean.

One observation, not a finding: this PR operationalizes the same evidence discipline several recent reviews converged on (A/B against base, tests-on-base vacuity checks, wire oracles over mocks) — encoding it as an on-demand CI lane with a stricter isolation contract than any hand-run round. The methodology sections of verify-pr/SKILL.md double as the best available documentation of how verification is actually done in this repo.

@wenshao

wenshao commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

Thank you — this is the one gap I could not close myself, and closing it on Linux is exactly the part that mattered: the whole static/replay battery in my test plan ran on macOS, and macOS is precisely where the platform differences hide. Two of this PR's real defects were found through that lens (iconv -c passing an incomplete trailing UTF-8 sequence through on BSD, and a 889 KB single argv element that macOS accepts and Linux rejects with E2BIG — the latter turned CI red on 3c5a0082f and is fixed in c25afbd8, the head you replicated).

I have updated the PR description accordingly: the Tested-on Linux row is now ✅ static/replay · ⚠️ live run, with your replication linked and the residual named exactly — the live path (jobs on a real Actions runner with the runner secrets) is what no local or third-party replication can cover before merge. I also corrected a stale claim your report exposed: the description still said "9 new run: blocks" from the first commit; the lane's own blocks are now 13, and your 29 covers the whole workflow.

One correction to the credit, though: the isolation invariants you audited are not all as originally designed — most of them are the result of review rounds on this PR, and several were rewritten as recently as 3c5a0082f. The PROXY_TOKEN bearer you singled out is one of those, and the honest comment beside it exists because a reviewer showed the fixed port 8787 was genuinely hijackable (a squatter answers the health probe while the real proxy dies EADDRINUSE). The git archive 'HEAD^1' pin you found at both clone sites is there twice for the same reason: pinning once before npm ci was not enough, because lifecycle scripts run afterwards and the workspace is chowned to the build user in between.

That leaves one open thread by design: 3650694817. The bearer closes the blind-localhost-scan path but not a command the agent itself launches, which inherits the token — a real fix needs the model client outside the agent's process namespace. I would rather leave that visible than resolve it on a partial fix.

中文说明

感谢——这正是我自己无法闭合的那一块,而且在 Linux 上闭合恰恰是关键:我测试方案里的整套静态/回放验证都跑在 macOS 上,而 macOS 正是平台差异藏身之处。本 PR 有两个真实缺陷就是从这个角度暴露的:BSD 上 iconv -c 会原样输出截断的 UTF-8 尾部序列;以及一个 889 KB 的单个 argv 参数——macOS 接受、Linux 以 E2BIG 拒绝,它让 3c5a0082f 的 CI 变红,已在你复现的这个 head c25afbd8 上修复。

PR 描述已相应更新:Tested on 的 Linux 一行改为 ✅ 静态/回放 · ⚠️ 实际运行,附上你的复现链接,并明确剩余项——实际运行路径(在真实 Actions runner 上带 secret 执行)是合并前任何本地或第三方复现都无法覆盖的。另外你的报告也暴露出一处过时表述:描述里仍写着首个提交的"9 个新 run: 块",本车道现为 13 个,而你统计的 29 个是整个 workflow 的数量,已一并更正。

不过有一处功劳需要澄清:你审计的这些隔离不变量并非都是最初设计好的,多数是本 PR 评审轮次的产物,其中数项直到 3c5a0082f 才改写完成。你特别提到的 PROXY_TOKEN 就是其一,旁边那段"诚实的注释"之所以存在,是因为有评审者证明固定端口 8787 确实可被劫持(占位进程回应健康探测,而真代理以 EADDRINUSE 死亡)。你在两处 clone 点都看到的 git archive 'HEAD^1' pin 之所以出现两次,也是同一原因:只在 npm ci 之前 pin 一次不够,因为生命周期脚本在其之后运行,而工作区在这中间已 chown 给构建用户。

因此有一条线程是刻意留开的:3650694817。bearer 封堵了盲扫 localhost 的路径,但封不住 agent 自己启动的命令(会继承该 token),彻底修复需要把模型客户端移出 agent 的进程命名空间。与其以部分修复 resolve 掉,我更愿意让它保持可见。

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: issue-fidelity — its prompt was built, but the harness transcript does not match the CLI-built brief. Not reviewed: build-and-test — its prompt was built, but the harness transcript does not match the CLI-built brief. Not reviewed: Agent 0: Issue fidelity & root-cause ownership, Agent 7: Build & test verification — its prompt was built, but no agent on record was launched with it. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies. Not reviewed: verification — a verifier ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and the posted findings cannot be counted as verified against it.

— qwen3.7-max via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml Outdated
Comment thread .github/workflows/qwen-triage.yml Outdated
…uced

Three publisher findings, all introduced by my own previous round:

- an artifact download failure (the step is continue-on-error) let the
  full-report path run with no results: the headline read 'completed' and
  the scope paragraph claimed the A/B, the harnesses and the gates had
  run when nothing had been delivered. The download outcome is now an
  input, and its failure gets its own body saying the results could not
  be retrieved
- the prepare-failure branch ignored the verdict the prepare step had
  just computed, so an install killed by a registry outage or OOM
  (classified infra-error) still told the author 'this is treated as a
  PR failure verdict rather than an infrastructure failure' — the exact
  opposite. It now branches on the verdict, and an infra-classified
  prepare failure is a weak body that cannot overwrite a real report
- weak notices were being snapshotted as the follow-up round's
  previous-report.md: they lack the running marker, so 'newest
  non-running comment' selected them. Bodies that carry findings now
  mark themselves (qwen-triage:verify-substantive) and the snapshot
  selects on that marker. A/B on the real jq: report A then cancelled B
  now snapshots A (101), the old filter picked B (102)

Tests: 4 more guards, all mutation-verified — the publisher is rendered
for each outcome with a stubbed gh and the assertions read the body it
would post, and the snapshot test runs the workflow's own jq program
verbatim against a paginate-shaped fixture.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed — no blockers. Suggestions are inline.

— qwen3.7-max via Qwen Code /review

Comment on lines +72 to +74
startsWith(github.event.comment.body, '@qwen-code /tmux ') ||
github.event.comment.body == '@qwen-code /verify' ||
startsWith(github.event.comment.body, '@qwen-code /verify '))) ||

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] GitHub Actions startsWith() is case-sensitive for characters, while == is case-insensitive. The shell gate below lowercases the body (body_lc) and handles uppercase correctly — but this job-level if predicate uses startsWith on the raw body. A comment like @QWEN-CODE /VERIFY please (uppercase + trailing text) fails both branches: == because of the suffix, startsWith because of the case mismatch — and the authorize job is silently skipped.

Concrete cost: a maintainer who types /VERIFY in caps with any trailing text gets no ack, no report, no error — just silence.

The same pattern appears in 5 other locations: the verify job if, the three acknowledge/deny/explain steps, and the concurrency group expression. Consider startsWith(toLower(github.event.comment.body), '@qwen-code /verify ') across all six.

— qwen3.7-max via Qwen Code /review

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Not a defect — startsWith() is case-insensitive. The expressions reference states it explicitly: contains(), startsWith() and endsWith() are each documented as "not case sensitive", alongside "GitHub ignores case when comparing strings" for ==. So @QWEN-CODE /VERIFY please matches startsWith(…, '@qwen-code /verify ') and the job does fire — no silent skip.

Worth stating why the shell still lowercases, since it looks redundant next to this: the two layers have opposite semantics. The Actions expression layer is permissive (case-insensitive), so uppercase forms reach the step; the shell case is strict, and before b92ebfc3c an uppercase /VERIFY passed the job predicates and then fell through to the commenter-only branch — running the author's code with the author never checked. The lowercasing exists to make the strict layer agree with the permissive one, which is exactly why toLower() in the predicates is not needed.

该条不成立——startsWith() 是大小写不敏感的。 官方表达式文档明确写着 contains()/startsWith()/endsWith() 均 "not case sensitive",与 == 的 "GitHub ignores case when comparing strings" 并列。因此 @QWEN-CODE /VERIFY please 能匹配 startsWith(…, '@qwen-code /verify '),job 会正常触发,不存在静默跳过。

顺带说明 shell 侧为何仍要小写化(看起来冗余,其实两层语义相反):表达式层宽松(不区分大小写),大写形式会进入步骤;而 shell 的 case 严格匹配——在 b92ebfc3c 之前,大写 /VERIFY 正是这样通过 job 条件后落入"仅查评论者"分支,导致在未校验作者的情况下执行其代码。小写化的作用就是让严格层与宽松层对齐,也正因如此,谓词里无需再加 toLower()

Comment thread .github/workflows/qwen-triage.yml
Comment thread .github/workflows/qwen-triage.yml
Two review findings plus a test-helper hazard:

- classify_failure grepped the prepare log for bare words like ENOSPC
  and ETIMEDOUT, but that log is written by PR-controlled code: a
  genuine build failure that merely prints 'expected ETIMEDOUT to equal
  ok' would be published as an infrastructure incident, telling the
  author to re-run something that fails identically. The patterns are
  now anchored to lines only npm's reporter or the kernel emits
  ('npm ERR! code E…', 'npm ERR! network …', kernel OOM, bare 'Killed');
  a signal exit still needs no log evidence. Replayed 10 cells: four
  PR-authored logs quoting infra words stay 'fail', five real
  diagnostics and one signal exit are 'infra-error'
- the two execution-time controls added last round — re-verifying the
  author's permission after the runner wait, and refusing a head that
  moved since authorization — had no tests. Both are now executed:
  the re-auth snippet against a stubbed permission API (write proceeds
  and pins head_oid; read skips with a publishable reason), and the pin
  step against a real git repo with a real merge commit (matching head
  proceeds, moved head exits non-zero)
- add a stepIn(job, step) test helper. Several step names exist in both
  the tmux and verify jobs, and the unscoped step() returns the first
  match, so a verify-lane assertion silently tests the tmux copy — that
  has now bitten this suite three times, including in this commit.

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

No issues found. LGTM! ✅

中文说明

未发现问题。LGTM!✅

— qwen3.7-max via Qwen Code /review

…te liveness

Fold techniques from the round-2 verification on #7620 (an ANSI parser
PR) that the skill had no equivalent for:

- test-only PRs get their own method: a mutation A/B across TEST FILES
  (same mutants of the unmodified production file, only the test file
  swapped), reporting killed/total on both sides, requiring that no
  mutant regressed from killed to survived, checking that the killing
  assertion is the one the commit claims to have strengthened, and
  adjudicating every survivor as coverage gap or defect with independent
  evidence rather than by inspection
- when the code emulates a known implementation, that implementation is
  the oracle: feed identical input to both and report disagreement
  counts per side, lift reference tables verbatim out of the shipped
  dependency, and build the corpus from bytes captured off a real
  producer alongside synthesized sweeps
- prove a gate is live before citing it: plant a violation the linter
  must catch, confirm it is reported, remove it — a linter that matched
  no files exits 0 exactly like one that passed
- attribute pre-existing failures by byte-identical failing file AND
  test names on both sides, with deltas, not just totals
- when the base is far behind, verify the merge: trial-merge into
  current main, confirm it is conflict-free, and re-run the affected
  suite on the merged tree
- round continuity gains its one legitimate shortcut: a production file
  proven byte-identical (sha256 quoted at both heads) carries prior
  evidence forward by construction
The previous commit's added paragraphs were hand-wrapped and prettier
--check flagged the file; the repo runs prettier over all of it.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.

中文说明

已审查。 建议见行内评论。 未审查:反向审计——有审计 agent 运行并打开了自己的 brief,但没有 agent 是用 CLI 构建的 prompt 启动的——启动 prompt 是手写的,agent 实际被要求做的并不是本 skill 所认证的内容。

— qwen3.7-max via Qwen Code /review

Comment thread .github/workflows/qwen-triage.yml
The kill-switch path had no test: a refactor could drop the notice and
leave a /verify request acknowledged with 👀 but permanently unanswered,
since the verify job refuses to start and publish-verify skips with it.

Fold the step into the existing PR-guard loop (now scoped through
stepIn, so it cannot match a same-named step in another job) and assert
the parts that make the answer useful — the kill-switch and permission
conditions, both languages, the alternative it points at, and the verify
job's own exclusion of the disabled pool. All three mutations turn it
red: removing the step, dropping its PR guard, or letting the verify job
queue against the disabled pool.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants