Skip to content

fix(autofix): state the primary agent budget and use the step's headroom - #8257

Merged
wenshao merged 8 commits into
mainfrom
autofix-agent-budget
Aug 1, 2026
Merged

fix(autofix): state the primary agent budget and use the step's headroom#8257
wenshao merged 8 commits into
mainfrom
autofix-agent-budget

Conversation

@wenshao

@wenshao wenshao commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Problem

The primary address attempt never stated its own budget, so it took run-agent.mjs's 50-minute default while the step that wraps it caps at 80. A third of the step was unreachable, and every AutoFix ran out of time before finishing (timeout (3000000ms)) round ended for a reason this workflow does not mention anywhere.

Measured on the #8005 round-9 timeout (run 30646547838, job 91211427276), per-step:

phase #8005 round 9 (timed out) #8211 (succeeded)
setup — checkout, install, build, 12 steps 7m10s 5m17s
Triage and address 50m03s — the agent's own timer, not the step cap 12m45s
Verification gate skipped 22m48s
push, report, finalize 3s 4s
job total 57m of 150 41m of 150

The setup runs in earlier steps, so it never competed with the agent for the 80 minutes. The step cap was doing nothing except sitting 30 minutes above the number that actually ends a round.

Raising the agent's budget surfaced the larger problem: the round's budget was never checked as a whole. The Verification gate is the job's largest consumer at 22m48s and had no step bound at all — only the job timeout held it. So the real worst case was 7 + 80 + 23 + 20 + 23 = 153 against a 150-minute job, and a JOB timeout cancels the always() reporters, which is exactly the silent round this design exists to prevent. Every assertion in the suite passed while that was true.

Change

Sized for the PRs that actually exhaust the budget (47 and 35 changed files), so this does not need revisiting per PR:

before after
agent budget (QWEN_TIMEOUT_MS) implicit 50m 120m, QWEN_AUTOFIX_TIMEOUT_MS overrides
Triage and address step cap 80m 130m (10m margin over the budget)
Verification gate unbounded 60m
Repair verification gate unbounded 60m
review-address job 150m 300m

Worst case is now 7 (setup) + 130 + 60 + 20 (repair) + 60 + 3 (report) = 280 against 300, itself under the 360-minute ceiling ubuntu-latest imposes regardless.

The 10-minute margin under the step cap has a job: the cap is the backstop for a runaway that ignores the internal timer, and if it fires first the internal kill path never writes agent-timeout — the file the report step reads to tell a timeout apart from a crash. That path only writes the file and exits, which is what the measured 3 seconds were.

Bounding the two verification gates is a graceful degrade, not a new way to fail: both already carry continue-on-error: true, so a bound turns a job-level kill into the ordinary verification-failure path — Finalize verification sees an empty outcome, falls through its case to exit 1, and the always() report step posts.

This buys rounds that were close to finishing, not rounds that were never going to. An exhausted budget still pushes nothing, which is the whole reason the breakers exist, and TIMEOUT_WINDOW_CAP still stops a PR after three time-budget exhaustions in one window. #8005 currently carries one.

What this deliberately does not do

The timeouts are not obviously size-driven, and I did not build a heuristic on data that thin. Across the five PRs autofix touched in that scan:

PR timeouts changed files additions
#8005 1 47 4946
#8077 1 35 186
#8147 0 2 539
#8211 0 14 1333
#8116 0 11 289

#8077 timed out on 186 added lines while #8211 finished with 1333, so line count is not it; file breadth fits better (47 and 35 timed out, 14/11/2 did not). That is a shape in five points, not an established cause — a width-scaled budget would be a knob built on a guess, so this change raises the flat budget and leaves the question open.

Tests

The test derives both numbers from the workflow and asserts the margin between them, rather than restating them as two literals — a pair asserted as two constants cannot catch the pair drifting, which is exactly how they came to be 30 minutes apart.

The invariant asserted is the sum against the job cap, plus the count of bounded steps — asserting the numbers individually is precisely what let 153-against-150 pass.

mutation result
budget raised above its step cap caught
Verification gate bound removed caught
Repair verification gate bound removed caught
job cap back to 150 (sum 280 > 150) caught
job cap above the runner's 360-minute ceiling caught
continue-on-error dropped from a gate caught
unmutated green

The fallback behaviour was executed rather than read — the real expression from run-agent.mjs:21 against each input:

"7200000"  => 7200000 ms = 120 min
""         => 3000000 ms = 50 min   (unset var)
"abc"      => 3000000 ms = 50 min   (malformed)
"0"        => 3000000 ms = 50 min   (cannot disable the timer)

scripts/tests/qwen-autofix-workflow.test.js 107/107 (and qwen-triage-workflow.test.js 116/116 unaffected); actionlint, yamllint, eslint --max-warnings 0 clean.

中文说明

问题

主处理尝试从未声明自己的预算,因此沿用了 run-agent.mjs 的 50 分钟默认值,而包裹它的 step 上限是 80 分钟。step 有三分之一永远用不到,并且每一次 AutoFix ran out of time before finishing (timeout (3000000ms)) 的轮次,其真正结束原因在本工作流里根本没有出现过。

在同一次扫描中实测(run 30646547838),逐步耗时:

阶段 #8005 第 9 轮(超时) #8211(成功)
setup —— checkout、安装、构建,共 12 步 7分10秒 5分17秒
Triage and address 50分03秒 —— 是 agent 自己的计时器,不是 step 上限 12分45秒
Verification gate 跳过 22分48秒
push、上报、finalize 3 秒 4 秒
job 合计 57 分钟 / 150 41 分钟 / 150

setup 跑在更早的 step 里,因此从未与 agent 争夺那 80 分钟。step 上限除了悬在真正结束轮次的那个数字之上 30 分钟以外,什么也没做。

调高 agent 预算时暴露出更大的问题:这一轮的预算从未被作为整体检查过。 Verification gate 是本 job 中最大的消耗项(22分48秒),却完全没有 step 约束——只有 job 上限兜着。于是真实最坏情况是 7 + 80 + 23 + 20 + 23 = 153,而 job 上限是 150;且 job 级超时会连 always() 的上报步骤一起取消,正是本设计要避免的「静默轮次」。在这个事实成立期间,测试套件的每一条断言都是通过的。

改动

按真正会耗尽预算的那类 PR(47 与 35 个改动文件)来定尺寸,以免逐个 PR 反复调整:

改前 改后
agent 预算(QWEN_TIMEOUT_MS 隐式 50 分钟 120 分钟,可由 QWEN_AUTOFIX_TIMEOUT_MS 覆盖
Triage and address step 上限 80 分钟 130 分钟(较预算留 10 分钟余量)
Verification gate 无约束 60 分钟
Repair verification gate 无约束 60 分钟
review-address job 150 分钟 300 分钟

最坏情况变为 7(setup)+ 130 + 60 + 20(修复)+ 60 + 3(上报)= 280,对 300;而 300 本身也在 ubuntu-latest 无论如何都会施加的 360 分钟上限之内。

step 上限之下的那 10 分钟余量是有职责的:该上限是用来拦住忽略内部计时器的失控 agent 的兜底,一旦它先触发,内部终止路径就不会写出 agent-timeout——那正是上报步骤用来区分「超时」与「崩溃」的文件。该路径只写这个文件然后退出,实测的那 3 秒就是它。

给两个验证门加约束是优雅降级,而不是新增一种失败方式:两者本就带有 continue-on-error: true,因此加上约束会把 job 级的击杀转化为普通的验证失败路径——Finalize verification 读到空 outcome,落入其 case 的兜底分支 exit 1,随后 always() 的上报步骤照常发出。

这买到的是那些差一点就能跑完的轮次,而不是那些本来就跑不完的轮次。 预算耗尽依旧什么都推不出去,这正是熔断器存在的理由,TIMEOUT_WINDOW_CAP 仍会在一个窗口内三次预算耗尽后停掉该 PR。#8005 目前是 1 次。

本次刻意没有做的事

这些超时并不明显由体量驱动,我不会在这么薄的数据上造启发式。该次扫描中 autofix 处理的五个 PR:

PR 超时次数 改动文件 新增行
#8005 1 47 4946
#8077 1 35 186
#8147 0 2 539
#8211 0 14 1333
#8116 0 11 289

#8077 只新增 186 行却超时,而 #8211 有 1333 行反而跑完,因此不是行数;文件宽度拟合得更好(47 与 35 超时,14/11/2 未超)。但这是五个点上的形状,不是已确立的因果——按宽度缩放的预算会是建立在猜测上的旋钮,所以本次只调高统一预算,把这个问题留着。

测试

断言的不变量是各步上限之和对 job 上限,外加受约束步骤的数量——把这些数字逐个断言,正是让「153 对 150」一路通过的原因。

变异 结果
预算高于其 step 上限 被捕获
移除 Verification gate 约束 被捕获
移除 Repair verification gate 约束 被捕获
job 上限退回 150(和为 280 > 150) 被捕获
job 上限超过 runner 的 360 分钟上限 被捕获
从验证门移除 continue-on-error 被捕获
未变异 绿

回退行为是被执行验证的,不是阅读得出的——用 run-agent.mjs:21 的真实表达式跑各输入:

"7200000"  => 7200000 ms = 120 分钟
""         => 3000000 ms = 50 分钟   (变量未设置)
"abc"      => 3000000 ms = 50 分钟   (格式错误)
"0"        => 3000000 ms = 50 分钟   (无法关闭计时器)

scripts/tests/qwen-autofix-workflow.test.js 107/107(qwen-triage-workflow.test.js 116/116 未受影响);actionlint、yamllint、eslint --max-warnings 0 均干净。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template: the body uses its own headings (Problem / Change / Tests) rather than the template's, but everything the template asks for is here and then some — motivation with a measured reproduction, a reviewer test plan, scope/risk, and a Chinese translation. Treating it as satisfied; no need to reformat.

Problem: observed, not theoretical. The #8005 round-9 timeout (run 30646547838) is cited with per-step timings — the agent died at exactly 50m03s on its own timer while the step cap sat at 80m, so a third of the step was unreachable and every "ran out of time" round ended for a reason this file never mentioned. I confirmed the mechanism in the base code: run-agent.mjs:21 defaults QWEN_TIMEOUT_MS to 50 minutes, the primary "Triage and address" step sets no QWEN_TIMEOUT_MS (so it inherits that default), and the kill path writes the agent-timeout file the report step reads. The drift is real.

Direction: aligned. This is internal autofix CI tooling and squarely in scope; it touches no auth/sandbox/model-selection/public-contract surface (the existing secret-forwarding note is unchanged). No CHANGELOG signal to cite — this is repo-specific CI infra, not a product feature.

Size: not applicable — no core paths. 61 additions across .github/workflows/qwen-autofix.yml (28) and its test (33), zero deletions.

Approach: the scope is right and the change is minimal — one env var (QWEN_TIMEOUT_MS = 70m, overridable via vars.QWEN_AUTOFIX_TIMEOUT_MS) plus a test that derives both the cap and the budget from the workflow and asserts the margin, instead of restating two literals that could drift again. That's the better version of this fix. I also appreciate the explicit "what this deliberately does not do" — declining to build a width-scaled budget on five data points is the right call. The inline comments are thorough; they document a genuinely non-obvious invariant (why the margin exists, why 70), so they earn their place, though a reviewer may weigh whether some of it belongs in the commit message.

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

Moving on to code review. 🔍

中文说明

感谢贡献!

模板:正文使用了自己的小标题(Problem / Change / Tests),但模板要求的内容全都具备,而且更充分——带有实测复现的动机、reviewer 测试计划、范围/风险、以及中文翻译。视为满足,无需重排格式。

问题:是已观测到的,而非理论性的。PR 引用了 #8005 第 9 轮超时(run 30646547838)的逐步耗时——agent 恰好在 50分03秒时被自己的计时器终止,而 step 上限悬在 80 分钟,因此 step 有三分之一永远用不到,每一次"超时"轮次都以一个本文件从未提及的原因结束。我在基线代码里确认了机制:run-agent.mjs:21QWEN_TIMEOUT_MS 默认设为 50 分钟,主"Triage and address"步骤没有设置 QWEN_TIMEOUT_MS(于是继承该默认值),而终止路径会写出 report 步骤所读取的 agent-timeout 文件。漂移是真实存在的。

方向:对齐。这是内部 autofix CI 工具,完全在范围内;不触及 auth/sandbox/模型选择/公共契约面(既有的 secret 转发说明保持不变)。没有可引用的 CHANGELOG 信号——这是仓库专属的 CI 基础设施,不是产品功能。

规模:不适用——未触及核心路径。共 61 行新增,分布在 .github/workflows/qwen-autofix.yml(28)及其测试(33),零删除。

方案:范围合理,改动最小——一个环境变量(QWEN_TIMEOUT_MS = 70 分钟,可通过 vars.QWEN_AUTOFIX_TIMEOUT_MS 覆盖),外加一个从工作流中同时推导上限与预算并断言其余量的测试,而不是把两个可能再次漂移的字面量重述一遍。这是该修复的更优版本。我也欣赏明确的"本次刻意没有做的事"——拒绝在五个数据点上造一个按宽度缩放的预算,是正确决定。内联注释很详尽;它们记录了一个确实不显然的不变量(余量为何存在、为何取 70),因此值得保留,尽管 reviewer 可以权衡其中一部分是否该放进 commit message。

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

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review

My independent take before reading the diff: set QWEN_TIMEOUT_MS explicitly on the primary step to a value safely under the 80-minute cap, make it overridable by repo variable, and pin the cap↔budget relationship in a test so they can't silently drift again. The PR does exactly this, and the test is the better version — it derives both numbers from the workflow and asserts the margin, where I might have lazily asserted two literals (which is precisely how they came to be 30 minutes apart).

Verified against the base code:

  • run-agent.mjs:21Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000. The fallback table in the PR is correct: "", "abc", and "0" all fall through to the 50-minute default, so the timer can't be disabled via the variable.
  • The timer (~line 225) kills at QWEN_TIMEOUT_MS and the kill path writes agent-timeout (~line 330); the report step reads that file (~workflow line 4153) to tell a timeout from a crash. This is exactly why the budget must stay under the cap — if the cap fires first, agent-timeout is never written. 70m under 80m leaves a 10-minute margin for a path that measures ~3 seconds. Ample.
  • The repair step already carried QWEN_TIMEOUT_MS: '1080000' (18m) under its 20m cap; the new test pins that margin too.
  • Worst-case arithmetic holds: 7m setup + 80m cap + 20m repair + reporting stays inside the 150m job timeout.

No correctness, security, or convention issues. The change is one env var plus comments plus a test; no new secret surface (the value comes from vars, not secrets), and the pre-existing secret-forwarding note is untouched. The comments are verbose for this repo's taste, but the why (the margin's job, the drift history) is genuinely non-obvious in a workflow file, so I'd leave them.

Testing

This is an unattended CI run — I did not build or run the PR's code (per the static-review rule). The signal below is the PR's own CI on the reviewed commit.

The claim under review is a static workflow invariant (budget under cap with margin), which the new test substantiates by construction — it parses the actual YAML and asserts the relationship, and the PR's mutation table reports it catches a removed / over-cap / too-close budget. I could not independently re-run that mutation table here; I'm treating it as the author's claim, but the test's design does pin the invariant. The relevant suite is still running, so confirmation is pending — the table below updates in place once CI settles.

No user-visible / TUI behavior changes, so real-scenario (tmux) testing is N/A.

Check Conclusion
Test (ubuntu-latest, Node 22.x) ⏳ in progress
Test (macos-latest, Node 22.x) skipped
Test (windows-latest, Node 22.x) skipped
Integration Tests (CLI, No Sandbox) skipped
Classify PR / label / authorize success

The ubuntu suite carries scripts/tests/qwen-autofix-workflow.test.js; macOS / Windows / integration are skipped for this change. No red checks.

中文说明

代码审查

我在读 diff 之前的独立想法:在主步骤上显式设置 QWEN_TIMEOUT_MS,取一个安全低于 80 分钟上限的值,使其可由仓库变量覆盖,并在测试中钉住"上限↔预算"的关系,让它们无法再次悄悄漂移。PR 正是这么做的,而且测试是更优版本——它从工作流中同时推导两个数字并断言余量;我本来可能偷懒地断言两个字面量(而它们相差 30 分钟恰恰就是这么来的)。

已对照基线代码核实:

  • run-agent.mjs:21 —— Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000。PR 的回退表正确:"""abc""0" 都会落回 50 分钟默认值,因此无法通过该变量关闭计时器。
  • 计时器(约 225 行)在 QWEN_TIMEOUT_MS 处终止进程,终止路径写出 agent-timeout(约 330 行);report 步骤读取该文件(工作流约 4153 行)以区分超时与崩溃。这正是预算必须低于上限的原因——若上限先触发,agent-timeout 永远不会被写出。70 分钟低于 80 分钟,留出 10 分钟余量,而该路径实测约 3 秒。绰绰有余。
  • 修复步骤本就带有 QWEN_TIMEOUT_MS: '1080000'(18 分钟),低于其 20 分钟上限;新测试也钉住了这个余量。
  • 最坏情况算术成立:7 分钟 setup + 80 分钟上限 + 20 分钟修复 + 上报,仍在 150 分钟 job 超时之内。

无正确性、安全性或规范问题。改动就是一个环境变量加注释加一个测试;没有新的 secret 面(值来自 vars 而非 secrets),既有的 secret 转发说明保持不变。注释对本仓库的口味偏多,但其 why(余量的职责、漂移的历史)在工作流文件里确实不显然,因此我倾向保留。

测试

这是一次无人值守的 CI 运行——我未构建或运行 PR 的代码(遵循静态审查规则)。下方信号是 PR 自身在被审查 commit 上的 CI。

本次审查的主张是一个静态工作流不变量(预算低于上限且有余量),新测试从构造上就证实了它——它解析真实的 YAML 并断言该关系;PR 的变异表报告说它能捕获"移除/超上限/过近"的预算。我无法在此独立重跑该变异表;我将其视为作者的主张,但测试的设计确实钉住了该不变量。相关测试套件仍在运行,因此确认尚待——下方表格会在 CI 落定后就地更新。

无用户可见 / TUI 行为变化,因此真实场景(tmux)测试为 N/A。

ubuntu 套件承载 scripts/tests/qwen-autofix-workflow.test.js;macOS / Windows / 集成测试对本次改动跳过。无红色检查。

Qwen Code · qwen3.8-max-preview

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean, minimal, well-evidenced fix from a maintainer; the only open item is the ubuntu suite still running, which the deferred approval waits on.

Stepping back: this is exactly the kind of PR the gate should wave through. The problem is measured (a real CI run, per-step timings), the fix is the smallest thing that solves it (one env var, made visible next to the cap it must stay under), and the test pins the invariant that actually broke — the two numbers drifting apart — rather than restating them. My independent proposal was the same idea; the PR's test is better than the lazy version I'd have written. The restraint in not building a width-scaled budget on five data points is the right KISS call.

The one mild reservation: the inline comments are on the verbose side. They document a real invariant, so I wouldn't block on it, but a reviewer may decide some of the rationale belongs in the commit message rather than the YAML.

Approval is deferred only until CI lands green on the reviewed commit — the ubuntu suite carrying the workflow test is still in progress. Once it's green, this is ready to ship.

中文说明

置信度:4/5 —— 来自维护者的干净、最小、证据充分的修复;唯一未决项是仍在运行的 ubuntu 套件,延迟批准正在等待它。

退一步看:这正是 gate 应当放行的那类 PR。问题是实测的(真实的 CI run、逐步耗时),修复是解决它的最小改动(一个环境变量,放在它必须低于的上限旁边使其可见),测试钉住了真正被破坏的不变量——两个数字彼此漂移——而不是把它们重述一遍。我的独立方案是同一个想法;PR 的测试比我本来会写的偷懒版本更好。拒绝在五个数据点上造一个按宽度缩放的预算,是正确的 KISS 决定。

唯一的一点保留:内联注释偏多。它们记录了一个真实的不变量,因此我不会因此阻塞,但 reviewer 可以决定其中一部分理由该放进 commit message 而非 YAML。

批准仅延迟到 CI 在被审查 commit 上转绿——承载工作流测试的 ubuntu 套件仍在运行。一旦转绿,即可合入。

Qwen Code · qwen3.8-max-preview

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

The primary attempt took run-agent.mjs's 50-minute default while its step
capped at 80, so a third of that step was unreachable and every "ran out
of time" round ended for a reason this file never named. Raising it
surfaced the larger problem: the budget was never checked as a whole.

Measured on one scan (run 30646547838): setup 5-7m in earlier steps, so
it never competes with the agent step; Triage and address 50m03s on #8005
round 9 (its own timer) and 12m45s on #8211; the Verification gate 22m48s
on #8211 — the largest consumer in the job, and unbounded; push, report
and finalize 3-4s. The old arithmetic ("80 + 20 leaves ~50 for setup, two
verification passes, and reporting") predates that measurement: the real
worst case was 7 + 80 + 23 + 20 + 23 = 153 against a 150-minute job, and
a JOB timeout cancels the always() reporters, which is the silent round
the design exists to prevent.

Sized for the PRs that actually exhaust the budget (47 and 35 changed
files): agent 120m under a 130m step cap, each verification gate bounded
at 60m — 2.6x the measured pass, and a graceful degrade because both
gates already carry continue-on-error, so a bound turns a job kill into
the ordinary verification-failure path that reports. Worst case
7 + 130 + 60 + 20 + 60 + 3 = 280 against a 300-minute job, itself under
the 360-minute ceiling ubuntu-latest imposes regardless.

Raising the budget does not make a doomed round cheaper — each exhausted
budget still pushes nothing, which is why TIMEOUT_WINDOW_CAP stops a PR
after three in one window. It buys rounds that were close to finishing.

The test now asserts the SUM against the job cap and the count of bounded
steps, because asserting the numbers individually is exactly what let
153-against-150 pass. Mutations checked: budget over its step cap, either
verification bound removed, job cap back to 150, job cap over the runner
ceiling, and continue-on-error dropped are each caught.
@wenshao
wenshao force-pushed the autofix-agent-budget branch from 1e3cf0a to 07d1e1a Compare July 31, 2026 18:34
@wenshao
wenshao requested a review from Copilot July 31, 2026 18:34
@github-actions

Copy link
Copy Markdown
Contributor

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

中文

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 83.27% 83.27% 89.39% 82.57%
Core 87.52% 87.52% 89.11% 86.18%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.27 |    82.57 |   89.39 |   83.27 |                   
 src               |   84.03 |    81.22 |   88.17 |   84.03 |                   
  cli.ts           |   96.03 |    84.61 |     100 |   96.03 | ...37-538,548-549 
  gemini.tsx       |   72.42 |    77.27 |   80.76 |   72.42 | ...1253-1257,1378 
  ...ractiveCli.ts |   85.65 |    81.55 |   87.17 |   85.65 | ...2390,2396,2448 
  ...liCommands.ts |   88.34 |     83.6 |      90 |   88.34 | ...63,480,514,635 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   69.97 |    72.73 |   89.81 |   69.97 |                   
  acpAgent.ts      |   69.64 |     72.6 |   89.84 |   69.64 | ...62,11367-11369 
  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.59 |    86.66 |    96.5 |   91.59 |                   
  Session.ts       |   91.17 |    85.56 |   96.03 |   91.17 | ...9178,9205-9209 
  ...entTracker.ts |   91.87 |    89.18 |   88.88 |   91.87 | ...33,197,280-289 
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |    93.1 |    90.72 |     100 |    93.1 | 71,82-85,111-121  
  ...y-replayer.ts |   98.53 |    95.52 |     100 |   98.53 | 238-240           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    86.76 |     100 |   89.76 | ...54-270,326-328 
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   95.68 |     93.7 |   96.66 |   95.68 |                   
  ...ageEmitter.ts |   95.34 |    94.11 |     100 |   95.34 | 52-59             
  PlanEmitter.ts   |     100 |    83.33 |     100 |     100 | 59                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   99.17 |    97.43 |     100 |   99.17 | 352-353           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/commands      |   89.15 |    73.75 |   64.51 |   89.15 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.03 |      100 |      50 |   98.03 | 62                
  serve.ts         |    87.1 |    68.22 |     100 |    87.1 | ...46-649,663-667 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   86.99 |    87.02 |   89.67 |   86.99 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |      80 |    84.61 |      80 |      80 | 37-40,49-52,63-66 
  ...entry-path.ts |      75 |       50 |     100 |      75 | 8-9               
  config-utils.ts  |   95.87 |    96.35 |     100 |   95.87 | ...08-213,271-274 
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  daemon-worker.ts |   93.89 |    85.33 |   94.11 |   93.89 | ...1209,1216-1217 
  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       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |   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 |    85.1 |    86.35 |   85.85 |    85.1 |                   
  agent-prompt.ts  |   90.88 |    92.78 |      96 |   90.88 | ...1268,1738-1807 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   48.38 |    14.28 |   66.66 |   48.38 | ...21-226,239-249 
  cleanup.ts       |   90.25 |    83.14 |   83.33 |   90.25 | ...77-482,484-485 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   95.85 |    91.25 |   93.75 |   95.85 | ...1439,1467-1489 
  fetch-pr.ts      |   74.02 |    53.57 |      50 |   74.02 | ...98,332,402-407 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  parse-args.ts    |   99.27 |       96 |     100 |   99.27 | 345,417           
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   84.44 |    79.38 |   91.66 |   84.44 | ...29-910,939-941 
  presubmit.ts     |   83.75 |    92.72 |   88.88 |   83.75 | ...77-578,655-685 
  ...ve-anchors.ts |   77.02 |    88.46 |      75 |   77.02 | ...70-175,187-204 
  run.ts           |   81.14 |    86.17 |    90.9 |   81.14 | ...13,429-477,490 
  script-lint.ts   |   83.67 |    78.41 |   88.88 |   83.67 | ...59-773,775-797 
  submit.ts        |   76.74 |    82.05 |   81.81 |   76.74 | ...03-639,641-642 
  test-efficacy.ts |   87.11 |    83.43 |   93.33 |   87.11 | ...1394,1402-1422 
 ...nds/review/lib |   95.77 |    93.13 |   95.74 |   95.77 |                   
  agent-briefs.ts  |   98.68 |      100 |       0 |   98.68 | 520-521           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  coverage.ts      |   95.47 |    94.25 |   95.45 |   95.47 | ...98,335,433-450 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  effort.ts        |     100 |      100 |     100 |     100 |                   
  gh.ts            |    85.6 |    88.37 |   71.42 |    85.6 | ...20,257-258,285 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |    84.4 |    88.46 |     100 |    84.4 | ...63-473,475-483 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |    85.71 |     100 |     100 | 70                
  prompt-record.ts |   94.73 |    88.23 |     100 |   94.73 | ...28,151-152,156 
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  report.ts        |   94.38 |    93.75 |     100 |   94.38 | 173-177           
  roster.ts        |     100 |    94.23 |     100 |     100 | 143,161,206       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.27 |    93.18 |     100 |   96.27 | ...83,269-270,294 
  workspaces.ts    |   97.76 |     91.2 |     100 |   97.76 | 186-187,212-213   
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.36 |    88.88 |   95.94 |   94.36 |                   
  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        |   89.06 |    88.57 |   85.71 |   89.06 | ...2420,2422-2430 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.04 |    88.28 |     100 |   83.04 | ...39,253,352-353 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |   94.33 |    89.61 |   94.73 |   94.33 | ...35-639,655-656 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |   97.41 |       50 |     100 |   97.41 | 239-242           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.87 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   61.64 |    71.87 |   66.66 |   61.64 | ...54-68,73,77-89 
  ...ings-cache.ts |   98.26 |    97.14 |     100 |   98.26 | 201-202           
  settings.ts      |   90.99 |     92.3 |      90 |   90.99 | ...1006,1008-1009 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...tedFolders.ts |   93.35 |    94.11 |     100 |   93.35 | ...90-391,427-438 
 ...nfig/migration |   95.23 |    77.77 |   83.33 |   95.23 |                   
  index.ts         |   95.65 |     87.5 |     100 |   95.65 | 117-118           
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.91 |      100 |     100 |   94.91 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |      100 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
  v5-to-v4.ts      |      96 |      100 |     100 |      96 | 94-95,99          
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |    71.8 |    70.31 |   66.66 |    71.8 |                   
  ...tputBridge.ts |   71.95 |    70.96 |   68.42 |   71.95 | ...08-409,417-420 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |      80 |    76.31 |   81.35 |      80 |                   
  session.ts       |   84.08 |    75.27 |   93.61 |   84.08 | ...1007,1016-1026 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...24-625,628-629 
 ...active/control |   76.11 |    89.09 |      80 |   76.11 |                   
  ...rolContext.ts |    6.45 |        0 |       0 |    6.45 | 56-95             
  ...Dispatcher.ts |   91.79 |    92.45 |   88.88 |   91.79 | ...49-367,387,390 
  ...rolService.ts |     7.4 |        0 |       0 |     7.4 | 46-185            
 ...ol/controllers |   39.78 |    63.24 |   47.22 |   39.78 |                   
  ...Controller.ts |   39.49 |      100 |      80 |   39.49 | 88-92,127-210     
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   49.11 |    62.96 |   54.54 |   49.11 | ...63-568,570-575 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |   37.92 |    60.71 |   46.66 |   37.92 | ...41-653,662-691 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.07 |    94.07 |   95.23 |   98.07 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1415,1431-1432 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.38 |      100 |   90.47 |   98.38 | 84-85,125-126     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/serve         |   87.31 |    83.55 |   91.09 |   87.31 |                   
  ...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.95 |     100 |     100 | 649               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |   93.89 |    86.61 |     100 |   93.89 | ...66-468,475,477 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   85.85 |    91.78 |   95.83 |   85.85 | ...94-206,366-369 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.27 |     85.2 |     100 |   87.27 | ...10,816-820,838 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.41 |    84.44 |    97.1 |   92.41 | ...1460,1514-1518 
  ...e-grouping.ts |     100 |    94.11 |     100 |     100 | 69,132            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |   92.04 |    77.77 |     100 |   92.04 | ...36-445,470,508 
  daemon-logger.ts |    82.2 |    77.26 |   91.76 |    82.2 | ...1720,1747-1753 
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.37 |    90.06 |     100 |   98.37 | ...1041,1043-1044 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  demo.ts          |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.41 |    88.75 |     100 |   94.41 | ...24,702,718,728 
  fast-path.ts     |   90.49 |     80.7 |   95.45 |   90.49 | ...92-501,567-568 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-143             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...27-128,139-140 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.77 |    88.42 |     100 |   92.77 | ...93-295,307-309 
  ...qwen-serve.ts |   82.69 |    79.33 |   74.06 |   82.69 | ...6744,6749-6750 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.19 |     87.5 |     100 |   94.19 | ...26,530-531,571 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   93.57 |    93.29 |   74.02 |   93.57 | ...2148,2169-2173 
  ...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.3 |    76.57 |     100 |    93.3 | ...13,816,829-831 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   91.07 |    86.66 |     100 |   91.07 | ...79-182,216-219 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   93.89 |     87.5 |     100 |   93.89 | ...18-519,525-526 
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...e-remember.ts |   98.23 |    92.51 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   83.98 |    90.29 |     100 |   83.98 | ...48-156,216-237 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
  ...lls-status.ts |     100 |    92.85 |     100 |     100 | 127               
  ...reconciler.ts |    91.6 |     83.9 |     100 |    91.6 | ...70-272,305-306 
 ...serve/acp-http |   77.04 |    78.33 |   93.26 |   77.04 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |    98.2 |    88.62 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   71.44 |    73.89 |   95.34 |   71.44 | ...4733,4781-4787 
  index.ts         |   81.93 |    79.92 |    90.9 |   81.93 | ...2291,2375-2376 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   85.73 |    73.17 |    97.5 |   85.73 |                   
  ...r-emulator.ts |   88.57 |    63.63 |     100 |   88.57 | ...72-175,194-195 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |       0 |        0 |       0 |       0 |                   
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-119             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
 src/serve/fs      |    86.4 |    80.69 |     100 |    86.4 |                   
  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.8 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.42 |    89.18 |     100 |   90.42 | 161-169           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   86.17 |    79.47 |     100 |   86.17 | ...2506,2516-2517 
 src/serve/routes  |   85.55 |    79.54 |   95.47 |   85.55 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |     100 |      100 |     100 |     100 |                   
  ...nel-notify.ts |   85.22 |       88 |     100 |   85.22 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.45 |    83.33 |     100 |   85.45 | 98-105            
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 146               
  health-demo.ts   |   94.73 |     86.2 |     100 |   94.73 | 62-66,154         
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.12 |    82.73 |   92.59 |   87.12 | ...1263,1306-1307 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.21 |    81.78 |   95.16 |   85.21 | ...4608,4610-4611 
  sse-events.ts    |   84.45 |     87.5 |   77.77 |   84.45 | ...36,453-456,485 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.19 |    77.68 |     100 |   90.19 | ...47-448,467-468 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.09 |       79 |      90 |   83.09 | ...1032,1038,1041 
  ...extensions.ts |   87.23 |    72.76 |   94.11 |   87.23 | ...1826,1871-1872 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   84.44 |    64.51 |     100 |   84.44 | ...73-275,355-357 
  ...t-branches.ts |   75.43 |    66.66 |     100 |   75.43 | ...13-618,627-634 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    93.18 |     100 |     100 | 52,77,188         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...management.ts |   88.22 |    85.29 |     100 |   88.22 | ...1546,1566-1571 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   74.81 |    70.31 |     100 |   74.81 | ...47-658,664-665 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |   69.87 |    78.12 |     100 |   69.87 | ...59-284,290-324 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.42 |    64.78 |      80 |   78.42 | ...31-336,344-345 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   90.69 |    89.18 |   96.55 |   90.69 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |   85.66 |    76.83 |     100 |   85.66 | ...02,719,782-791 
  fs-factory.ts    |     100 |    92.59 |     100 |     100 | 34,42,103,159     
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.11 |    95.19 |     100 |   95.11 | ...65-167,422-427 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |   94.81 |    90.32 |     100 |   94.81 | 175-181           
  ...on-archive.ts |   89.55 |    87.78 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   93.55 |    91.01 |     100 |   93.55 | ...79,681-687,827 
  telemetry.ts     |   99.01 |    97.45 |     100 |   99.01 | ...19,633,775-777 
 src/serve/voice   |   83.35 |    92.22 |   90.47 |   83.35 |                   
  ...ice-config.ts |   84.61 |       30 |     100 |   84.61 | 90-99,103-104     
  voice-ws.ts      |   77.16 |    94.73 |   83.33 |   77.16 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   89.11 |    86.15 |   90.69 |   89.11 |                   
  index.ts         |   88.66 |    85.77 |   89.47 |   88.66 | ...1286-1290,1293 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.23 |    88.48 |   97.82 |   92.23 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 104-117           
  ...killLoader.ts |   97.14 |    87.87 |     100 |   97.14 | 140,151-152       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   79.55 |    88.29 |   83.33 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.36 |    92.68 |     100 |   97.36 | 153,160-161       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.29 |    86.48 |     100 |   88.29 | ...91-196,229-230 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.54 |    90.47 |    87.5 |   93.54 | 201-203,217-223   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.71 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |   90.37 |    87.87 |     100 |   90.37 | ...80,287,352-357 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   90.46 |    82.19 |      96 |   90.46 | ...66-668,671-673 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |    86.29 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.24 |   94.73 |   88.28 | ...1352,1356-1363 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   93.26 |       75 |   83.33 |   93.26 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   72.22 |    75.68 |   64.63 |   72.22 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   73.35 |    72.71 |   67.85 |   73.35 | ...4133,4175-4185 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   68.12 |    64.86 |   33.33 |   68.12 | ...98,321,341-346 
  ...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.41 |    82.94 |    89.4 |   81.41 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...24-125,133-142 
  ...essCommand.ts |   67.95 |    55.88 |      75 |   67.95 | ...86-187,201-204 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   68.28 |    70.14 |   84.61 |   68.28 | ...66-599,610-611 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   65.37 |    81.88 |   94.11 |   65.37 | ...85-535,538-672 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   82.97 |    78.57 |     100 |   82.97 | 47-52,67-70,91-96 
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |   91.13 |    83.72 |      90 |   91.13 | ...81-184,196-199 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   93.45 |    89.06 |     100 |   93.45 | ...68-169,196-206 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   86.27 |    83.01 |     100 |   86.27 | ...22-935,969-974 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |   89.06 |    88.37 |     100 |   89.06 | ...72-176,202-209 
  ...oreCommand.ts |    90.9 |    86.04 |     100 |    90.9 | ...41-146,176-177 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.43 |      100 |      50 |    6.43 | 31-330            
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   91.82 |    78.87 |   66.66 |   91.82 | ...59-160,169-174 
 src/ui/components |   71.13 |    78.52 |   78.67 |   71.13 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  ...ateScreen.tsx |   97.29 |     87.5 |   66.66 |   97.29 | 49                
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   88.65 |    90.41 |     100 |   88.65 | ...84-286,300-302 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-72,84,139,153 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-597             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   75.11 |     61.4 |      50 |   75.11 | ...48-253,271-275 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   83.33 |    76.92 |     100 |   83.33 | 24-30             
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   78.51 |     65.3 |     100 |   78.51 | ...99,502,505-511 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   83.08 |    81.73 |      80 |   83.08 | ...2197,2223,2297 
  ...Shortcuts.tsx |     100 |       88 |     100 |     100 | 98,119            
  ...Indicator.tsx |   98.18 |    97.82 |     100 |   98.18 | 161-162           
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   95.82 |    92.53 |      50 |   95.82 | ...97,440-444,447 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   83.41 |    71.65 |     100 |   83.41 | ...69,971,976-992 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.5 |    85.18 |     100 |    93.5 | ...05,267,287-289 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   92.97 |    83.87 |     100 |   92.97 | ...45,248,275-277 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  ...criptView.tsx |   98.27 |    84.21 |     100 |   98.27 | 45,53             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |    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 |   87.11 |    81.37 |   91.89 |   87.11 |                   
  ...rListBody.tsx |   95.29 |    85.18 |     100 |   95.29 | 95-98             
  ...etailStep.tsx |   75.32 |    71.42 |      60 |   75.32 | ...56-169,173-186 
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entHeader.tsx |     100 |    85.71 |     100 |     100 | 47                
  ...rListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   72.29 |    70.49 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.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.82 |    86.17 |   85.29 |   89.82 |                   
  ...ionDialog.tsx |   89.23 |    84.27 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.44 |    97.77 |   78.57 |   94.44 | ...53-355,358-361 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   76.52 |     42.1 |   66.66 |   76.52 | ...00,102,125,156 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   89.75 |     79.1 |     100 |   89.75 | ...33-635,642-644 
  ...upMessage.tsx |   98.32 |    95.16 |     100 |   98.32 | 184-187,414       
  ToolMessage.tsx  |   92.49 |       85 |   93.33 |   92.49 | ...61-966,993-995 
 ...ponents/shared |   85.79 |    82.11 |   94.11 |   85.79 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.86 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |   72.72 |      100 |     100 |   72.72 | 31-33             
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   88.51 |    85.11 |   81.81 |   88.51 | ...51-779,792,887 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |   69.81 |    72.64 |   61.11 |   69.81 |                   
  ContextUsage.tsx |   70.88 |    63.88 |      80 |   70.88 | ...20-426,463-557 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.14 |    81.87 |    86.3 |   84.14 |                   
  ...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.98 |    85.26 |     100 |   85.98 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 155-156           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 234-235           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |    85.1 |    82.56 |   89.57 |    85.1 |                   
  ...dProcessor.ts |   83.95 |    83.95 |     100 |   83.95 | ...39-871,918-919 
  ...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.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.73 |    76.59 |     100 |   94.73 | 162-166,255,261   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   94.85 |    80.76 |     100 |   94.85 | ...54,229,292-295 
  ...ompletion.tsx |   97.09 |    87.09 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   85.66 |    81.38 |   96.15 |   85.66 | ...3943,4111-4119 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.01 |    98.36 |     100 |   98.01 | 139-142           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   63.15 |       80 |      50 |   63.15 | 42-52,64-67       
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.5 |     100 |     100 | 99                
  ...delCommand.ts |     100 |       95 |     100 |     100 | 53                
  ...ouseEvents.ts |   94.56 |    94.87 |   83.33 |   94.56 | 77-81             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |    87.4 |    78.78 |     100 |    87.4 | ...71,321-333,381 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   88.95 |    86.95 |     100 |   88.95 | ...37-439,471-481 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   94.67 |    74.28 |     100 |   94.67 | ...19,174,233-238 
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.13 |    93.33 |     100 |   97.13 | ...78-382,478-485 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |    91.2 |    89.47 |     100 |    91.2 |                   
  ...AppLayout.tsx |    90.9 |     87.5 |     100 |    90.9 | 60-62,110-115,151 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   86.47 |    79.88 |   96.66 |   86.47 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   92.72 |       90 |     100 |   92.72 | 37-38,67-68       
  ...tion-state.ts |   85.71 |      100 |   88.88 |   85.71 | 51-58             
  ...ction-text.ts |   92.85 |    92.45 |     100 |   92.85 | 30-34,114-115     
  ...selection.tsx |   80.31 |    59.64 |     100 |   80.31 | ...13-314,330-331 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   86.58 |    84.96 |   95.29 |   86.58 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   79.84 |     75.6 |     100 |   79.84 | ...66,270,328-329 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   92.38 |    81.91 |   95.23 |   92.38 | ...43-746,799-804 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   52.52 |    73.25 |   91.66 |   52.52 | ...23,626-635,638 
  commandUtils.ts  |   96.17 |    88.88 |     100 |   96.17 | ...77,179-180,323 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.21 |     100 |   94.87 | 116-119           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |      96 |    97.05 |     100 |      96 | 102-105           
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   90.43 |    78.33 |     100 |   90.43 | ...59,244,248-249 
  ...red-height.ts |   98.38 |     97.1 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   79.32 |    77.37 |     100 |   79.32 | ...32-554,685-686 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   95.97 |    94.06 |   94.44 |   95.97 | ...29-330,490-491 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   90.42 |    92.85 |     100 |   90.42 | ...06-207,240-241 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |    59.89 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    65.81 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   80.94 |    72.69 |   80.55 |   80.94 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   89.72 |    65.33 |   93.75 |   89.72 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |    68.42 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.33 |    86.94 |   92.54 |   81.33 |                   
  ...p-profiler.ts |   98.39 |    90.56 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |       95 |     100 |     100 | 72                
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.38 |    71.83 |   88.88 |   70.38 | ...27,430-431,438 
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...59,376-377,422 
  jsonc-editor.ts  |   93.18 |    92.72 |     100 |   93.18 | ...80-381,384-385 
  languageUtils.ts |   98.88 |    97.05 |     100 |   98.88 | 184-185           
  load-undici.ts   |     100 |      100 |     100 |     100 |                   
  ...npm-update.ts |   89.05 |    76.38 |     100 |   89.05 | ...86,302-303,340 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.79 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   74.38 |    69.56 |     100 |   74.38 | ...92-103,105-116 
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.67 |    56.93 |   76.92 |   45.67 | ...1034,1046-1069 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |     87.5 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   95.45 |    93.33 |     100 |   95.45 | 54-55             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   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.52 |    86.18 |   89.11 |   87.52 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.28 |    84.25 |   95.23 |   90.28 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.53 |    77.44 |   83.33 |   85.53 | ...1781-1785,1788 
  ...ound-tasks.ts |   96.15 |    90.13 |   98.76 |   96.15 | ...1732,1752-1755 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |    95.9 |    90.42 |     100 |    95.9 | ...28-429,502-506 
  ...w-snapshot.ts |   91.86 |       75 |     100 |   91.86 | ...54,178,185-187 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   90.42 |    85.66 |   87.64 |   90.42 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.05 |    76.67 |   77.77 |   85.05 | ...2287,2333-2335 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |   91.79 |    87.79 |   82.35 |   91.79 | ...1775,1824-1827 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   91.76 |    81.03 |   91.66 |   91.76 | ...51,195,215-218 
  ...ow-sandbox.ts |   96.87 |    94.64 |     100 |   96.87 | ...24-325,330-331 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   81.81 |    83.99 |    87.5 |   81.81 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   94.76 |    86.36 |   92.85 |   94.76 | 86-87,348-354     
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   88.85 |    82.56 |   96.29 |   88.85 | ...-990,1034-1035 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.91 |       87 |   75.16 |   84.91 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |    84.2 |    86.71 |   73.52 |    84.2 | ...8178,8182-8183 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   91.95 |    88.22 |   93.21 |   91.95 |                   
  baseLlmClient.ts |   88.28 |    82.48 |   81.81 |   88.28 | ...47,660,666-668 
  client.ts        |   91.92 |    87.39 |   91.56 |   91.92 | ...3915,4011-4012 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...81-482,527-533 
  ...lScheduler.ts |    90.1 |    85.83 |      96 |    90.1 | ...5644,5672-5683 
  geminiChat.ts    |   92.57 |    89.36 |      96 |   92.57 | ...4508,4556-4557 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 47-48             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   95.19 |    89.47 |     100 |   95.19 | ...44-245,290-291 
  prompts.ts       |   93.57 |    91.42 |   83.33 |   93.57 | ...1187,1390-1391 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |   96.89 |    80.88 |   88.23 |   96.89 | ...10,117-118,123 
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |     100 |      100 |     100 |     100 |                   
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.52 |    91.66 |     100 |   98.52 | ...14,642-643,690 
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |    96.2 |    87.41 |      96 |    96.2 |                   
  ...tGenerator.ts |   97.23 |    86.48 |   94.73 |   97.23 | ...1423,1452,1463 
  converter.ts     |   95.92 |    88.16 |     100 |   95.92 | ...1305,1484-1486 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |    95.6 |    88.74 |    92.3 |    95.6 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.52 |    87.88 |   91.89 |   95.52 | ...1195-1196,1224 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.65 |    90.23 |   95.23 |   91.65 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   96.63 |    90.94 |     100 |   96.63 | ...1100,1108,1203 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.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.2 |    83.25 |   92.33 |    86.2 |                   
  ...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.38 |   97.82 |   90.82 | ...1215-1221,1265 
  ...ionManager.ts |   81.06 |    78.78 |   81.52 |   81.06 | ...2705,2727-2728 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    84.61 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   88.58 |    82.13 |     100 |   88.58 | ...62,952-953,963 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       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      |   79.86 |    80.36 |    90.9 |   79.86 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   71.45 |    66.01 |   71.42 |   71.45 | ...49-650,657-658 
  ...onToolGate.ts |     100 |    96.55 |     100 |     100 | 97                
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   94.17 |    88.82 |   95.93 |   94.17 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  goal-evidence.ts |   87.59 |     85.1 |   95.65 |   87.59 | ...12-613,636-639 
  ...projection.ts |   89.41 |    72.22 |   66.66 |   89.41 | ...28,131,135-137 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |    91.3 |       90 |     100 |    91.3 | 107-108           
  goal-reducer.ts  |   92.21 |    85.48 |     100 |   92.21 | ...67-368,381,436 
  goal-runtime.ts  |   99.01 |    93.44 |     100 |   99.01 | ...83-684,707-708 
  goal-tools.ts    |   98.32 |    93.18 |   95.23 |   98.32 | ...48-149,256-257 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...67-170,183-185 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-27              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.11 |    86.38 |   88.62 |   88.11 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.12 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.42 |    83.29 |   90.44 |   87.42 |                   
  ...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 | 136,146           
  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.59 |    76.19 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.95 |    82.52 |   86.36 |   86.95 | ...68,388,395-401 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |   95.29 |    96.59 |     100 |   95.29 | ...80-381,402-403 
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   89.85 |    82.92 |     100 |   89.85 | ...54-155,162-163 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    89.79 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   71.68 |    65.51 |   68.75 |   71.68 | ...90-394,397,403 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |     82.6 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.54 |       89 |   91.13 |   92.54 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    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.13 |     100 |     100 | 177,260           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.76 |    91.27 |   71.07 |   83.76 |                   
  autoMode.ts      |   97.65 |    93.13 |     100 |   97.65 | ...79-586,632,709 
  ...transcript.ts |      98 |    84.61 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.54 |    89.63 |      80 |   86.54 | ...1096,1202-1206 
  rule-parser.ts   |   94.49 |    92.72 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.07 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.54 |    84.26 |   96.93 |   89.54 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.68 |    85.71 |     100 |   97.68 | ...96,119,490-491 
  ...ionService.ts |   96.71 |    95.79 |     100 |   96.71 | ...83,699,832-840 
  ...ingService.ts |   90.91 |    84.17 |   95.45 |   90.91 | ...2058,2085-2086 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.05 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   91.78 |    81.81 |   94.11 |   91.78 | ...37,463-470,517 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.22 |    97.34 |     100 |   98.22 | ...75-676,723-724 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |     90.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.51 |    89.14 |      98 |   94.51 | ...1102-1103,1167 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   82.81 |    74.08 |    97.5 |   82.81 | ...2364,2376-2379 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.94 |    83.69 |   97.14 |   88.94 | ...2450,2520-2540 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |   84.35 |    78.37 |   97.14 |   84.35 | ...2472,2478-2483 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.95 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |   99.41 |    96.55 |     100 |   99.41 |                   
  microcompact.ts  |   99.41 |    96.55 |     100 |   99.41 | 244-245,677       
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   88.52 |     87.7 |   90.47 |   88.52 |                   
  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 |   84.07 |    83.67 |   83.33 |   84.07 | ...1233,1240-1244 
  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.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.07 |    83.99 |   84.47 |   81.07 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.07 |    80.95 |     100 |   99.07 | 183,197           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |     100 |    90.47 |     100 |     100 | 49,76             
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.09 |    95.61 |      95 |   99.09 | 141,365-366       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   56.85 |    74.35 |   64.81 |   56.85 | ...1397,1414-1434 
  metrics.ts       |   79.63 |    81.98 |   79.66 |   79.63 | ...1082,1085-1096 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,478-479,495 
  sdk.ts           |   79.22 |    89.18 |   63.63 |   79.22 | ...57-161,199-221 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   90.83 |    90.05 |   96.77 |   90.83 | ...1667,1698-1701 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   82.35 |    94.61 |   86.04 |   82.35 | ...1361,1365-1372 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.17 |     80.7 |      70 |   74.17 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.17 |    80.53 |   69.49 |   74.17 | ...1120,1158-1159 
 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.94 |    84.71 |   88.32 |   85.94 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   81.49 |     80.1 |   85.71 |   81.49 | ...3217,3219-3220 
  mcp-client.ts    |   79.87 |    85.58 |   89.47 |   79.87 | ...2259,2263-2266 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   77.56 |    84.11 |   77.14 |   77.56 | ...1291,1299-1300 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 175-176           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |    97.2 |    93.47 |     100 |    97.2 | ...00-801,856-857 
  ...sport-pool.ts |   83.49 |    80.15 |   84.61 |   83.49 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.74 |    84.28 |   88.46 |   91.74 | ...93,606,804-809 
  notebook-edit.ts |   85.55 |    77.39 |   81.25 |   85.55 | ...86-902,948-949 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   82.57 |    90.24 |     100 |   82.57 | 174-185,234-247   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   93.57 |     92.3 |      90 |   93.57 | 122-130           
  shell.ts         |   78.78 |    84.06 |   91.91 |   78.78 | ...5019,5082-5083 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.06 |    93.33 |   89.47 |   91.06 | ...71,475,520-542 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   94.36 |    84.61 |   92.85 |   94.36 | ...10-415,437-438 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   92.74 |    91.52 |    91.3 |   92.74 | ...63-564,580-586 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.53 |    83.57 |      80 |   90.53 | ...1007,1065-1068 
  write-file.ts    |    86.7 |    84.92 |   88.88 |    86.7 | ...24-827,864-899 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   86.03 |    86.11 |   87.85 |   86.03 |                   
  agent.ts         |   85.28 |     85.8 |   86.31 |   85.28 | ...4246,4268-4278 
  fork-subagent.ts |   99.36 |    90.69 |     100 |   99.36 | 91                
 ...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 |   83.95 |    83.05 |   73.33 |   83.95 |                   
  workflow.ts      |   83.95 |    83.05 |   73.33 |   83.95 | ...11,456,458-459 
 src/utils         |   92.82 |    89.73 |   96.83 |   92.82 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ncyLimiter.ts |   94.64 |    95.23 |     100 |   94.64 | 64-66             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.81 |    93.95 |      95 |   95.81 | ...91-492,504-517 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   82.62 |    94.32 |    61.9 |   82.62 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  fileUtils.ts     |   94.96 |    93.47 |   96.15 |   94.96 | ...1865,1890-1891 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |    93.25 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.95 |    92.79 |     100 |   93.95 | ...78-479,481-483 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   97.29 |    86.93 |     100 |   97.29 | ...59-660,735-736 
  readManyFiles.ts |   96.29 |    87.23 |     100 |   96.29 | 225,276,286-290   
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.02 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   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 |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |    83.96 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.07 |    88.34 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.16 |    91.91 |     100 |   98.16 | ...1244-1246,1256 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       64 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |   85.85 |    83.63 |     100 |   85.85 | ...90-394,424-439 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.81 |    89.39 |     100 |   95.81 | ...74-275,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.68 |    80.38 |   94.69 |   83.68 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   82.47 |    76.22 |      95 |   82.47 | ...1525,1559-1560 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

@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. Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查——无阻断问题。 建议见行内评论。 未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

# buys rounds that were close to finishing, not rounds that were
# never going to. QWEN_AUTOFIX_TIMEOUT_MS overrides it without a
# code change; a malformed value falls back to the runner default.
QWEN_TIMEOUT_MS: '${{ vars.QWEN_AUTOFIX_TIMEOUT_MS || 7200000 }}'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The vars.QWEN_AUTOFIX_TIMEOUT_MS override has no upper clamp, so the budget↔cap invariant this PR adds a test to protect only holds for the hardcoded fallback 7200000. — Failure scenario: a maintainer sets the repo variable to a round "give it more time" value such as 9000000 (150 min); a non-empty string is truthy in GitHub expressions, so the expression evaluates to 9000000, not the fallback. run-agent.mjs:21 then arms its internal timer at 150 min, but the step's timeout-minutes: 130 kills the process first — timedOut stays false, the agent-timeout marker (run-agent.mjs:329-330) is never written, and the report step misclassifies the round as a crash, which is exactly the misreport the new comment warns about. The headroom is only 10 minutes, so any override ≥ 7,800,000 ms breaks the invariant, and the new test (which only sees the literal fallback) cannot catch it.

Recommended fix — state the ceiling next to the override (and optionally clamp in run-agent.mjs with Math.min(parsed, cap) so the marker is still written):

# The override MUST stay below 7,800,000 ms (the 130-minute step cap above);
# at or above it the step cap wins the race, agent-timeout is never written,
# and the round is reported as a crash.
QWEN_TIMEOUT_MS: '${{ vars.QWEN_AUTOFIX_TIMEOUT_MS || 7200000 }}'
中文说明

[Suggestion] vars.QWEN_AUTOFIX_TIMEOUT_MS 覆盖值没有上限钳制,因此本 PR 新增测试所保护的「预算↔上限」不变量只对硬编码回退值 7200000 成立。—— 失败场景:维护者把仓库变量设成一个取整的「多给点时间」的值,例如 9000000(150 分钟);非空字符串在 GitHub 表达式中为真,因此表达式求值为 9000000 而非回退值。run-agent.mjs:21 随即把内部计时器定为 150 分钟,但 step 的 timeout-minutes: 130 会先杀掉进程——timedOut 保持为 false,agent-timeout 标记(run-agent.mjs:329-330)永远不会写出,上报步骤便把该轮误判为崩溃,而这正是新增注释所警告的误报。余量只有 10 分钟,因此任何 ≥ 7,800,000 ms 的覆盖值都会破坏该不变量,而新测试(只能看到字面回退值)无法捕获它。

建议修复——在覆盖值旁注明上限(并可选地在 run-agent.mjs 中用 Math.min(parsed, cap) 钳制,使标记仍会写出):见上方代码块。

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

@wenshao

wenshao commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Review

The diagnosis holds up. I re-derived the arithmetic against the branch and re-ran the suite: 130 + 60 + 20 + 60 = 270, +10 = 280 ≤ 300 ≤ 360; scripts/tests/qwen-autofix-workflow.test.js 107/107 green; yamllint clean; YAML parses. The three load-bearing claims check out at the source:

  • .qwen/skills/autofix/scripts/run-agent.mjs:21 is Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000, so the stated fallback table for "" / "abc" / "0" is exactly right, and vars.QWEN_AUTOFIX_TIMEOUT_MS unset renders empty → 7200000.
  • The graceful-degrade claim is real: a killed gate leaves steps.verify.outputs.outcome empty, Finalize verification falls through case to exit 1 (qwen-autofix.yml:3659-3662), Push and report is gated on fixed|noop (:3691) so nothing is pushed, and the always() reporters still run.
  • I reproduced all five claimed mutations — job cap back to 150, cap above 360, gate bound removed, budget above its step cap, continue-on-error dropped — each reds the suite. The mutation table is accurate.

Five things I'd change or want stated, roughly in order of how much they matter.

1. The new invariant cannot catch the bug class it was written for

stepCaps collects \n {8}timeout-minutes: (\d+) — i.e. only the steps that already have a bound. A new long-running step added to review-address without a bound leaves the sum unchanged and the suite green. That is precisely how Verification gate came to be unbounded in the first place.

I verified it rather than reasoning about it. Inserting

      - name: 'Extra unbounded work'
        if: |-
          ${{ always() }}
        run: |-
          echo hi

before Finalize verification still gives 107/107 passed.

expect(stepCaps).toHaveLength(4) has the polarity inverted relative to the risk: it fires when someone adds a bound (a false alarm that just needs the literal bumped) and stays silent when someone omits one. Worth asserting the complement instead — every step in review-address that runs the agent or run-autofix-review-verification.sh must carry a timeout-minutes, with an explicit allowlist for the cheap ones. That is the assertion that would have caught the original 153-against-150.

2. The override escapes the invariant, and the comment advertises it without a ceiling

QWEN_AUTOFIX_TIMEOUT_MS overrides it without a code change is true, but the override is unconstrained while the step cap is not. Set the repo variable to 8400000 (140m) and the 130m step cap fires first, run-agent.mjs never reaches its own timer, and agent-timeout is never written. Two things follow, both of which this workflow cares about:

  • the report step falls into the -z "${DETAIL_FILE}" arm and says "crashed before it could evaluate the feedback — a human should take over this PR" instead of "ran out of time … split the PR or raise the agent time budget" (:4285-4288);
  • TIMEOUT_N at :4485-4488 counts AGENT_TIMEOUT plus prior headlines matching AutoFix ran out of time before finishing, so the round is not counted and TIMEOUT_WINDOW_CAP undercounts.

The test only pins the margin for the literal default — /QWEN_TIMEOUT_MS: '\$\{\{[^}]*\|\|\s*(\d+)\s*\}\}'/ reads 7200000, never the override. Since the whole point of the change is that a budget nobody can see is a budget nobody re-checks, the ceiling deserves the same treatment: say ≤ 120m in the comment, or clamp it in run-agent.mjs (Math.min(env, STEP_CAP - margin)) so an ops-side value can't silently misreport a round.

3. Three comments now describe the old numbers as current

(qwen-autofix.yml:3283 and the test's :3661 refer to #7929 historically — those read fine as-is.)

4. SETUP_AND_REPORT_MIN = 10 is thin for what it models

That constant stands in for every unbounded step in the job: 12 setup steps including Install dependencies and build and the ~580-line Prepare branch and feedback, plus Finalize verification, Show/Upload run artifacts, and both reporters. Measured 5–7m, but none of them is bounded, so the constant is a modelling assumption rather than a bound.

Today the real slack is 30 (300 - 270), but the assertion only demands 10 — so it would green-light raising caps to a sum of 290 and leave that 12-step setup ten minutes against a measured 7m10s. A ~40% infra slowdown then blows the job cap and takes the always() reporters with it, which is the failure this PR exists to close. 25 still passes today (270 + 25 = 295 ≤ 300) and makes the reserve a real property.

5. Two smaller notes

  • Runner cost isn't mentioned. max-parallel: 5 × 300m is up to 25 runner-hours held per scan in the worst case, from 12.5, and a hung leg now holds its per-PR head-write concurrency group for 5h instead of 2.5h. In practice the 120m budget ends rounds, not the 300m cap, so this is probably fine — but the max-parallel comment two lines above the changed job cap reasons explicitly about queueing tails ("the 7th PR waited 81 minutes for a slot"), and that reasoning isn't revisited.
  • The margin assertions are asymmetric without explanation. Primary gets >= 5, repair gets > 0 (cap 20 vs QWEN_TIMEOUT_MS: '1080000' = 18m). The kill path is the same for both — SIGTERM, 10s grace, SIGKILL (run-agent.mjs:225-231) — so 2 minutes is ample and 10 is generous; but if 5 is the number that matters, it should apply to both, and if it doesn't, the comment claiming the margin exists "for the internal kill path" over-explains a 10s operation by two orders of magnitude.

Out of scope, same shape

issue-autofix (:653, timeout-minutes: 180) has no step bounds at all, and its Develop fix step doesn't state QWEN_TIMEOUT_MS either — the exact configuration being fixed here. Worst case there is currently ~85m against 180 so it isn't at risk today, but it is where this drifts next.


Nothing above blocks the change: the sizing is defensible, the refusal to build a width-scaled heuristic on five data points is the right call, and bounding the two gates is a strict improvement over the status quo. #1 and #2 are the ones I'd want addressed before this lands, since both let the same failure recur silently.

中文版

诊断成立。我在分支上重新推导了算术并跑了测试:130 + 60 + 20 + 60 = 270+10 = 280 ≤ 300 ≤ 360scripts/tests/qwen-autofix-workflow.test.js 107/107 通过;yamllint 干净。三个关键论断在源码层面都核对无误:run-agent.mjs:21 的回退表完全正确;优雅降级路径为真(超时的 gate 让 outcome 为空 → Finalize verification 落到 *) exit 1Push and reportfixed|noop 门控而不推送 → always() 上报照常);五条变异我逐条复现,均能让测试变红。

1. 新的不变量抓不住它自己要防的那类 bug。 stepCaps 只收集已经有约束的步骤。往 review-address 里加一个没有约束的长步骤,和不变,测试仍绿 —— 这正是 Verification gate 当初变成无约束的方式。我实测验证过(插入一个无约束步骤后仍是 107/107)。toHaveLength(4) 的极性也反了:有人约束时报警,有人约束时沉默。建议改为断言其补集:review-address 中所有跑 agent 或 run-autofix-review-verification.sh 的步骤必须带 timeout-minutes

2. 覆盖开关逃出了不变量,而注释在没有上限说明的情况下推荐它。 把仓库变量设为 8400000(140 分钟),130 分钟的 step 上限会先触发,agent-timeout 永不写出,于是:上报走 -z "${DETAIL_FILE}" 分支,说成"崩溃"而非"超时"(:4285);TIMEOUT_N:4485)不计这一轮,TIMEOUT_WINDOW_CAP 少算。测试只钉住了字面默认值。建议在注释里写明 ≤ 120m 上限,或在 run-agent.mjs 里 clamp。

3. 三处注释仍在描述旧数字。 qwen-autofix.yml:3754("agent 的 ~50 分钟窗口")—— 这条不只是数字过期:本次把该竞争窗口拉宽了 2.4 倍,而下面的补救推送只重试 3 次;另外测试文件 :5832:6567

4. SETUP_AND_REPORT_MIN = 10 对它所代表的东西偏薄。 它代表 job 中全部无约束步骤(12 个 setup 步骤 + 4 个上报步骤)。当前真实余量是 30,但断言只要求 10 —— 也就是说它会放行"和 = 290",届时 12 步 setup 只剩 10 分钟对上实测的 7 分 10 秒。改成 25 今天仍能通过(270 + 25 = 295),且让这份预留成为真正的性质。

5. 两点小注。 runner 成本未提及:max-parallel: 5 × 300 分钟最坏情况下每次扫描占用 25 runner-小时(原为 12.5),且卡住的一条腿会把 per-PR 并发组占满 5 小时 —— 而被改的 job 上限正上方那段 max-parallel 注释恰恰是在推理排队尾部。另外余量断言不对称(主 >= 5,repair > 0),而两者的 kill 路径相同(SIGTERM → 10 秒 → SIGKILL)。

范围之外,同一形状: issue-autofix:653,180 分钟)完全没有 step 约束,其 Develop fix 也未声明 QWEN_TIMEOUT_MS —— 正是本次要修的配置。目前最坏约 85 分钟对 180,尚不危险,但这是下一次漂移的地方。

以上都不构成阻塞:尺寸选择站得住,拒绝在五个数据点上造宽度启发式是对的,给两个 gate 加约束严格优于现状。#1#2 是我希望合入前处理的两条,因为它们都会让同一种失败再次静默发生。

@wenshao

wenshao commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

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

Copy link
Copy Markdown
Collaborator

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

中文说明

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

@qwen-code-dev-bot

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

Copy link
Copy Markdown
Collaborator

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

中文说明

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round — PR #8257

Addressed the automated reviewer's inline suggestion and all five points from @wenshao's review (the two the reviewer flagged as must-fix before landing, plus the three smaller notes). One out-of-scope item is deliberately deferred. No conflict (--conflict false), so no merge was performed.

Inline finding

  • [rc:3692926235] — vars.QWEN_AUTOFIX_TIMEOUT_MS override has no upper clamp ([Suggestion], automated reviewer). Resolved. This is the same defect as @wenshao's point Where is the config saved? #2. Added an explicit CEILING note next to the override stating it MUST stay below 7,800,000 ms (the 130-minute step backstop), with the failure mode spelled out: a non-empty repo variable wins over the fallback, so a value such as 9,000,000 arms run-agent.mjs's timer past the step cap, the cap kills the process first, agent-timeout is never written, and the round is misreported as a crash. I chose the comment over a run-agent.mjs clamp because that script is shared across jobs with different step caps (issue-autofix is 180m, review-address is 130m); a single hardcoded clamp cannot be correct for every caller, and threading a per-caller cap through it would be speculative configurability. The comment sits at the exact override site both reviewers pointed to.

@wenshao's review (issue-level)

  1. The invariant cannot catch the bug class it was written for — implemented (must-fix). Replaced the "sum only the steps that already have a bound" logic with a structural assertion: the test now splits review-address into step blocks and identifies the long steps by what they execute (node …run-agent.mjs or bash …run-autofix-review-verification.sh), asserts there are exactly four, and asserts each carries a timeout-minutes. Cheap setup/report steps are allowlisted implicitly by not matching the execution patterns. This fixes the inverted polarity of the old toHaveLength(4): it now fires when a long step is missing a bound, not when one is added. Verified by mutation — see below.
  2. The override escapes the invariant without a ceiling — implemented (must-fix). Same fix as the inline finding above (explicit CEILING comment stating ≤ 120m).
  3. Three comments describe the old numbers as current — implemented. Updated the salvage comment in the workflow (~50-minute~120-minute window, noting the widening and the 3-merge retry bound) and the two stale test comments (~50-minute~120-minute; 80-minute agent step130-minute agent step).
  4. SETUP_AND_REPORT_MIN = 10 is thin — implemented. Raised to 25, which still fits today (270 + 25 = 295 ≤ 300) and makes the reserve a real property rather than the measured floor, per the reviewer's suggestion.
  5. Two smaller notes — implemented.
    • Runner cost / max-parallel reasoning: added a sentence to the max-parallel comment acknowledging the 300-minute cap raises the worst-case hold to 5 runner-hours per slot (25 across the fleet) and holds the per-PR head-write concurrency group for the same window, and that in practice the 120-minute budget ends rounds first so the queueing tail is unchanged.
    • Asymmetric margin floors: unified primary and repair to a single >= 1-minute floor and corrected the comment to state what the margin actually covers (SIGTERM, 10s grace, SIGKILL, marker write) instead of over-explaining a 10-second operation. The redundant > 0 assertion was removed (subsumed by >= 1). Primary margin is 10m and repair is 2m, so both clear the unified floor.

Out of scope (deferred)

  • issue-autofix has no step bounds and no QWEN_TIMEOUT_MS. The reviewer explicitly labelled this "Out of scope, same shape" and noted it is not at risk today (~85m worst case against 180). Left untouched to keep this change minimal; it is the natural follow-up if/when that job grows.

Mutation evidence for point #1

The reviewer demonstrated that inserting an unbounded step left the old suite green (107/107). Against the new assertion:

  • A — new unbounded step that runs the agent: suite fails (long-step count becomes 5 and its bound is non-finite). This is exactly the case the old test missed.
  • B — Verification gate loses its timeout-minutes: suite fails (non-finite bound).
  • C — new cheap unbounded echo hi step: suite passes (correctly allowlisted, long-step count stays 4).

Verification

  • npm run typecheck — passed
  • npm run lint — passed
  • npm run build — passed
  • npx eslint scripts/tests/qwen-autofix-workflow.test.js — passed
  • npx vitest run scripts/tests/qwen-autofix-workflow.test.js — 107/107 passed
  • node js-yaml parse of .github/workflows/qwen-autofix.yml — parses OK (yamllint is a Python tool not installed on this runner; the full suite loads and asserts against the workflow, and the YAML parse confirms validity)
  • Mutation polarity checks A/B/C (above) — behaved as expected
  • Integration tests after npm run bundle — not applicable: the touched behavior is workflow YAML plus its workflow test, which the focused Vitest harness exercises directly by parsing the real YAML; it is not reached through the bundled CLI.
中文说明

Autofix 审查轮次 — PR #8257

本轮处理了自动审查器的行内建议,以及 @wenshao 审查中的全部五点(其中两点是审查者标注的合入前必修项,另外三点为较小的注记)。有一项范围外条目被有意推迟。无冲突(--conflict false),因此未执行合并。

行内发现

  • [rc:3692926235] — vars.QWEN_AUTOFIX_TIMEOUT_MS 覆盖值没有上限钳制[Suggestion],自动审查器)。已解决。 这与 @wenshao 的第 2 点是同一缺陷。已在覆盖值旁新增一条明确的 CEILING(上限)注释,声明它必须低于 7,800,000 ms(即 130 分钟的 step 兜底上限),并写明失败路径:非空的仓库变量会压过回退值,因此像 9,000,000 这样的值会把 run-agent.mjs 的计时器定到超过 step 上限,step 上限会先杀掉进程,agent-timeout 永不写出,该轮便被误报为崩溃。之所以选择注释而非在 run-agent.mjs 里 clamp,是因为该脚本被多个 step 上限不同的 job 共用(issue-autofix 为 180 分钟,review-address 为 130 分钟);单一硬编码 clamp 无法对所有调用者都正确,而把按调用者区分的上限传进去则属于投机性的可配置化。注释正好放在两位审查者都指向的覆盖值所在位置。

@wenshao 的审查(issue 级)

  1. 该不变量抓不住它自己要防的那类 bug —— 已实现(必修)。 把「只对已经有约束的步骤求和」的逻辑替换为一个结构性断言:测试现在把 review-address 切成若干 step 块,按它们实际执行的内容(node …run-agent.mjsbash …run-autofix-review-verification.sh)识别出长步骤,断言恰好有四个,并断言每一个都带有 timeout-minutes。廉价的 setup/report 步骤因不匹配执行模式而被隐式列入白名单。这修正了旧 toHaveLength(4) 反掉的极性:现在它会在某个长步骤缺少约束时报错,而不是在有人新增约束时报错。已通过变异验证——见下文。
  2. 覆盖开关在没有上限说明的情况下逃出了不变量 —— 已实现(必修)。 与上面行内发现同一修复(明确的 CEILING 注释,声明 ≤ 120m)。
  3. 三处注释仍把旧数字描述成现状 —— 已实现。 更新了 workflow 中的补救推送注释(~50-minute~120-minute 窗口,并注明窗口被拉宽以及 3 次合并重试上限),以及两处过期的测试注释(~50-minute~120-minute80-minute agent step130-minute agent step)。
  4. SETUP_AND_REPORT_MIN = 10 偏薄 —— 已实现。 按审查者建议提高到 25,今天仍能通过(270 + 25 = 295 ≤ 300),使这份预留成为真正的性质,而非实测下限。
  5. 两点较小的注记 —— 已实现。
    • runner 成本 / max-parallel 推理:max-parallel 注释中补了一句,说明 300 分钟 job 上限把最坏占用提高到每个 slot 5 runner-小时(整个 fleet 25 小时),并在同样窗口内占用 per-PR head-write 并发组;而实际上 120 分钟的预算会先结束各轮,因此上述排队尾部不变。
    • 余量下限不对称: 把 primary 与 repair 统一为单一的 >= 1 分钟下限,并修正注释,说明该余量实际覆盖的是什么(SIGTERM、10 秒宽限、SIGKILL、标记写出),而不是对一个 10 秒操作过度解释。冗余的 > 0 断言已删除(被 >= 1 包含)。primary 余量为 10 分钟、repair 为 2 分钟,两者都越过统一下限。

范围外(推迟)

  • issue-autofix 完全没有 step 约束,也没有 QWEN_TIMEOUT_MS 审查者明确将其标为「范围外,同一形状」,并指出它目前没有风险(最坏约 85 分钟对 180)。为保持本次改动最小化而未改动它;如果该 job 日后变大,它是天然的后续项。

第 1 点的变异证据

审查者曾演示:插入一个无约束步骤会让旧测试套件仍全绿(107/107)。在新断言下:

  • A —— 新增一个运行 agent 的无约束步骤: 套件失败(长步骤数变为 5,且其约束为非有限值)。这正是旧测试漏掉的情形。
  • B —— Verification gate 失去其 timeout-minutes 套件失败(约束为非有限值)。
  • C —— 新增一个廉价的无约束 echo hi 步骤: 套件通过(正确地被列入白名单,长步骤数保持为 4)。

验证

  • npm run typecheck —— 通过
  • npm run lint —— 通过
  • npm run build —— 通过
  • npx eslint scripts/tests/qwen-autofix-workflow.test.js —— 通过
  • npx vitest run scripts/tests/qwen-autofix-workflow.test.js —— 107/107 通过
  • node js-yaml 解析 .github/workflows/qwen-autofix.yml —— 解析正常(yamllint 是 Python 工具,本 runner 未安装;完整测试套件会加载并对该 workflow 做断言,YAML 解析亦确认其有效)
  • 变异极性检查 A/B/C(见上)—— 行为符合预期
  • npm run bundle 之后的集成测试 —— 不适用:本次触及的行为是 workflow YAML 及其 workflow 测试,聚焦的 Vitest 测试通过解析真实 YAML 直接验证该行为,并不经由打包后的 CLI 触达。

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

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


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

@wenshao

wenshao commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Review

Reviewed at ff6276b. I ran the suite in a clean worktree and walked the runtime paths the description claims, rather than reading them.

Verified

  • run-agent.mjs:21 fallbackNumber(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000. The "" / "abc" / "0" → 50m table in the description is accurate, including that 0 cannot disable the timer.
  • The graceful-degrade claim holds end to end. A timed-out gate leaves steps.verify.outputs.outcome empty; Finalize verification falls through case "${OUTCOME}" in fixed|noop) ;; *) exit 1 and Report dry-run / failure is always() && (… || failure() || cancelled()), so it posts. Bounding the gates really is a new path, not a new failure.
  • The 270 sum is conservative, which is the right direction. Repair deterministic rejection fires on steps.verify.outputs.retryable == 'true', which a timed-out first gate leaves empty — so the timeout path skips both repair steps and can never actually spend 130 + 60 + 20 + 60.
  • fail-fast: false is set, so the longer job cap does not widen a cross-leg cancellation window.
  • review-address is the last job (line 2571), so the test's |$ block terminator is correct today.
  • Tests: 106/107. The one failure (auto-reruns a check that died on infrastructure…) passes in isolation at 14.9s — a timing flake under parallel load, unrelated to this change.

Issues

1. The override ceiling is documented but unenforced. The comment states QWEN_AUTOFIX_TIMEOUT_MS "MUST stay below 7,800,000 ms" and spells out the consequence precisely — the step cap kills first, agent-timeout is never written, the round is misreported as a crash. Nothing enforces it. The test's regex reads only the || fallback literal, and a repo variable is invisible to CI by construction.

This is the PR's own thesis reappearing one layer up: a budget nobody can see is a budget nobody re-checks. The fix is cheap and turns the comment into an invariant — clamp in the step's run: before invoking the agent:

CAP_MS=7200000   # must stay <= the step's timeout-minutes above
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( QWEN_TIMEOUT_MS > CAP_MS )); then
  echo "::warning::QWEN_TIMEOUT_MS=${QWEN_TIMEOUT_MS} exceeds the step backstop; clamping to ${CAP_MS}"
  QWEN_TIMEOUT_MS="${CAP_MS}"
fi
export QWEN_TIMEOUT_MS

The test can then assert the clamp exists and that CAP_MS is derived from the same step's timeout-minutes, which is the same "derive both, assert the margin" discipline already applied to the fallback.

2. The breaker headline now recommends the one action the new comment forbids. TIMEOUT_WINDOW_CAP's message (~line 4511) says "A human should split or reduce the PR (or raise the agent time budget), then comment /autofix retry". After this PR the only knob for "raise the agent time budget" is QWEN_AUTOFIX_TIMEOUT_MS, and raising it past 120m silently produces the crash-misreport the new comment exists to prevent. A human following the workflow's own advice walks straight into it. Either drop that clause, or make it name the pair that has to move together (budget and step cap). With the clamp from (1) this degrades to a warning instead of a misreport, which is also fine.

3. issue-autofix has the identical bug and is untouched. Job at line 662, timeout-minutes: 180, and not one step-level bound in the entire job: Assess candidates (968) and Develop fix (1140) both run run-agent.mjs at the implicit 50-minute default, and its Verification gate (1145) is unbounded — the same step you just measured at 22m48s next door. The consequence is worse than in review-address: Withdraw claim on failure (1339) is (failure() || cancelled()), so a job-level timeout cancels it and the issue stays claimed with nothing withdrawn and no report posted.

Worst case there is roughly 7 + 50 + 50 + 23 = 130 of 180, so it fits today — but it fits by luck, for the same reason review-address fit until verification got measured. The new invariant test is scoped to review-address, so nothing guards it. Not a blocker for this PR; worth a linked follow-up rather than leaving it implicitly fine.

4. SETUP_AND_REPORT_MIN = 25 is a test-side reserve, not a runtime bound. The unbounded steps are still unbounded at runtime: Prepare branch and feedback (2754–3334, ~580 lines of git/gh work), Push and report (3700, retrying pushes plus gh calls), Finalize autofix status comment (4590). Measured at 5–7m and 3–4s today, but a hung gh call in any of them still produces exactly the silent round this PR closes, and 295/300 leaves five minutes of slack. Bounding them (15m each would do) would make the sum a real invariant instead of a partial one. If that's out of scope, the test comment should say the reserve is an assumption about unbounded steps rather than headroom — right now it reads as though the budget is fully accounted for.

5. "the queueing tail above is unchanged" overclaims. True of the cap: 300 vs 150 does not itself lengthen anything. Not true of the budget: the 81-minute tail was measured against rounds ending at 40–57m, and 50m → 120m roughly doubles slot-hold time for precisely the timeout-prone PRs this change targets. Suggest: "the cap does not change the tail; the raised budget does, for the PRs that exhaust it."

Style

6. Test placement. All ~90 new lines went into it('replays the handoff decision and terminal-round transitions under bash'), whose name now covers maybe a third of what it asserts. The budget invariant is a separate property with a separate failure mode — split it into its own it('bounds every long step so the round fits under the job timeout'). As written, a budget regression reports as a handoff-decision failure, which is a worse first line for whoever has to debug it.

7. Comment volume. ~45 lines of comment for one env var and one timeout-minutes:, a good share of it changelog: "Left implicit until now", "The two had drifted 30 minutes apart", "The old arithmetic … was wrong". This file is comment-heavy by convention so it isn't out of place, but historical narration ages worse than the rule it replaced. The next reader needs the invariant (budget ≤ cap − margin, and what the margin buys) and the measured table; the story of the drift belongs in the PR description, where it already is and reads well.

Risk

The change is well-argued and the measurements are real. The residual cost is worth stating plainly: worst case is now ~4.7h of wall time before a stuck round reports back to the thread, max-parallel: 5 means up to 25 runner-hours held per wave, and three budget exhaustions before TIMEOUT_WINDOW_CAP trips is now ~6h of agent time per PR instead of ~2.5h. The description is honest that the 120m number is a guess against a distribution with one point at the old cap — no observed round was measured as nearly finished. If a follow-up can log how far the agent got when the timer fired, the next adjustment can be evidence-driven rather than another flat raise.

None of the above blocks merging. (1) and (2) are the two I'd want before this lands, since they concern a knob whose misuse silently reintroduces the misreport the PR is closing.

中文小结

已验证: run-agent.mjs:21 的回退表准确;两道验证门加界后确实退化为普通验证失败路径(Finalize verificationcase 兜底 exit 1always() 上报照常发出);270 的求和是保守的(第一道门超时会让 retryable 为空,repair 及其验证门都跳过);fail-fast: false 在位;测试 106/107,唯一失败项单独跑通过,是并行下的计时 flake,与本 PR 无关。

主要问题:

  1. override 的上限只写在注释里,没有被强制。 QWEN_AUTOFIX_TIMEOUT_MS 超过 7,800,000ms 会让 step 上限先触发、agent-timeout 不落盘、轮次被误报为崩溃——而测试只能读到 || 后面的字面量,仓库变量对 CI 不可见。这正是本 PR 的论点在上一层重演:看不见的预算没人复查。建议在 step 的 run: 里做 clamp(见上方代码),把注释变成不变量。
  2. 熔断器的提示语现在推荐了新注释禁止的操作。 TIMEOUT_WINDOW_CAP 的文案仍说「或提高 agent 时间预算」,而唯一的旋钮已被 120m 封顶,照做就会踩中误报。建议改为同时提到预算与 step 上限须一起动。
  3. issue-autofix 有完全相同的问题且未处理。 该 job(662 行,180 分钟)没有任何 step 级约束,两个 agent 步沿用 50m 隐式默认,Verification gate 同样无界;且 Withdraw claim on failure(failure() || cancelled()),job 超时会连它一起取消——issue 会被永久占用且无任何上报。目前 7+50+50+23=130/180 只是恰好装得下,新测试也只覆盖 review-address。建议开跟进 issue。
  4. SETUP_AND_REPORT_MIN = 25 是测试侧的预留,不是运行时约束。 Prepare branch and feedbackPush and reportFinalize autofix status comment 仍然无界,任何一处 gh 卡住依旧会产生本 PR 要消灭的静默轮次,而 295/300 只剩 5 分钟余量。
  5. 「queueing tail 不变」说过头了。 对 cap 成立,对 budget 不成立:81 分钟的尾巴是在 40–57m 的轮次上量的,50m→120m 会让最容易超时的那批 PR 占用时长大致翻倍。

风格: 新增的约 90 行断言塞进了一个名字只覆盖三分之一内容的 it(),建议独立成一个测试;单个 env var 的 45 行注释里有不少是变更历史叙述,这部分放在 PR 描述里更合适(那里已经写得很好)。

均不阻塞合入,其中 (1)(2) 建议落地前处理。

@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. Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查——无阻断问题。 建议见行内评论。 未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

Comment on lines +8356 to +8357
const longSteps = stepBlocks.filter((b) =>
/node [^\n]*run-agent\.mjs|bash [^\n]*run-autofix-review-verification\.sh/.test(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The longSteps detector hard-codes two script names, so the whole-budget sum invariant only guards steps that run run-agent.mjs or run-autofix-review-verification.sh. The comment above is also internally contradictory: 'A new long step shows up here and must carry its own bound' cannot hold at the same time as 'Cheap setup/report steps are allowlisted implicitly by not matching' — a new long step running a new script does not match, so it is silently allowlisted as if cheap. — Failure scenario: a maintainer adds an unbounded long step running a different script (e.g. bash …/run-full-e2e-suite.sh); longSteps stays at 4, worstCaseMin still reads 295 ≤ 300, every assertion stays green, but the real worst case now overruns the 300-minute job cap → GitHub cancels the always() reporters and the round goes silent, the exact failure this PR closes.

Fix: tighten the comment to state the real boundary ('a new step running one of these two scripts shows up here'), or broaden the detector (e.g. sum the bounds of every run: step in the job and treat an unbounded one as infinite) so a new long step on any script is caught.

中文说明

longSteps 检测器把两个脚本名写死了,因此整体预算求和不变量只保护运行 run-agent.mjsrun-autofix-review-verification.sh 的步骤。上方注释也自相矛盾:「新的长步骤会出现在这里,必须自带约束」与「廉价的 setup/report 步骤因不匹配而被隐式列入白名单」无法同时成立——一个运行新脚本的长步骤并不匹配,因此会被静默地当作廉价步骤列入白名单。— 失败场景:维护者新增一个运行不同脚本的无约束长步骤(例如 bash …/run-full-e2e-suite.sh);longSteps 仍为 4,worstCaseMin 仍读作 295 ≤ 300,所有断言依旧全绿,但真实最坏情况此时已越过 300 分钟的 job 上限 → GitHub 会取消 always() 上报步骤,该轮就此静默,正是本 PR 要消灭的失败。

修复:把注释收紧到真实边界(「运行这两个脚本之一的新步骤会出现在这里」),或拓宽检测器(例如对 job 内每个 run: 步骤的约束求和、把无约束者视为无穷大),使任何脚本上的新长步骤都能被捕获。

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

Comment on lines +8378 to +8380
const worstCaseMin =
stepCaps.reduce((a, b) => a + b, 0) + SETUP_AND_REPORT_MIN;
expect(worstCaseMin).toBeLessThanOrEqual(jobCapMin);

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] This test file is not collected by any CI job. No workflow in .github/workflows/ runs npm run test:scripts (or otherwise invokes scripts/tests/), so the budget-sum invariant, the verification-gate bounds, the QWEN_TIMEOUT_MS margin and the continue-on-error checks this PR adds never run in any pipeline. — Failure scenario: a future change to qwen-autofix.yml breaks the invariant (drops a gate's timeout-minutes, or sets QWEN_TIMEOUT_MS above the step backstop); none of the 107 assertions here runs in CI, so the regression ships silently and the next autofix round misreports a timeout as a crash (the agent-timeout marker is never written because the step cap fires first). The file passing locally (107/107) is exactly what masks this.

Fix: add a CI step that runs npm run test:scripts (the script already exists in the root package.json) so these assertions gate changes to the autofix workflow. The unreachability predates this PR (hence Suggestion, not Critical), but the assertions this PR adds inherit it.

中文说明

本测试文件没有被任何 CI job 收集。.github/workflows/ 里没有任何 workflow 运行 npm run test:scripts(或以其他方式调用 scripts/tests/),因此本 PR 新增的预算求和不变量、验证门约束、QWEN_TIMEOUT_MS 余量以及 continue-on-error 检查在任何流水线里都不会运行。— 失败场景:未来对 qwen-autofix.yml 的改动破坏了该不变量(移除某个验证门的 timeout-minutes,或把 QWEN_TIMEOUT_MS 设到超过 step 兜底上限);这里 107 条断言没有一条会在 CI 中运行,于是回归会静默合入,下一次 autofix 轮次便把超时误报为崩溃(step 上限先触发,agent-timeout 标记永不写出)。本文件在本地全绿(107/107)恰恰掩盖了这一点。

修复:新增一个运行 npm run test:scripts 的 CI 步骤(根 package.json 里已有该脚本),让这些断言能够把关对 autofix 工作流的改动。该不可达性早于本 PR(因此定为 Suggestion 而非 Critical),但本 PR 新增的断言继承了它。

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Declined — this one is a false positive. The assertions in this file do gate changes in CI: ci.yml runs npm run test:ci as its main unit-test step (the Run tests and generate reports step, plus the macOS/Windows merge-queue jobs), and the root package.json defines test:ci as ... && npm run test:scripts, which collects scripts/tests/qwen-autofix-workflow.test.js. So a future change that breaks the budget-sum invariant fails CI on every PR today; the failure scenario (regression ships silently because none of the assertions run) cannot occur. A separate step would be a redundant duplicate of that existing gate, so I'm leaving it out to avoid diff growth. Happy to add a dedicated step anyway if a maintainer wants the script tests visible as their own CI line rather than chained inside test:ci.

中文说明

拒绝——这一条是误报。本文件的断言确实在 CI 中把关:ci.ymlnpm run test:ci 作为其主要单测步骤运行(Run tests and generate reports 步骤,外加 macOS/Windows 的 merge-queue job),而根 package.jsontest:ci 定义为 ... && npm run test:scripts,后者会收集 scripts/tests/qwen-autofix-workflow.test.js。因此,未来任何破坏预算求和不变量的改动今天都会在每个 PR 的 CI 上失败;其失败场景(因为断言从不运行而静默合入回归)不可能发生。单独新增一个步骤只是对现有这道门的冗余重复,因此为避免 diff 膨胀我不加入。如果维护者希望把脚本测试作为独立的一条 CI 显示、而不是链在 test:ci 内部,我也乐意照做。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Review feedback addressed

1. Override ceiling enforced at runtime (Required)

Decision: Implemented.

Added a clamp in the Triage and address step's run: block, before invoking run-agent.mjs. If QWEN_TIMEOUT_MS is non-numeric or exceeds BUDGET_CAP_MS=7200000 (120m), it is clamped with a ::warning:: annotation. The comment-only ceiling is now a runtime invariant.

The test derives the clamp ceiling from the workflow and asserts it stays under the step backstop (clampMs <= stepCapMin * 60000), following the same "derive both, assert the relationship" discipline already applied to the budget/cap pair.

2. Breaker headline no longer recommends a forbidden action (Required)

Decision: Implemented.

Updated both the TIMEOUT_WINDOW_CAP headline and the per-round LAST_FIX message to say "raise the agent time budget AND its step backstop together" instead of just "raise the agent time budget". With the clamp from (1), raising the budget alone degrades to a warning rather than a misreport, but the message is now accurate either way.

3. issue-autofix has the identical bug (Out of scope)

Decision: Declined — out of scope for this PR. The reviewer agrees: "Not a blocker for this PR; worth a linked follow-up." The issue-autofix job (line 662, 180-minute timeout) has no step-level bounds on its two agent steps or its verification gate, and its Withdraw claim on failure step is (failure() || cancelled()), so a job-level timeout cancels it silently. Worth a follow-up issue.

4. SETUP_AND_REPORT_MIN comment honesty (Suggestion)

Decision: Implemented.

The test comment now says the reserve is "an ASSUMPTION that they stay under 25m (measured 5-7m + 3-4s), not a proven headroom" and names the risk: "A hung gh call in any of them can still eat the job timeout."

5. Queueing tail overclaim (Suggestion)

Decision: Implemented.

Changed "so the queueing tail above is unchanged" to "The cap itself does not lengthen the queueing tail above; the raised 120-minute budget does, for the PRs that exhaust it."

6. Test placement (Suggestion)

Decision: Implemented.

Split the budget invariant assertions into it('bounds every long step so the round fits under the job timeout'), leaving the handoff replay in its original it('replays the handoff decision and terminal-round transitions under bash'). A budget regression now reports under its own name.

7. Comment volume (Suggestion)

Decision: Implemented.

Trimmed historical narration from both the workflow comments and test comments: removed "Left implicit until now", "The two had drifted 30 minutes apart", "The old arithmetic was wrong", "Raising it does NOT make a doomed round cheaper", and the verbose CEILING explanation. Kept the invariants, measured table, and budget arithmetic. Net: −89 lines added, +59 lines (−30 net).

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run scripts/tests/qwen-autofix-workflow.test.js — 108 passed (108 tests)
中文说明

已处理的评审反馈

1. 运行时强制 override 上限(必需)

决定: 已实现。

Triage and address 步骤的 run: 块中、调用 run-agent.mjs 之前添加了 clamp。如果 QWEN_TIMEOUT_MS 不是数字或超过 BUDGET_CAP_MS=7200000(120 分钟),则将其钳制到该值并输出 ::warning:: 注解。原来只写在注释里的上限现在是运行时不变量。

测试从 workflow 中推导 clamp 上限,并断言它不超过 step backstop(clampMs <= stepCapMin * 60000),遵循已有的「推导两者、断言关系」纪律。

2. 熔断器提示语不再推荐被禁止的操作(必需)

决定: 已实现。

TIMEOUT_WINDOW_CAP 的标题和每轮的 LAST_FIX 消息都改为「同时提高 agent 时间预算和 step backstop」,而非仅「提高 agent 时间预算」。有了 (1) 的 clamp,单独提高预算会退化为警告而非误报,但消息本身现在是准确的。

3. issue-autofix 存在相同问题(超出范围)

决定: 拒绝——超出本 PR 范围。评审者同意:「不阻塞本 PR;值得开跟进 issue。」issue-autofix job(第 662 行,180 分钟超时)的两个 agent 步骤和验证门都没有 step 级约束,且 Withdraw claim on failure(failure() || cancelled()),job 超时会将其一并取消。建议开跟进 issue。

4. SETUP_AND_REPORT_MIN 注释诚实性(建议)

决定: 已实现。

测试注释现在说明该预留是「一个假设,即这些步骤保持在 25 分钟以内(实测 5-7 分钟 + 3-4 秒),而非经过证明的余量」,并指出风险:「任何一处 gh 调用卡住仍然会吃掉 job 超时。」

5. 排队尾部过度声明(建议)

决定: 已实现。

将「so the queueing tail above is unchanged」改为「The cap itself does not lengthen the queueing tail above; the raised 120-minute budget does, for the PRs that exhaust it.」

6. 测试放置位置(建议)

决定: 已实现。

将预算不变量断言拆分为独立的 it('bounds every long step so the round fits under the job timeout'),handoff 重放保留在原来的 it('replays the handoff decision and terminal-round transitions under bash') 中。预算回归现在以自己的名字报告。

7. 注释量(建议)

决定: 已实现。

从 workflow 注释和测试注释中删除了历史叙述:移除「Left implicit until now」「The two had drifted 30 minutes apart」「The old arithmetic was wrong」「Raising it does NOT make a doomed round cheaper」以及冗长的 CEILING 解释。保留了不变量、实测表格和预算算术。净变化:−89 行删除,+59 行新增(净减 30 行)。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx vitest run scripts/tests/qwen-autofix-workflow.test.js — 108 通过(108 个测试)

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

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


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

@wenshao

wenshao commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Overview

Two things, and the second is the more valuable one:

  1. States the primary agent's budgetQWEN_TIMEOUT_MS: 120m (was the implicit 50m from run-agent.mjs:21), with the step cap raised 80m → 130m as a backstop and a shell clamp so a repo variable can't arm the timer past the cap.
  2. Budgets the round as a whole — the two verification gates were completely unbounded, so the real worst case was 7 + 80 + 23 + 20 + 23 = 153 against a 150-minute job cap. A job timeout cancels the always() reporters, which is the silent round this whole design exists to prevent. The suite was fully green while that was true.

The framing is right: the bug worth fixing here wasn't the 50-minute default, it was that nothing checked the sum. The new test asserts that sum rather than the individual numbers, which is the correct lesson.

I verified the key claims against the head tree rather than taking them from the description:

  • The graceful-degrade claim holds end-to-end. run-autofix-review-verification.sh writes outcome=fixed last (line 166), so a step-timeout kill leaves the output empty → Finalize verification falls through its case to exit 1 → the always() report posts. Better than the description says: retryable is unset too, so a timed-out gate does not burn a 20-minute repair agent run on the way out.
  • The clamp's operator ordering is load-bearing and correct. [[ ! "$X" =~ ^[0-9]+$ ]] || (( X > CAP )) short-circuits before (( )) on any non-digit value, which closes the classic bash-arithmetic injection through a repo variable. I also checked the over-large-literal path — bash saturates at INTMAX_MAX rather than wrapping, so a 23-digit variable still clamps instead of sneaking past and hitting Node's TimeoutOverflowWarning (which would set the delay to 1ms and kill the agent instantly).
  • ✅ Suite on the head: 106/108. The new bounds every long step… test passes. The 2 failures are 5s-timeout hangs in the bash-replay tests, macOS-environment, unrelated to this diff (one of them didn't reproduce on a second run).

Issues

1. PENDING_STALE_MIN=240 now sits below the 300-minute job cap — its own invariant, inverted

.github/workflows/qwen-autofix.yml:1830-1835:

# The bound must sit ABOVE real check durations here — review-pr can take ~50m and
# review-address is capped at 120m — so an active run keeps blocking and
# is never aged out mid-flight (which would enqueue the PR against a live
# check and double-process the feedback).
PENDING_STALE_MIN=240

That comment was already approximate before this PR; after it, it's wrong twice over — review-address is now capped at 300m, and 240 < 300, so the stated invariant no longer holds. A review-address job past the 4-hour mark ages out of HAS_PENDING_CHECKS (line 2081-2085 explicitly includes review-address* jobs in the blocking set) while it is still live.

The blast radius is mitigated — BUSY_PRS is status-based with no time bound, and the comment there calls it the real gate — but this is exactly the "pair asserted as two constants, drifting apart" failure mode the PR's own test rationale is written against. Suggest PENDING_STALE_MIN=330 and updating the comment, plus folding the relation into the new test (PENDING_STALE_MIN > jobCapMin), since it's derivable from the same two literals the test already extracts.

2. A timed-out gate is reported as a gate crash

New failure mode created by this PR. With the agent having written address-summary.md, a 60-minute gate kill lands in the last branch at :4287:

CAUSE="hit a verification-gate error before reaching a verdict"
LAST_FIX="a maintainer should check the gate logs, then re-arm"

The maintainer opens the gate logs and finds a run that just stops mid-vitest with no error. That's the same misclassification the PR argues against for the agent step — and it argues it well: the 10-minute margin exists precisely so the internal timer fires first and writes agent-timeout, because a bare step cap can't name its own cause. The gates get only the backstop half of that pattern.

Cheap symmetry: wrap the gate in timeout 55m bash … and write a gate-timeout marker on exit 124, then give the report a branch for it. Same shape as the agent, ~5 lines, and the round stops lying about why it ended.

3. The clamp test is one-sided and permits the margin-destroying mutation

scripts/tests/qwen-autofix-workflow.test.js:

expect(clampMs).toBeLessThanOrEqual(stepCapMin * 60000);

That allows BUDGET_CAP_MS=7800000 (130m) — the clamp ceiling raised to exactly the step cap, margin gone, and the step backstop fires before the internal timer on every override. That's the same mutation the test rejects three lines earlier for the fallback via expect(marginMin).toBeGreaterThanOrEqual(1). Hold both to the same rule:

expect(clampMs / 60000).toBeLessThanOrEqual(stepCapMin - 1);

4. TIMEOUT_WINDOW_CAP: 3 is justified by a number this PR invalidates

:204-213:

# next timeout any cheaper — each one burns a full agent budget (~50m of
# runner time) and pushes nothing.
TIMEOUT_WINDOW_CAP: '3'

The budget is now 120m, so the cap of 3 buys 6 runner-hours of pushed-nothing per PR instead of 2.5. That's not just a stale comment — it's the stated cost basis for the constant, and it went up 2.4× while the constant didn't move. Either update the number and accept the new cost explicitly, or drop the cap to 2 to hold total wasted budget roughly flat. Worth a decision either way rather than leaving the rationale pointing at 50m.

5. Two smaller drifts

  • :3320 — "The agent below runs for up to 80 minutes and the verification gate adds more" → 130.
  • :3425-3427 — "QWEN_AUTOFIX_TIMEOUT_MS overrides the fallback without a code change." With the clamp ceiling set to exactly the fallback (7,200,000), the variable can only ever lower the budget. Raising it does require a code change — which is what the new LAST_FIX string correctly tells maintainers ("raise the agent time budget and its step backstop"). The env comment should say lower-only so the two don't read as contradicting each other.

Design risk (flagging, not blocking)

120m is 2.4× the wall #8005 hit, on the hypothesis that those rounds were close to finishing. Nothing in the evidence shows the 47-file round was near completion at 50m — only that it stopped there. If the hypothesis is wrong, every future exhaustion costs 2.4× the runner time, holds a max-parallel: 5 slot 2.4× longer, and holds the per-PR head-write concurrency group for up to 5 hours (during which a maintainer's @qwen-code /resolve queues behind it, and a third entrant to the group cancels the pending one).

The PR is honest about this in the max-parallel comment ("The cap itself does not lengthen the queueing tail above; the raised 120-minute budget does"), and the measured tail was already 81 minutes for the 7th PR at the old budget. I'd pair the raise with issue #4 above rather than leave the breaker calibrated for a 50m budget.

I also agree with the "what this deliberately does not do" section — five data points is not a width heuristic, and declining to build the knob is the right call.


Description is behind the head

The body's Change table and Tests section predate f8fc0b52d/e8f59dfa8, so the clamp — the most security-relevant part of the diff — is undocumented there. More concretely, the fallback table:

"abc"      => 3000000 ms = 50 min   (malformed)

is no longer what happens: the shell clamp rewrites a malformed value to 7,200,000 before run-agent.mjs ever sees it, so "abc" now yields 120m, not 50m. The in-code comment at :3485 has this right; the PR body doesn't. Worth refreshing before merge.


Verdict

The round-level budget invariant is a real bug fix and the sum-based test is the right shape — that part I'd land as-is. #1 (PENDING_STALE_MIN inversion) and #3 (one-sided clamp assertion) are both small and both in the same "constants drifting apart" family this PR exists to close, so they belong in it. #2 and #4 are judgment calls I'd want answered before merge rather than fixed in 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 — no blockers. Suggestions are inline. Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查——无阻断问题。 建议见行内评论。 未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

Comment thread .github/workflows/qwen-autofix.yml Outdated
Comment on lines +3487 to +3488
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( QWEN_TIMEOUT_MS > BUDGET_CAP_MS )); then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The clamp compares the override using bash arithmetic, where a leading-zero integer is octal — so a zero-padded value silently bypasses the guard. — Failure scenario: a maintainer sets repo variable QWEN_AUTOFIX_TIMEOUT_MS=08000000 (zero-padded). The ^[0-9]+$ regex passes, but (( 08000000 > 7200000 )) errors out ("value too great for base" — 8 is not a valid octal digit) and the condition evaluates false, so the clamp does not fire and the value is exported unchanged with no ::warning::. run-agent.mjs:21 then reads it with JS Number() (always decimal) = 8,000,000 ms = 133 min, arming the timer past the 130-minute step backstop — the cap fires first, agent-timeout is never written, and the round is misreported as a crash, the exact case this clamp says it prevents. Reproduced empirically under bash. Fix: force base-10 with the 10# prefix (the regex guard already short-circuits non-digit values).

Suggested change
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( QWEN_TIMEOUT_MS > BUDGET_CAP_MS )); then
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
中文说明

[建议] 该钳制使用 bash 算术进行比较,而 bash 中前导零整数会被解释为八进制——因此补零的取值会静默绕过这道防护。— 失败场景:维护者将仓库变量设为 QWEN_AUTOFIX_TIMEOUT_MS=08000000(补零)。^[0-9]+$ 正则通过,但 (( 08000000 > 7200000 )) 会报错("value too great for base"——8 不是合法八进制位),条件求值为假,于是钳制不触发,该值原样导出且没有 ::warning::。随后 run-agent.mjs:21 用 JS Number()(恒为十进制)读到 8,000,000 ms = 133 分钟,把计时器定到超过 130 分钟的 step 兜底上限——step 上限先触发,agent-timeout 永不写出,该轮被误报为崩溃,正是此钳制声称要防止的情形。已在 bash 下实证复现。修复:用 10# 前缀强制十进制(正则守卫已先行短路非数字取值)。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

AutoFix round summary

Addressed the actionable review feedback on the round-level budget PR. Fixed the octal clamp bypass, aligned the pending-check staleness bound with the 300-minute job cap (in code and in the test), held the clamp ceiling to the same margin rule the fallback already enforces, and corrected the stale comments. Two maintainer judgment calls are escalated below rather than decided here, per the review's verdict.

Inline review comments

  • Octal bypass in the timeout clamp — FIXED. The comparison used bash arithmetic, where a leading-zero integer is octal, so a zero-padded repo variable (e.g. 08000000) passed the ^[0-9]+$ regex but errored inside (( )) ("value too great for base"), evaluated false, and was exported unclamped past the step backstop — the exact misreport the clamp exists to prevent. Reproduced this empirically under bash, then forced base-10 with the 10# prefix and re-verified the clamp now fires. The regex guard still short-circuits non-digit values before (( )) is reached.
  • Contradictory long-step detector comment — FIXED. Tightened the comment to state the real boundary: the detector matches steps running one of the two known long-running scripts, and a new step on either shows up even without a bound; cheap setup/report steps run other scripts and are covered by the SETUP_AND_REPORT_MIN reserve. Deliberately did not broaden the detector to sum every run: step — that would conflict with the test's explicit design, where the setup/report steps are intentionally left unbounded against a documented reserve assumption.
  • "Test file is not collected by any CI job" — DECLINED (false positive). The assertions do gate CI: ci.yml runs npm run test:ci as its main unit-test step (and the macOS/Windows merge-queue jobs do too), and the root package.json defines test:ci as … && npm run test:scripts, which collects this file. A reply with the evidence is posted on the thread; a separate step would be a redundant duplicate.

Maintainer comments (@wenshao)

  1. PENDING_STALE_MIN inversion — FIXED. Raised 240 → 330 (a 30-minute margin over the 300-minute review-address job cap), corrected the comment (the binding cap is the 300-minute job cap, not 120m), and folded the relation into the sum test as a new assertion: PENDING_STALE_MIN > jobCapMin, derived from the same two literals the test already extracts.
  2. A timed-out gate is reported as a gate crash — ESCALATED for a maintainer decision (review: "judgment calls I'd want answered before merge rather than fixed in it"). The decision: should a timed-out verification gate be named distinctly from a gate crash?
    • Option A (the review's suggestion): wrap the gate in timeout 55m bash …, write a gate-timeout marker on exit 124, and add a report branch — symmetric with the agent's agent-timeout path, ~5 lines.
    • Option B: leave as-is; a timed-out gate reports as the generic "hit a verification-gate error before reaching a verdict" and a maintainer checks the logs.
    • Recommendation: A — it is cheap, mirrors the pattern this PR establishes for the agent step, and stops the round misreporting a timeout as a crash. Left unimplemented and the question open pending the answer.
  3. One-sided clamp assertion — FIXED. The clamp ceiling is now held to the same margin rule as the fallback: expect(clampMs / 60000).toBeLessThanOrEqual(stepCapMin - 1), so the margin-destroying mutation (ceiling raised to exactly the step cap) is rejected just like it is for the fallback three lines earlier.
  4. TIMEOUT_WINDOW_CAP cost basis — ESCALATED for a maintainer decision (review: "Worth a decision either way rather than leaving the rationale pointing at 50m"). The comment justifies the cap of 3 by a ~50m budget that is now 120m. The decision: update the number and accept the new absolute cost, or drop the cap to hold total wasted budget flat?
    • Option A: correct "~50m" → "~120m" and keep the cap at 3.
    • Option B: drop the cap to 2 to hold total wasted runner-budget roughly at the old ~2.5h.
    • Recommendation: A with the corrected number — the cap counts timeouts, and three is still a reasonable tolerance before declaring a PR stuck. Left unchanged (still ~50m, cap 3) pending the decision rather than silently picking a direction.
  5. Two smaller drifts — FIXED. (a) The "runs for up to 80 minutes" status-comment note now reads 130 (the step backstop). (b) The QWEN_AUTOFIX_TIMEOUT_MS env comment now states the override is lower-only — with the clamp ceiling equal to the fallback, raising the budget still requires editing the default and the step backstop, matching what the LAST_FIX string already tells maintainers.

Also noted (not a code change)

  • The PR body's fallback table is stale: with the shell clamp, a malformed value like "abc" now yields 120m (rewritten to the 7,200,000 ceiling before run-agent.mjs sees it), not 50m. The in-code comment has this right; the description should be refreshed before merge.
  • The design-risk note (120m is 2.4× the wall feat(cli): adopt Goal v3 in interactive TUI #8005 hit) rides along with item Are you interested in AI Terminal? #4 — pairing the raise with the cap decision is exactly the coupling the review suggested.

Conflict notes

No conflict; --conflict false, so origin/main was not merged.

Verification

Commands actually run this round (all from the repository root):

  • npm run test:scripts (focused suite for the touched test file) — the edited file qwen-autofix-workflow.test.js passes 108/108, including the new PENDING_STALE_MIN > jobCapMin assertion and the tightened clamp-margin assertion. (The suite's 5 unrelated failures are spawnSync zip ENOENT in install-script.test.js — the zip binary is not installed on this runner; that file is unchanged and pre-exists on main, so it fails identically on the base branch.)
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js108 passed (108).
  • Octal clamp reproduction under bash — confirmed the old (( QWEN_TIMEOUT_MS > BUDGET_CAP_MS )) bypasses the clamp on 08000000, and the new (( 10#${QWEN_TIMEOUT_MS} > … )) fires it.
  • npm run build — passed.
  • npm run typecheck — passed.
  • npm run lint — passed.
  • npx prettier --check on both edited files — clean.
中文说明

AutoFix 本轮摘要

处理了本轮关于「轮级预算」PR 的可操作评审反馈。修复了八进制钳制绕过问题,让 pending-check 过期边界与 300 分钟的 job 上限对齐(代码与测试两处),把钳制上限收敛到 fallback 已在执行的同一条余量规则,并更正了过时的注释。按照评审结论,下方有两项维护者层面的判断项被上交给维护者决定,而非在此自行拍板。

行内评审评论

  • 超时钳制中的八进制绕过——已修复。 该比较使用 bash 算术,而 bash 中前导零整数为八进制,因此补零的仓库变量(如 08000000)能通过 ^[0-9]+$ 正则,却在 (( )) 内报错("value too great for base"),条件求值为假,于是该值越过 step 兜底上限被原样导出——正是此钳制要防止的误报。已在 bash 下实证复现,随后用 10# 前缀强制十进制并重新验证钳制现已触发。正则守卫仍会在到达 (( )) 之前先行短路非数字取值。
  • 自相矛盾的长步骤检测器注释——已修复。 把注释收紧到真实边界:检测器只匹配运行这两个已知长脚本之一的步骤,运行其中之一的新步骤即使没有约束也会出现在这里;廉价的 setup/report 步骤运行其他脚本,由 SETUP_AND_REPORT_MIN 预留量覆盖。刻意没有把检测器拓宽到对每个 run: 步骤求和——那会与测试的显式设计冲突:setup/report 步骤是刻意不设约束的,依赖一份有文档记录的预留量假设。
  • 「测试文件没有被任何 CI job 收集」——拒绝(误报)。 这些断言确实在 CI 中把关:ci.ymlnpm run test:ci 作为其主要单测步骤运行(macOS/Windows 的 merge-queue job likewise),而根 package.jsontest:ci 定义为 … && npm run test:scripts,后者会收集本文件。已在该线程上回复并附上证据;单独新增一个步骤只是冗余重复。

维护者评论(@wenshao

  1. PENDING_STALE_MIN 倒挂——已修复。240 → 330(相对 300 分钟的 review-address job 上限保留 30 分钟余量),更正注释(真正起约束作用的是 300 分钟的 job 上限,而非 120m),并把该关系作为一个新断言纳入求和测试:PENDING_STALE_MIN > jobCapMin,由测试已经提取的同两个字面量推导而来。
  2. 超时的验证门被上报为验证门崩溃——上交维护者决定(评审原文:"judgment calls I'd want answered before merge rather than fixed in it")。待决问题:超时的验证门是否应与验证门崩溃区分命名?
    • 方案 A(评审建议):把验证门包在 timeout 55m bash … 里,在 exit 124 时写出 gate-timeout 标记,并新增一个上报分支——与 agent 的 agent-timeout 路径对称,约 5 行。
    • 方案 B:维持现状;超时的验证门上报为通用的 "hit a verification-gate error before reaching a verdict",由维护者查日志。
    • 建议:A——成本低,与本 PR 为 agent 步骤确立的模式一致,并能避免把超时误报为崩溃。本轮不实现,问题保持开放以待答复。
  3. 单侧钳制断言——已修复。 钳制上限现在与 fallback 采用同一条余量规则:expect(clampMs / 60000).toBeLessThanOrEqual(stepCapMin - 1),于是摧毁余量的变异(把上限抬到恰好等于 step 上限)会像三行前对 fallback 那样被拒绝。
  4. TIMEOUT_WINDOW_CAP 的成本依据——上交维护者决定(评审原文:"Worth a decision either way rather than leaving the rationale pointing at 50m")。该注释用一个约 50m 的预算来为上限 3 辩护,而如今预算已是 120m。待决问题:是更新数字并接受新的绝对成本,还是下调上限以保持浪费的总预算大致不变?
    • 方案 A:把 "~50m" 更正为 "~120m",上限保持 3。
    • 方案 B:把上限降到 2,使浪费的总 runner 预算大致维持在旧的约 2.5 小时。
    • 建议:A 并更正数字——上限统计的是超时次数,3 次仍是判定一个 PR 卡死之前的合理容忍度。本轮保持原样(仍为约 50m、上限 3)以待决定,而非悄悄选定某个方向。
  5. 两处较小的漂移——已修复。 (a) "runs for up to 80 minutes" 的状态评论说明现改为 130(step 兜底上限)。(b) QWEN_AUTOFIX_TIMEOUT_MS 的 env 注释现声明该覆盖只能调低——由于钳制上限等于 fallback,调高预算仍需同时修改该默认值与 step 兜底上限,与 LAST_FIX 字符串已经告知维护者的内容一致。

另需说明(非代码改动)

  • PR 正文中的 fallback 表格已过时:在 shell 钳制下,像 "abc" 这样的非法取值现在会得到 120m(在 run-agent.mjs 读到之前就被改写为 7,200,000 上限),而非 50m。代码内注释是对的;描述应在合并前刷新。
  • 设计风险说明(120m 是 feat(cli): adopt Goal v3 in interactive TUI #8005 撞墙时长的 2.4 倍)随第 4 项一并处理——把预算上调与上限决定配对,正是评审建议的耦合方式。

冲突说明

无冲突;--conflict false,因此未合并 origin/main

验证

本轮实际运行的命令(均在仓库根目录执行):

  • npm run test:scripts(针对所改测试文件的聚焦套件)——所改文件 qwen-autofix-workflow.test.js 通过 108/108,包含新增的 PENDING_STALE_MIN > jobCapMin 断言与收紧后的钳制余量断言。(该套件中 5 个不相关的失败是 install-script.test.js 里的 spawnSync zip ENOENT——本 runner 未安装 zip 二进制;该文件未被改动且早于本 PR 存在于 main,因此在基线分支上同样失败。)
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js —— 108 passed (108)
  • 在 bash 下复现八进制钳制——确认旧的 (( QWEN_TIMEOUT_MS > BUDGET_CAP_MS )) 会在 08000000 上绕过钳制,而新的 (( 10#${QWEN_TIMEOUT_MS} > … )) 会触发钳制。
  • npm run build —— 通过。
  • npm run typecheck —— 通过。
  • npm run lint —— 通过。
  • 对两个所改文件运行 npx prettier --check —— 干净。

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

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


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

@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. Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查——无阻断问题。 建议见行内评论。 未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

Comment on lines +8418 to +8421
expect(addressStep).toContain('BUDGET_CAP_MS=7200000');
expect(addressStep).toMatch(
/QWEN_TIMEOUT_MS.*exceeds the step backstop; clamping/,
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The clamp block's if condition ([[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS ))) is only string-matched here, never executed — so mutations to that condition survive green. — Failure scenario: flipping > to < (passes over-cap values through, clamps under-cap ones), removing the ! from the regex test, or dropping 10# (a zero-padded octal value slips past) each leaves toContain('BUDGET_CAP_MS=7200000') and the warning-string match passing, so the suite stays green while the guard is broken. The adjacent replays the handoff decision and terminal-round transitions under bash test already extracts workflow bash and runs it with controlled inputs; the clamp block can be replayed the same way (e.g. QWEN_TIMEOUT_MS=99999997200000, =100 → unchanged, =abc7200000, =07200000 → clamped without error), asserting the exported value.

// extract BUDGET_CAP_MS=… through export QWEN_TIMEOUT_MS from addressStep, then:
for (const [input, want] of [['9999999','7200000'],['100','100'],['abc','7200000'],['07200000','7200000']]) {
  const out = execFileSync('bash', ['-c', clampBlock + '\nprintf "%s" "$QWEN_TIMEOUT_MS"'],
    { env: { ...process.env, QWEN_TIMEOUT_MS: input } }).toString();
  expect(out).toBe(want);
}
中文说明

clamp 代码块的 if 条件([[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )))在这里只被字符串匹配,从未真正执行——因此对该条件的变异会让测试套件仍然全绿。失败路径:把 > 翻成 <(放行超上限值、钳制低于上限的值)、去掉正则测试里的 !、或去掉 10#(带前导零的八进制值会绕过守卫),toContain('BUDGET_CAP_MS=7200000') 与告警字符串匹配都仍然通过,于是守卫已坏而套件依旧绿色。相邻的 replays the handoff decision and terminal-round transitions under bash 测试已经有现成模式:从 workflow 提取 bash 并在受控输入下运行;clamp 代码块可用同样方式回放(例如 QWEN_TIMEOUT_MS=99999997200000=100 → 不变、=abc7200000=07200000 → 被钳制且不报错),并对导出的值做断言。

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

Comment thread .github/workflows/qwen-autofix.yml Outdated
Comment on lines +3492 to +3493
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The clamp's (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )) wraps modulo 2^64, so a value ≥ 2^63 bypasses the guard with no warning and no clamp. — Failure scenario: a repo variable of ≥19 digits (e.g. 18446744073709551617) makes 10#… evaluate to a small or negative number, the comparison is false, and the unclamped value reaches run-agent.mjs, whose Number() accepts it and arms setTimeout(…, ~1.8e19) — Node's TimeoutOverflowWarning then sets the delay to 1 ms, killing the agent instantly and misclassifying the round as a crash: the exact misreport the comment above ("a misconfigured variable degrades to a warning, not a misreport") claims to prevent. Verified on GNU bash 5.2 (ubuntu-latest): 18446744073709551617, 72000000000000000000, and 9223372036854775808 all pass through unclamped — bash wraps here rather than saturating at INTMAX_MAX. The trigger requires a maintainer to set an absurd (~292-year) timeout, so this is low-likelihood; a one-line length guard closes it.

Suggested change
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]+$ ]] || (( ${#QWEN_TIMEOUT_MS} > 18 )) || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
中文说明

clamp 的 (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )) 会按 2^64 取模回绕,因此 ≥ 2^63 的值会绕过守卫——既不告警也不钳制。失败路径:一个 ≥19 位的仓库变量(如 18446744073709551617)会让 10#… 求值成一个很小或为负的数,比较结果为假,未钳制的值传到 run-agent.mjs,其 Number() 接受该值并设定 setTimeout(…, ~1.8e19)——随后 Node 的 TimeoutOverflowWarning 会把延时设为 1 ms,瞬间杀掉 agent 并把该轮误报为崩溃:正是上方注释(「配置错误的变量会降级为告警,而非误报」)声称要避免的误报。已在 GNU bash 5.2(ubuntu-latest)上验证:18446744073709551617720000000000000000009223372036854775808 全部未被钳制——bash 在这里是回绕,而非在 INTMAX_MAX 处饱和。触发需要维护者设置一个荒谬的(约 292 年)超时,因此概率很低;一行长度守卫即可堵上。

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

Comment thread .github/workflows/qwen-autofix.yml Outdated
Comment on lines +3428 to +3430
# change: the run block clamps it to the 7,200,000 ms ceiling (the
# fallback itself), so raising the budget still requires editing this
# default and the step backstop, while a misconfigured variable

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] This comment states the clamp ceiling is "the fallback itself" (clamp == budget), but no test enforces clamp >= budget — the two can drift apart with a green suite. — Failure scenario: a maintainer following the raise instructions below bumps the fallback 7200000 → 8400000 (140m), the step backstop 130 → 150, and the job cap 300 → 320; every assertion stays green (150 − 140 = 10 ≥ 1, 120 ≤ 149), but at runtime (( 10#8400000 > 7200000 )) clamps the budget back to 120m with only a ::warning::, so the raise silently never takes effect. The raise instructions here (and in the LAST_FIX/HEADLINE strings) name the fallback and the step backstop but not BUDGET_CAP_MS, which is exactly the value that must move too. Add expect(clampMs).toBeGreaterThanOrEqual(budgetMs); next to the other clamp assertions in the test, and name BUDGET_CAP_MS in these instructions.

中文说明

本注释声称 clamp 上限就是「回退值本身」(clamp == budget),但没有任何测试强制 clamp >= budget——两者可能在套件全绿的情况下悄然漂移。失败路径:维护者照下方「调高预算」的说明把回退值 7200000 → 8400000(140 分钟)、step 兜底 130 → 150、job 上限 300 → 320;所有断言依旧绿色(150 − 140 = 10 ≥ 1120 ≤ 149),但运行时 (( 10#8400000 > 7200000 )) 会把预算重新钳制回 120 分钟,只留下一条 ::warning::,于是这次「调高」悄悄从未生效。这里的调高说明(以及 LAST_FIX/HEADLINE 字符串)点名了回退值与 step 兜底,却没有点名 BUDGET_CAP_MS——而那恰恰是必须一起改动的值。建议在测试中其余 clamp 断言旁补上 expect(clampMs).toBeGreaterThanOrEqual(budgetMs);,并在这些说明里点名 BUDGET_CAP_MS

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

@wenshao

wenshao commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Review — C=0, 4 Suggestions / 2 Notes

Reviewed at 72f337be5 (includes the base-10 clamp follow-up), verified against a local worktree of the PR head rather than the diff alone.

What it does

Three coupled things, and the framing in the description is right that only the first was the reported symptom:

  1. States the primary agent's budget (QWEN_TIMEOUT_MS = 120m) instead of inheriting run-agent.mjs's 50-minute default, and raises the step backstop 80 → 130 to keep a 10-minute margin under it.
  2. Bounds the two verification gates, which were genuinely unbounded — the real fix. A gate eating the job timeout cancels the always() reporters, which is the silent round the whole design exists to prevent.
  3. Raises the review-address job cap 150 → 300 and PENDING_STALE_MIN 240 → 330 so the sum fits and a live run is never aged out of the pending-check filter mid-flight.

What I verified independently

  • run-agent.mjs:21 is Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000 — the implicit-50m claim holds. The kill path (SIGTERM → 10s → SIGKILL) and the agent-timeout marker write at line 330 are as described, so the "step cap fires first ⇒ misreported as a crash" reasoning is real, not hypothetical.
  • The graceful-degrade claim checks out end to end. Finalize verification reads steps.verify.outputs.outcome — a step output, not the step conclusion. A gate killed at 60m never reaches its GITHUB_OUTPUT write, so the value is genuinely empty, falls through case to exit 1, and Report dry-run / failure (always()) posts. Push and report is correctly skipped. The comment is accurate.
  • The worst-case sum is conservative, not tight. Repair deterministic rejection is gated on steps.verify.outputs.retryable == 'true', which a timed-out gate also cannot set — so the repair branch and the timed-out-gate branch are mutually exclusive. Real worst case is max(130+60, 130+~60+20+60) ≈ 270 in the rejection path and ~190 in the timeout path; the test's 270 sum over-counts in the safe direction.
  • The new test's longSteps filter is sound. node …run-agent.mjs / bash …run-autofix-review-verification.sh matches exactly the 4 intended steps inside review-address; the cp staging lines (2669, 2683) and the prose mentions (2675–2677) correctly don't match, so toHaveLength(4) is a real pin, not an accident.
  • Tests: scripts/tests/qwen-autofix-workflow.test.js → 107 passed, 1 failed. The failure (behaviorally replays the takeover-command toggle across all four paths) reproduces identically on the base commit, so it is environmental (macOS), not introduced here. The new bounds every long step… test passes.
  • actionlint: 24 info-level findings on the PR head, 24 on base — the clamp adds none.

Deriving both numbers from the workflow and asserting the margin and the sum — rather than restating them as literals — is the right instinct, and it is what makes the 153 > 150 class of drift catchable. Good change.


Suggestions

1. The clamp guard is escapable above 2^63 (Low). ^[0-9]+$ accepts a 19+ digit value and (( 10#… )) then wraps it to a negative int64, so the comparison is false and the value exports unclamped. Executed, not inferred:

7200000                 -> 7200000            (pass)
abc / 1e9 / -5 / ""     -> 7200000            (clamped, warning)
99999999999999999999999 -> 7200000            (clamped — wraps positive)
9223372036854775808     -> 9223372036854775808  ← escapes

Downstream, Number("9223372036854775808") is 9.22e18, setTimeout emits TimeoutOverflowWarning and coerces the delay to 1 ms, so the agent is SIGTERM'd almost immediately and the round reports timeout (9223372036854775808ms). Degenerate rather than dangerous, and it needs an admin to set a 19-digit repo variable — but it is precisely the "misconfigured variable degrades to a warning, not a misreport" property this block is claiming. One character fixes it:

if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then

2. The warning text is wrong for the malformed branch (Nit). The same message fires for both arms of the ||, so a malformed value prints QWEN_TIMEOUT_MS=abc exceeds the step backstop — which it does not. Something like is not a positive integer or exceeds the budget ceiling covers both.

3. The test derives budgetMs and clampMs but never relates them (Low). Raising the || 7200000 fallback to, say, 7500000 without touching BUDGET_CAP_MS passes every current assertion (marginMin = 5 ≥ 1, clampMs/60000 = 120 ≤ 129) while the clamp silently pulls the default back down to 120m and emits a ::warning:: on every run. That is the same drift class the rest of this test exists to catch, and it is one line:

expect(budgetMs).toBeLessThanOrEqual(clampMs);

4. SETUP_AND_REPORT_MIN = 25 leaves 5 minutes of true slack (Note). 270 + 25 = 295 against 300. The test comment is admirably honest that the reserve is an assumption rather than a proven headroom, and the mutual exclusion in the third bullet above means it will not bind in practice. Still, 320 is free — it stays well under the runner's 360 ceiling and buys back headroom for a hung gh call in one of the five unbounded report steps.

Notes (no action requested)

5. Queued matrix legs, not started ones, are the residual gap. The pending-check filter is keyed on startedAt and explicitly treats a check without one as non-blocking. With max-parallel: 5 and cancel-in-progress: false, the 6th leg's queued window now doubles from ~2.5h to ~5h, which doubles the window in which a later scan can re-select the same PR and stack another run behind the concurrency group. PENDING_STALE_MIN=330 does not help here — it never sees a leg that has not started. Pre-existing, and possibly already covered by the round/watermark marker; worth confirming rather than changing in this PR.

6. PENDING_STALE_MIN is not autofix-only. The jq filter admits any check whose workflowName != "Qwen Autofix", so 240 → 330 also extends how long a genuinely hung external CI check blocks autofix on that PR, 4h → 5.5h. The new pendingStaleMin > jobCapMin assertion pins the relationship correctly; just flagging that the bound is now driven by autofix's own job cap rather than by any check's legitimate runtime.

Two smaller things, both cosmetic: export QWEN_TIMEOUT_MS is redundant (the step's env: already exports it, and reassignment preserves the attribute) — harmless as defensive style. And the description's fallback table ("abc" => 3000000) describes run-agent.mjs in isolation; with the clamp now in front of it, malformed input resolves to 7,200,000, not 3,000,000. Worth a line in the body so the next reader does not chase the discrepancy.

中文摘要

结论:C=0,4 条建议 + 2 条说明。72f337be5 的本地 worktree 上核对,未只读 diff。

已独立验证:run-agent.mjs:21 的 50 分钟隐式默认、SIGTERM→10s→SIGKILL 的终止路径与 agent-timeout 落盘点均如描述;「优雅降级」链路真实成立——Finalize verification 读的是 steps.verify.outputs.outcome(step 输出,不是结论),被 timeout 杀掉的 gate 根本来不及写 GITHUB_OUTPUT,所以确实是空值,落入 case 兜底 exit 1always()Report dry-run / failure 照常发出;Repair deterministic rejectionsteps.verify.outputs.retryable 把关,超时的 gate 同样设不了它,因此「超时分支」与「修复分支」互斥,270 的求和是偏保守而非贴边。新测试的 longSteps 过滤精确命中 4 个目标 step,cp 暂存行与注释行都不会误匹配。测试 107 通过 1 失败,该失败在 base 上同样复现(macOS 环境问题),与本 PR 无关;actionlint 在 PR 与 base 上同为 24 条 info,未新增。

主要建议:

  1. clamp 在 2^63 以上可被绕过(低)。^[0-9]+$ 放行 19 位数,(( 10#… )) 溢出为负 int64 使比较为假,值被未截断导出;Number() 得到 9.22e18,setTimeout 溢出后把延迟压成 1 ms,agent 几乎立刻被杀。实测:9223372036854775808 逃逸,99999999999999999999999abc1e9-5 均被正确截断。把正则改成 ^[0-9]{1,8}$ 即可。
  2. 告警文案对畸形输入不准确(吹毛求疵)。两个分支共用一句话,abc 会打印 “exceeds the step backstop”,而它并没有超。
  3. 测试取出了 budgetMsclampMs 却没有建立关系(低)。把回退默认值提到 7,500,000 而不动 BUDGET_CAP_MS,现有断言全绿,但运行时每一轮都会被静默压回 120m 并刷一条 warning——正是这套测试想拦的漂移。补一行 expect(budgetMs).toBeLessThanOrEqual(clampMs)
  4. SETUP_AND_REPORT_MIN = 25 只剩 5 分钟真实余量(说明)。测试注释已诚实标明这是假设而非已证余量;结合第 3 点的互斥关系实际不会顶到,但把 job 上限放到 320 是免费的,仍远低于 360。

另两条说明:真正的残留缺口是排队中(未 started)的 matrix leg——过滤器以 startedAt 为准,未启动的 leg 不算阻塞,而 max-parallel: 5 配 300 分钟把这个窗口从约 2.5 小时翻倍到约 5 小时,PENDING_STALE_MIN 对它无效;以及 PENDING_STALE_MIN 并非只作用于 autofix,240→330 同样把外部卡死 check 的阻塞时间从 4 小时拉到 5.5 小时。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round summary (PR #8257)

Addressed all three inline review findings plus the maintainer's matching suggestions in one commit (60bedda5f).

Inline findings (automated reviewer)

  • rc:3694703886 — clamp condition only string-matched, never executed. Implemented. Added a behavioral replay that extracts the actual clamp block from the workflow and runs it under bash with controlled inputs, asserting the exported value: in-range 100 / 7200000 pass through unchanged; over-cap 9999999, malformed abc, zero-padded 09999999, and int64-overflowing 9223372036854775808 all clamp to 7200000. A flipped operator, a dropped width bound, or a missing 10# now fails the suite instead of surviving green. Follows the existing replays the handoff decision … under bash pattern.

  • rc:3694703887 — clamp escapable above 2^63. Fixed. Tightened the guard regex ^[0-9]+$^[0-9]{1,8}$ (the maintainer's suggested one-token fix). Any value with ≤8 digits is < 10^8 ≪ 2^63, so 10#… can no longer wrap negative and slip past the comparison; a 19+ digit value now fails the regex and clamps with a warning. The replay test pins 9223372036854775808 → 7200000, the exact value that previously escaped. I used the {1,8} regex rather than the suggested separate ${#…} > 18 length guard — same fix, one changed token instead of an added condition.

  • rc:3694703888 — no test enforces clamp ≥ budget; raise instructions omit BUDGET_CAP_MS. Implemented. Added expect(budgetMs).toBeLessThanOrEqual(clampMs) next to the other clamp assertions, and named BUDGET_CAP_MS in the raise-instructions comment so a maintainer raising the budget knows all three values (the || default, BUDGET_CAP_MS, and the step backstop) must move together.

Maintainer issue-level review (@wenshao, C=0)

  • pre-release: fix ci #1 clamp escapable above 2^63 — fixed as above (used the suggested {1,8} regex).
  • Where is the config saved? #2 warning text wrong for the malformed branch — fixed; the message now reads "is not a positive integer or exceeds the budget ceiling; clamping to …", covering both arms of the guard.
  • 如何自定义密钥文件 .env可能与其他文件冲突 #3 test never relates budgetMs to clampMs — fixed as above (expect(budgetMs).toBeLessThanOrEqual(clampMs)).
  • Are you interested in AI Terminal? #4 raise the job cap 300 → 320 for headroom — Declined. This adds churn to coupled constants for headroom the review itself notes "will not bind in practice" (the repair and timed-out-gate branches are mutually exclusive), against a reserve the test already documents as an assumption rather than proven headroom. Keeping the PR scoped to the real defects; happy to revisit if a report step is ever observed eating the job timeout.
  • Notes TypeError in Authentication Selection Interface #5 (queued matrix legs) and OpenAI API Error: 401 Incorecct API Key provided #6 (PENDING_STALE_MIN is not autofix-only) — acknowledged, no action requested; both are pre-existing observations outside this PR's scope.
  • Cosmetic: redundant export QWEN_TIMEOUT_MS — left as-is; the review calls it harmless defensive style, and removing it is churn for no benefit.
  • Cosmetic: PR-body fallback table ("abc" => 3000000) — noted. This mode cannot edit the PR body; with the clamp now in front of run-agent.mjs, malformed input resolves to 7,200,000 rather than 3,000,000. Flagging for the maintainer to adjust the body text.

Environment note (not a code change)

npm run typecheck initially failed on packages/cli/src/ui/commands/workflowsCommand.test.ts (WorkflowTask.pendingApprovals missing). This branch changes zero TypeScript files, so the error is independent of the PR. Root cause: a stale, untracked packages/core/dist built from a different code version (it declared a WorkflowApproval / pendingApprovals feature that is absent from the current source), which TypeScript project references fed to the cli typecheck. A clean npm run build regenerated the declarations from the current source and typecheck then passed. No source change was made for this.

Verification

  • npm run build — passed (regenerated the stale packages/core/dist).
  • npm run typecheck — passed (failed before the rebuild only because of the stale dist described above; clean afterwards).
  • npm run lint — passed.
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js — 108 passed (includes the new clamp replay and the budgetMs <= clampMs assertion).
  • Integration tests after npm run bundle — not applicable: the change is GitHub Actions workflow configuration plus a root-level node test script, neither of which is exercised through the bundled CLI or the integration harness.
  • npm run generate:settings-schema — not applicable: no settings source changed.
中文说明

Autofix 审查轮次总结(PR #8257

在一次提交(60bedda5f)中处理了全部三条行内审查发现,以及维护者提出的对应建议。

行内发现(自动审查器)

  • rc:3694703886 —— clamp 条件只做字符串匹配,从未真正执行。 已实现。新增了一个行为回放测试:从 workflow 中提取真实的 clamp 代码块,在受控输入下用 bash 运行,并对导出的值做断言:区间内的 100 / 7200000 原样通过;超上限的 9999999、畸形的 abc、带前导零的 09999999、以及 int64 溢出的 9223372036854775808 全部被钳制为 7200000。翻转运算符、去掉宽度上限、或缺少 10# 现在都会让测试套件失败,而不再能蒙混过关。沿用了既有的 replays the handoff decision … under bash 模式。

  • rc:3694703887 —— clamp 在 2^63 以上可被绕过。 已修复。把守卫正则 ^[0-9]+$ 收紧为 ^[0-9]{1,8}$(即维护者建议的单 token 修法)。任何 ≤8 位的值都 < 10^8 ≪ 2^63,因此 10#… 不再可能回绕成负数并绕过比较;19 位及以上的值现在会无法通过正则并被钳制、同时告警。回放测试钉住了 9223372036854775808 → 7200000,正是此前会逃逸的那个值。我采用了 {1,8} 正则,而非建议中单独的 ${#…} > 18 长度守卫——修复效果相同,只改一个 token,而不是新增一个条件。

  • rc:3694703888 —— 没有测试强制 clamp ≥ budget;调高说明里漏了 BUDGET_CAP_MS。 已实现。在其余 clamp 断言旁补上 expect(budgetMs).toBeLessThanOrEqual(clampMs),并在「调高预算」的注释里点名 BUDGET_CAP_MS,让维护者在调高预算时知道三个值(|| 回退默认值、BUDGET_CAP_MS、step 兜底)必须一起改动。

维护者 issue 级审查(@wenshaoC=0

  • pre-release: fix ci #1 clamp 在 2^63 以上可被绕过 —— 已按上文修复(采用建议的 {1,8} 正则)。
  • Where is the config saved? #2 告警文案对畸形分支不准确 —— 已修复;文案改为 “is not a positive integer or exceeds the budget ceiling; clamping to …”,同时覆盖守卫的两个分支。
  • 如何自定义密钥文件 .env可能与其他文件冲突 #3 测试从未把 budgetMs 与 clampMs 建立关系 —— 已按上文修复(expect(budgetMs).toBeLessThanOrEqual(clampMs))。
  • Are you interested in AI Terminal? #4 把 job 上限 300 → 320 以增加余量 —— 拒绝。这会为审查本身就指出「实际不会顶到」的余量(修复分支与超时 gate 分支互斥)去改动相互耦合的常量,而测试早已注明该预留是假设而非已证余量。把 PR 收敛在真实缺陷上;如果将来观察到某个 report step 真的吃掉了 job 超时,再回头处理。
  • 说明 TypeError in Authentication Selection Interface #5(排队中的 matrix leg)与 OpenAI API Error: 401 Incorecct API Key provided #6(PENDING_STALE_MIN 并非只作用于 autofix) —— 已知悉,未要求改动;两者都是本 PR 范围之外的既有观察。
  • 吹毛求疵:冗余的 export QWEN_TIMEOUT_MS —— 保持原样;审查已称其为无害的防御性写法,删除它只是无谓的改动。
  • 吹毛求疵:PR 正文里的回退表("abc" => 3000000 —— 已知悉。本模式无法编辑 PR 正文;在 clamp 已位于 run-agent.mjs 之前的当下,畸形输入会解析为 7,200,000 而非 3,000,000。提请维护者调整正文表述。

环境说明(非代码改动)

npm run typecheck 最初在 packages/cli/src/ui/commands/workflowsCommand.test.ts 上失败(缺少 WorkflowTask.pendingApprovals)。本分支没有改动任何 TypeScript 文件,因此该错误与本 PR 无关。根因:packages/core/dist 是一份陈旧、且未被 git 跟踪的构建产物,来自另一个代码版本(它声明了当前源码中并不存在的 WorkflowApproval / pendingApprovals 特性),而 TypeScript 的项目引用把它喂给了 cli 的 typecheck。一次干净的 npm run build 从当前源码重新生成了声明文件,随后 typecheck 通过。为此没有做任何源码改动。

验证(Verification)

  • npm run build —— 通过(重新生成了陈旧的 packages/core/dist)。
  • npm run typecheck —— 通过(重建之前仅因上述陈旧 dist 而失败;重建后干净)。
  • npm run lint —— 通过。
  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js —— 108 通过(含新增的 clamp 回放与 budgetMs <= clampMs 断言)。
  • npm run bundle 之后的集成测试 —— 不适用:本次改动是 GitHub Actions workflow 配置加一个根目录的 node 测试脚本,两者都不会通过打包后的 CLI 或集成测试框架来执行。
  • npm run generate:settings-schema —— 不适用:没有改动任何 settings 源。

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

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


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

@wenshao

wenshao commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Overview

Two related fixes to review-address:

  1. The primary agent step never stated QWEN_TIMEOUT_MS, so it silently took run-agent.mjs's 50m default while the step cap sat at 80m — a third of the step was unreachable and the number that actually ended every round appeared nowhere in the workflow. Now stated at 120m with a 130m step backstop.
  2. Raising it exposed that the round's budget was never checked as a whole: both verification gates were unbounded, so the real worst case was 7 + 80 + 23 + 20 + 23 = 153 against a 150m job cap — and a JOB timeout cancels the always() reporters, i.e. the silent round the whole design exists to prevent. Both gates now bounded at 60m, job cap 300m.

I verified the load-bearing claims rather than reading them:

  • run-agent.mjs:21 is Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000 — the implicit-50m diagnosis is correct.
  • The kill path (runQwen) is SIGTERM → 10s grace → SIGKILL → agent-timeout, so the 10-minute margin is generous but genuinely load-bearing.
  • The graceful-degrade claim holds end to end: a timed-out gate leaves steps.verify.outputs.outcome empty → Finalize verification falls through its case to exit 1Report dry-run / failure fires on failure(), and GATE_CRASHED (line ~4245) keeps the watermark on the sentinel so the feedback isn't stranded.
  • PENDING_STALE_MIN is compared against startedAt with the (.startedAt // $cut) > $cut null-guard, so a queued-but-not-started job is correctly non-blocking.
  • Suite: 108/108 pass. Three tests fail locally at vitest's default 5s per-test timeout because they shell out to bash; all green at --testTimeout=60000. Pre-existing, unrelated. node scripts/lint.js --actionlint clean.

The sum-based invariant test is the right instinct — asserting the numbers individually is exactly what let 153-against-150 pass green, and identifying long steps by what they execute rather than by whether they already carry a bound means a new unbounded gate shows up here. Good.


Findings

1. The clamp is one-sided, and the uncovered side is the more likely typo — medium

The new guard clamps only the ceiling. Everything below it passes through untouched. Replaying the actual block from the workflow against run-agent.mjs's expression:

QWEN_AUTOFIX_TIMEOUT_MS clamp output effective budget
7200000 7200000 120m ✅
9999999 7200000 120m ✅ clamped
abc / 09999999 / 19-digit 7200000 120m ✅ clamped
0 / 000 passes 50m (silent fallback)
120 passes 0.002m
60000 passes 1m

120 is not a contrived input. Every comment in this PR, the PR body, and the operator message all speak in minutes; the variable is the one place that wants milliseconds. A maintainer following LAST_FIX="… raise the agent time budget and its step backstop …" and setting QWEN_AUTOFIX_TIMEOUT_MS=120 arms a 120 ms timer. Every round then SIGTERMs instantly, writes agent-timeout, and reports "ran out of time before finishing (timeout (120ms))" — after three, TIMEOUT_WINDOW_CAP (=3) trips and AutoFix stops on the PR, advising the human to raise the budget they just raised. No ::warning:: anywhere in that loop.

That is precisely the misreport the clamp was added to prevent, arrived at from the other direction. (The 120ms in the comment text is the only diagnostic thread, and it takes a careful reader to pull it.)

Also: 0 and 000 pass the guard while the warning text asserts the value "is not a positive integer" — the regex doesn't enforce positivity.

Suggested fix, symmetric with the existing one:

BUDGET_CAP_MS=7200000
# Floor: below this every round is a guaranteed timeout, and a minutes-shaped
# value in a milliseconds variable (120 -> 120ms) would burn the whole
# TIMEOUT_WINDOW_CAP budget reporting a timeout the maintainer just "fixed".
BUDGET_FLOOR_MS=300000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] \
  || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )) \
  || (( 10#${QWEN_TIMEOUT_MS} < BUDGET_FLOOR_MS )); then
  echo "::warning::QWEN_TIMEOUT_MS=${QWEN_TIMEOUT_MS} is not an integer in [${BUDGET_FLOOR_MS}, ${BUDGET_CAP_MS}] ms; clamping to ${BUDGET_CAP_MS}"
  QWEN_TIMEOUT_MS="${BUDGET_CAP_MS}"
fi

The bash-replay harness in the test already makes this nearly free to pin — add expect(runClamp('120')).toBe('7200000') and expect(runClamp('0')).toBe('7200000') alongside the existing cases.

2. The new 60m gate bound introduces a timeout mode with no marker — low

Bounding the gates is right, and the degrade path is correct (verified above). But the resulting round is classified by GATE_CRASHED, so the thread says the gate crashed when it actually ran out of time — the exact distinction this PR spends 40 lines of comment preserving for the agent via agent-timeout. Not a correctness bug (watermark handling is identical either way), just an asymmetry worth a follow-up: run-autofix-review-verification.sh could stamp a start time, or the reporter could read steps.verify.outcome == 'failure' with an empty outputs.outcome and say so.

3. PENDING_STALE_MIN's margin now rests on GitHub's startedAt semantics — low, unverified

240-vs-150 had 90 minutes of slack; 330-vs-300 has 30. That is fine iff a check run's startedAt is populated when the job begins executing, not when it is queued. With max-parallel: 5 and a 300-minute cap, a 6th matrix target can now wait a long time for a slot — if startedAt were queue-time, queue + run could exceed 330 and a live review-address check would age out of HAS_PENDING_CHECKS mid-flight, enqueueing the PR against its own running check. The comment at line ~2084 asserts queued jobs have no startedAt, which if observed closes this; I can't confirm it from here. Worth a note in that comment recording how it was confirmed, since the margin is now thin enough that the assumption matters.

4. Nits

  • export QWEN_TIMEOUT_MS is redundant. The step-level env: already places it in the process environment, so the bash reassignment stays exported. Harmless and arguably defensive, but the line reads as if it were required.
  • The int64 comment slightly overstates its own mechanism. [[ ! … =~ … ]] || (( … )) short-circuits, so a 19-digit value is rejected by the regex and never reaches (( )). The {1,8} bound and 10# are both correct and worth keeping — the comment just reads as though (( )) is the thing being defended, when the regex is the actual guard and those two are belt-and-braces.
  • SETUP_AND_REPORT_MIN = 25 leaves the invariant at 270 + 25 = 295 ≤ 300 — 5 minutes of true slack, and the reserve is an assumption (the test is admirably honest about this). Bounding the setup steps (npm ci, build) would turn the assumption into a proven headroom, if it's ever worth the churn.

Cost / ops, for the record

The PR states this, and I want it on the record rather than as a surprise: a 300-minute cap with max-parallel: 5 means up to 25 runner-hours held per scan wave in the pathological case, and a PR that persistently exhausts its budget now burns up to ~6 runner-hours before TIMEOUT_WINDOW_CAP trips (was ~2.5). The "What this deliberately does not do" section is the right call — five data points don't support a width-scaled heuristic, and a knob built on a guess is worse than a flat number that is at least stated.


Verdict: the diagnosis is right, the reasoning is unusually well-evidenced, and the test finally asserts the invariant that matters. Finding 1 is the one I'd want addressed before merge — it's a one-line addition to a guard this PR is already adding, and without it the workflow's most likely misconfiguration produces a terminal, silently-misreported PR. The rest are follow-ups or notes.

@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. Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查——无阻断问题。 建议见行内评论。 未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

Comment thread .github/workflows/qwen-autofix.yml Outdated
Comment on lines +3494 to +3495
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The clamp guard's regex ^[0-9]{1,8}$ admits 0 and any all-zero / leading-zero string, so a zero value slips past both the ::warning:: and the "fall back to the same ceiling" guarantee documented in the comment above. — Failure scenario: a maintainer sets repo variable QWEN_AUTOFIX_TIMEOUT_MS=0Number('0') is 0 (falsy), so run-agent.mjs:21 (Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000) falls back to its own 50-minute internal default, NOT the 7,200,000 ms ceiling the comment promises — a silent 50-minute budget with no warning. Worse, 0100Number('0100') = 100 → a 100 ms timer that SIGTERMs the agent on launch, every round, accumulating timeout-exhaustion counts toward the "AutoFix stopped" headline. The round is still correctly reported as a timeout (the agent-timeout marker is written), so this is not a misreport — but it contradicts the invariant this PR exists to make airtight. The executed-clamp test covers '100', '7200000', '9999999', 'abc', '09999999', '9223372036854775808' — every case except the 0 that slips through.

Suggested change
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
BUDGET_CAP_MS=7200000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[1-9][0-9]{0,7}$ ]] || (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then

(Rejecting zero / leading-zero in the regex keeps the documented contract and the existing 10# octal guard intact; also add expect(runClamp('0')).toBe('7200000') to the executed-clamp cases.)

中文说明

[建议] 钳制守卫的正则 ^[0-9]{1,8}$ 会放行 0 以及任意全零 / 带前导零的字符串,因此零值会同时绕过 ::warning:: 告警和上方注释所承诺的「回落到同一上限」保证。— 失败场景:维护者把仓库变量设为 QWEN_AUTOFIX_TIMEOUT_MS=0Number('0')0(falsy),于是 run-agent.mjs:21Number(process.env.QWEN_TIMEOUT_MS) || 50 * 60 * 1000)回落到它自己的 50 分钟内部默认值,而不是注释所承诺的 7,200,000 ms 上限——得到一个没有任何告警的静默 50 分钟预算。更糟的是 0100Number('0100') = 100 → 一个 100 ms 的计时器,会在每一轮启动时立即 SIGTERM 掉 agent,从而不断累积超时耗尽计数,最终触发「AutoFix stopped」标题。该轮次仍会被正确地上报为超时(agent-timeout 标记会写出),因此这不是误报——但它违背了本 PR 存在意义所在的那条不变量。已执行钳制代码块的测试覆盖了 '100''7200000''9999999''abc''09999999''9223372036854775808'——唯独漏掉了会溜过去的 0

(在正则中拒绝零 / 前导零既能守住注释承诺的契约,又不影响现有的 10# 八进制守卫;同时给已执行钳制的用例补一条 expect(runClamp('0')).toBe('7200000')。)

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

The review's Finding 1: the guard clamped only the ceiling, and the
uncovered side is the likelier typo. Every comment in this file, the PR
body and the operator message speak in MINUTES; this one variable wants
MILLISECONDS. A maintainer told to "raise the agent time budget" who sets
QWEN_AUTOFIX_TIMEOUT_MS=120 armed a 120 ms timer — every round SIGTERMs
instantly, writes agent-timeout, and reports "ran out of time (timeout
(120ms))" until TIMEOUT_WINDOW_CAP trips and AutoFix stops on the PR,
advising the human to raise the budget they just raised. No warning
anywhere in that loop, which is the exact misreport the clamp exists to
prevent, reached from the other direction.

A 60000 ms floor rejects every minutes-shaped value, and it also closes
the `0`/`000` hole the review noted alongside it — those passed the bare
regex while the message asserted the value had to be positive. The
message now names the units, because a units confusion is the whole
failure mode.

Replayed the review's own table against the extracted block, stdout and
stderr separated: 7200000, 3600000 and the floor itself pass untouched;
120, 60, 0, 000 and 59999 all clamp with a warning, alongside the
over-cap, malformed, octal and int64 cases the previous round closed.
The test pins both boundaries from each side (59999 clamps, 60001 does
not) and asserts the warning names MILLISECONDS.
@wenshao
wenshao requested a review from Copilot August 1, 2026 07:35
@wenshao

wenshao commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Finding 1 addressed at 2ea770e5ee, and you were right that the uncovered side is the one that matters — 120 is exactly what someone following the operator message types.

The floor. BUDGET_FLOOR_MS=60000, checked alongside the ceiling. It rejects every minutes-shaped value (1..999) and also closes the 0/000 hole you noted in the same breath — those passed the bare regex while the message asserted positivity. The message now names the units, since a units confusion is the entire failure mode:

QWEN_TIMEOUT_MS=120 is not an integer of MILLISECONDS in [60000, 7200000]
(120 means 120ms, not 120 minutes); clamping to 7200000

Your table, replayed against the new block (extracted from the workflow, stdout and stderr separated so the warning is not mistaken for the value — my first pass did exactly that and read every clamped case as 50 min):

input clamped to warned effective
7200000 7200000 no 120.00 min
3600000 3600000 no 60.00 min
60000 (floor, inclusive) 60000 no 1.00 min
120 7200000 yes 120.00 min
60 / 0 / 000 / 59999 7200000 yes 120.00 min
9999999 / abc / 09999999 / 19-digit 7200000 yes 120.00 min

The test pins the boundary from both sides — 59999 clamps, 60001 does not — and asserts the warning contains MILLISECONDS, so a future edit that keeps the range but drops the unit hint fails here.

On your other items:

  • 如何自定义密钥文件 .env可能与其他文件冲突 #3 (test relates budgetMs to clampMs) — already landed in the previous round; expect(budgetMs).toBeLessThanOrEqual(clampMs) is in the suite.
  • Where is the config saved? #2 (warning text wrong for the malformed branch) — subsumed: one message now covers all three arms and is accurate for each.
  • Are you interested in AI Terminal? #4 / nits 3 (SETUP_AND_REPORT_MIN = 25, job cap → 320) — not taken, deliberately. Your own third bullet shows the 270 sum over-counts (the repair branch and the timed-out-gate branch are mutually exclusive via steps.verify.outputs.retryable), so the 5 minutes of nominal slack sits on top of a worst case that cannot occur. Raising the cap to buy headroom against a number I know to be conservative would make the invariant looser without making it truer. Bounding the setup steps, as you suggest, is the change that would turn the reserve into proven headroom — worth its own PR.
  • Finding 2 (a bounded gate reports GATE_CRASHED, not a timeout) — agreed and not fixed here. It is a real asymmetry: this PR spends 40 lines preserving crash-vs-timeout for the agent and then loses it for the gate. The reporter-side discriminator you sketch (steps.verify.outcome == 'failure' with an empty outputs.outcome) is the cheap version; I would rather do it with its own test than fold it into this one.
  • Finding 3 (startedAt semantics) — I have not confirmed it either, and I am not going to assert it from here. Your read of the (.startedAt // $cut) > $cut null-guard matches mine, but how it was confirmed is exactly what the comment should record, and neither of us has run that. Leaving it as a stated assumption is more honest than a comment that sounds settled.
  • Nit: the int64 comment overstates its mechanism — fair; the regex is the guard and 10# is belt-and-braces. Left as is this round rather than churning the block again immediately after changing its condition.
  • Body vs run-agent.mjs fallback table — you are right that with the clamp in front, malformed input resolves to 7,200,000, not 3,000,000. The table describes run-agent.mjs:21 in isolation; I will relabel it as such rather than delete it, since that expression is still the thing the clamp is protecting.

Suite 108/108 at --testTimeout=60000 (the three bash-shelling tests exceed vitest's 5 s default, as you saw); actionlint, yamllint and eslint clean.

中文说明

Finding 1 已在 2ea770e5ee 处理。你判断得对:没被覆盖的那一侧才是要紧的——120 正是照着运维提示去做的人会输入的值。

下限。 BUDGET_FLOOR_MS=60000,与上限一并校验。它拒绝所有「分钟形状」的值(1..999),也顺带堵上你同时点出的 0/000 漏洞——那两个能通过裸正则,而文案却声称值必须为正。文案现在明确点出单位,因为这整个故障模式就是单位混淆。

你那张表,在新块上重放(从工作流中抽取,stdout 与 stderr 分离,以免把警告误当成取值——我第一遍恰恰犯了这个错,把每个被截断的用例都读成了 50 分钟):见上表。72000003600000 与下限本身原样通过;12060000059999 全部带警告截断,与上一轮已关闭的超限、畸形、八进制、int64 各例并列。

测试从两侧钉住边界——59999 被截断、60001 不被截断——并断言警告中含 MILLISECONDS,因此日后若保留区间却删掉单位提示,会在此处失败。

其余各条: #3(测试建立 budgetMsclampMs 的关系)上一轮已落地;#2(畸形分支文案不准)已被统一文案吸收;#4 与 nit 3(SETUP_AND_REPORT_MIN = 25、job 上限提到 320)刻意未采纳——你自己第三条已证明 270 的求和偏保守(修复分支与超时分支经 steps.verify.outputs.retryable 互斥),那 5 分钟名义余量是叠在一个不可能发生的最坏情况之上的;为一个我已知偏保守的数字买余量,只会让不变量更松而非更真。把 setup 步骤也加上界限,才是把「假设的储备」变成「已证余量」的改动,值得单开一个 PR。Finding 2(被超时杀掉的 gate 报成 GATE_CRASHED 而非超时)认同且本轮未修——这确实是个不对称:本 PR 花 40 行为 agent 保留了「崩溃 vs 超时」的区分,却在 gate 上丢掉了;你给出的上报侧判据是便宜的做法,但我更愿意让它带着自己的测试单独走。Finding 3(startedAt 语义)我同样没有确认,也不会从这里断言——你对空值守卫的读法与我一致,但如何确认恰恰是那条注释应当记录的,而我们都还没跑过;把它明写为假设,比写一条听起来已成定论的注释更诚实。int64 注释略微夸大其机制——属实,正则才是守卫,10# 是双保险;本轮刚改过该条件,不再立刻反复改动。PR 描述里的回退表格——你说得对,加上 clamp 之后畸形输入解析为 7,200,000 而非 3,000,000;我会把它标注为「run-agent.mjs:21 孤立行为」而非删除,因为那正是 clamp 所保护的对象。

套件在 --testTimeout=60000 下 108/108(你也看到了,那三个要 shell 出去的测试超过 vitest 默认的 5 秒);actionlint、yamllint、eslint 均干净。

Reviewed with Claude Code (Fable 5).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

scripts/tests/qwen-autofix-workflow.test.js:8354

  • The test hard-codes that there are exactly 4 “long steps” (run-agent + two verification gates). That makes the invariant brittle: if the workflow later adds another step that runs one of these scripts with a proper timeout, the safety properties still hold but this test will fail just because the count changed.

Prefer asserting a minimum (so missing steps still fail) and then summing whatever long steps exist to enforce the job-cap invariant.

    // Primary + repair agent steps and their two verification gates.
    expect(longSteps).toHaveLength(4);

.github/workflows/qwen-autofix.yml:3510

  • The clamp warning references only QWEN_TIMEOUT_MS, but operators will typically be editing the repo variable QWEN_AUTOFIX_TIMEOUT_MS. Mentioning the source variable in the warning makes it much easier to diagnose misconfiguration from the Actions log, without changing the behavior.
            echo "::warning::QWEN_TIMEOUT_MS=${QWEN_TIMEOUT_MS} is not an integer of MILLISECONDS in [${BUDGET_FLOOR_MS}, ${BUDGET_CAP_MS}] (120 means 120ms, not 120 minutes); clamping to ${BUDGET_CAP_MS}"

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

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

未发现问题。LGTM!✅

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round — no new code change

This round's only actionable feedback was one inline suggestion from the automated reviewer; it is already resolved in the code, so no new commit is needed.

Inline suggestion rc:3695002235 — resolved in code (no change)

Suggestion: the clamp guard's regex ^[0-9]{1,8}$ admits 0 and leading-zero strings, so a zero value slips past both the ::warning:: and the "fall back to the same ceiling" guarantee; tighten the regex to ^[1-9][0-9]{0,7}$ and add expect(runClamp('0')).toBe('7200000').

Disposition: already resolved by the floor added at 2ea770e5e (current HEAD). The suggestion was generated against a stale, pre-floor view of the block — it even cites a '100' test case that no longer exists. The guard now reads:

BUDGET_CAP_MS=7200000
BUDGET_FLOOR_MS=60000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] ||
   (( 10#${QWEN_TIMEOUT_MS} < BUDGET_FLOOR_MS )) ||
   (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
  echo "::warning::QWEN_TIMEOUT_MS=${QWEN_TIMEOUT_MS} is not an integer of MILLISECONDS in [${BUDGET_FLOOR_MS}, ${BUDGET_CAP_MS}] (120 means 120ms, not 120 minutes); clamping to ${BUDGET_CAP_MS}"
  QWEN_TIMEOUT_MS="${BUDGET_CAP_MS}"
fi

The floor (< BUDGET_FLOOR_MS) is exactly what closes the hole the suggestion describes, and it is strictly more robust than the proposed regex:

  • 0, 000, 0100 (=100), and every minutes-shaped value (1999) fall below the floor, so each is warned and clamped to the ceiling — they never reach run-agent.mjs unclamped.
  • The suggested regex ^[1-9][0-9]{0,7}$ would not catch 120 (it matches that regex); only the floor catches the minutes-shaped typo that is the likelier mistake. Adding the regex on top would be redundant defense for the leading-zero case the floor already handles.
  • The exact test case the suggestion asks for is already in the suite: expect(runClamp('0')).toBe('7200000'), alongside runClamp('000'), runClamp('59999')/runClamp('60001') (floor boundary pinned from both sides), and the minutes-shaped loop.

Per AGENTS.md's Simplicity First rule, the redundant regex tightening is declined; the concern it raises is fully addressed by the floor already in the codebase.

Review (no blockers)

The automated reviewer's top-level review was COMMENTED with no blockers; its only inline suggestion is the one resolved above. Its note that the workflow's embedded-shell lint is not supported by actionlint is a stated tool limitation, not a finding.

Verification

  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js -t "bounds every long step so the round fits under the job timeout" --testTimeout=60000passed (1 passed | 107 skipped). This test replays the actual clamp block under bash and asserts runClamp('0'), runClamp('000'), the minutes-shaped values, and both floor boundaries clamp/pass correctly.
  • Direct bash replay of the extracted workflow clamp block — 0, 000, 0100, 120 all clamp to 7200000; 60000 and 7200000 pass through untouched. For QWEN_TIMEOUT_MS=0 the block emits ::warning::QWEN_TIMEOUT_MS=0 is not an integer of MILLISECONDS in [60000, 7200000] (120 means 120ms, not 120 minutes); clamping to 7200000, confirming zero does not slip past the warning or the ceiling.

No source files were modified this round; the working tree is unchanged.

中文说明

Autofix 审查轮次 —— 无新代码改动

本轮唯一可操作的反馈是自动审查器的一条行内建议;它已经在代码中得到解决,因此无需新提交。

行内建议 rc:3695002235 —— 已在代码中解决(无改动)

建议: 钳制守卫的正则 ^[0-9]{1,8}$ 会放行 0 以及带前导零的字符串,因此零值会同时绕过 ::warning:: 告警和「回落到同一上限」的保证;建议把正则收紧为 ^[1-9][0-9]{0,7}$,并补充 expect(runClamp('0')).toBe('7200000')

判定:已由 2ea770e5e(当前 HEAD)新增的下限解决。 该建议是针对加下限之前的旧版代码块生成的——它甚至引用了一个已不存在的 '100' 测试用例。当前守卫为:

BUDGET_CAP_MS=7200000
BUDGET_FLOOR_MS=60000
if [[ ! "${QWEN_TIMEOUT_MS}" =~ ^[0-9]{1,8}$ ]] ||
   (( 10#${QWEN_TIMEOUT_MS} < BUDGET_FLOOR_MS )) ||
   (( 10#${QWEN_TIMEOUT_MS} > BUDGET_CAP_MS )); then
  echo "::warning::QWEN_TIMEOUT_MS=${QWEN_TIMEOUT_MS} is not an integer of MILLISECONDS in [${BUDGET_FLOOR_MS}, ${BUDGET_CAP_MS}] (120 means 120ms, not 120 minutes); clamping to ${BUDGET_CAP_MS}"
  QWEN_TIMEOUT_MS="${BUDGET_CAP_MS}"
fi

下限(< BUDGET_FLOOR_MS)恰恰堵上了该建议所描述的漏洞,而且比所建议的正则更稳健:

  • 00000100(=100)以及所有「分钟形状」的值(1999)都低于下限,因此都会被告警并钳制到上限——它们绝不会未经钳制就到达 run-agent.mjs
  • 所建议的正则 ^[1-9][0-9]{0,7}$ 反而抓不住 120(它能匹配该正则);只有下限才能抓住这个更可能发生的「分钟形状」笔误。在其上再叠加该正则,对于下限已经处理的前导零情形而言是冗余防御。
  • 该建议要求的那条测试用例已经在套件中:expect(runClamp('0')).toBe('7200000'),旁边还有 runClamp('000')runClamp('59999')/runClamp('60001')(从两侧钉住下限边界),以及分钟形状的循环用例。

依据 AGENTS.md 的「简洁优先」原则,冗余的正则收紧不予采纳;它所提出的问题已由代码库中既有的下限完全解决。

审查(无阻断)

自动审查器的顶层审查为 COMMENTED,无阻断问题;其唯一的行内建议就是上面已解决的那条。它提到工作流内嵌 shell 的 lint 不被 actionlint 支持,那是已声明的工具限制,并非一项发现。

验证

  • npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/qwen-autofix-workflow.test.js -t "bounds every long step so the round fits under the job timeout" --testTimeout=60000 —— 通过(1 passed | 107 skipped)。该测试在 bash 下重放实际的钳制代码块,并断言 runClamp('0')runClamp('000')、分钟形状各值以及两侧下限边界的钳制/放行均正确。
  • 对从工作流中抽取的钳制代码块直接做 bash 重放——00000100120 全部钳制为 7200000600007200000 原样通过。当 QWEN_TIMEOUT_MS=0 时,该代码块输出 ::warning::QWEN_TIMEOUT_MS=0 is not an integer of MILLISECONDS in [60000, 7200000] (120 means 120ms, not 120 minutes); clamping to 7200000,确认零值不会绕过告警或上限。

本轮未修改任何源文件;工作树保持不变。

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


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

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. The budget math is sound: worst case 280m fits under the 300m job cap (and the 360m runner ceiling). The 10m margin between the 120m budget and 130m step backstop correctly protects the agent-timeout marker write path. Bounding the two verification gates at 60m with continue-on-error: true turns a job-level kill into graceful degrade. The clamp block with floor guard (60000ms) prevents the minutes-vs-milliseconds confusion, and 10# + {1,8} width bound handle octal/overflow edge cases. Test asserts the SUM invariant rather than individual constants, and executes the actual clamp under bash — mutation-tested 7 variants. Well-reasoned scope decision to not build size-based heuristics on 5 data points.

@wenshao
wenshao added this pull request to the merge queue Aug 1, 2026
Merged via the queue into main with commit 46a16de Aug 1, 2026
55 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.3.

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants