Skip to content

fix(daemon): reduce subagent live replay journal - #9057

Merged
wenshao merged 5 commits into
mainfrom
fix/subagent-live-journal
Aug 14, 2026
Merged

fix(daemon): reduce subagent live replay journal#9057
wenshao merged 5 commits into
mainfrom
fix/subagent-live-journal

Conversation

@ytahdn

@ytahdn ytahdn commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This change adds a compact live-turn replay projection for clients that only render the main conversation summary. The daemon keeps the existing complete journal as the default for compatibility, while WebUI load and reconnect requests select a summary journal that excludes nested subagent detail events but retains root conversation events, subagent lifecycle signals, tool state, and nested usage frames consumed by the main transcript.

The summary and complete journals have independent replay limits and pagination anchors. The load-only replay mode is validated at the REST and bridge boundaries, and resume requests do not send or apply it.

Why it is needed

During a long running turn, the daemon previously placed every nested subagent event into the live replay journal. The live EventBus stream itself was not limited to 8 MiB, so an already connected client continued to work. The problem appeared after a refresh: session load had to return the bounded live journal, and verbose subagent output could exceed the 10,000-event or 8 MiB replay window. Web Shell then received only the truncation marker and could show History truncated for live turn replay until the turn finished and the complete persisted transcript became available.

Web Shell no longer renders nested subagent detail in the main conversation and exposes it through the detail view instead. Replaying those detail events into the main-session recovery response consumed the limit without contributing visible main transcript content.

With this change, refresh recovery requests use the summary journal, so nested detail no longer exhausts the live replay budget. The real-time EventBus stream, completed-turn persistence, historical pagination, full replay for other clients, and the subagent detail view remain unchanged.

Reviewer Test Plan

How to verify

  1. Start a turn that produces a large volume of nested subagent output and refresh Web Shell before the turn completes.
  2. Confirm the load request uses summary live replay and the restored main conversation contains the root messages, task lifecycle and tool state, and accumulated subagent usage without the nested detail stream.
  3. Confirm the restore response does not hit the live-journal truncation marker solely because of nested subagent detail.
  4. Confirm a default load without the summary option still returns the complete live journal.
  5. Confirm resume does not send the load-only option and invalid values are rejected.
  6. After the turn completes, confirm persisted history pagination and the subagent detail view still expose the complete content.

Automated coverage verifies the independent full and summary caps, summary filtering and usage retention, record anchors, mixed concurrent restore shapes, reconnect and epoch-reset paths, request validation, and default backward compatibility.

Evidence (Before & After)

Before: refreshing during a verbose subagent turn could replace the visible live transcript with a truncation notice until the turn completed.

After: refresh recovery restores the compact main-conversation projection while complete subagent details remain available through their existing detail and persisted-history paths.

No browser recording was captured; verification is covered at the daemon, SDK, and provider layers.

Tested on

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

Environment (optional)

Local Node.js workspace. Verified with the affected ACP, CLI, SDK, and WebUI tests, full repository build, lint, and typecheck.

Risk & Scope

  • Main risk or tradeoff: the daemon keeps a small second journal for summary recovery; the complete journal remains the compatibility default, and tests cover independent truncation state and anchors.
  • Not validated / out of scope: real browser E2E and platform-specific behavior. Live EventBus delivery, completed history pagination, and Web Shell rendering are intentionally unchanged.
  • Breaking changes / migration notes: none. The new load option is optional and defaults to complete replay.

Linked Issues

N/A

Pictures

Before

image
中文说明

本 PR 做了什么

本改动为只展示主会话摘要的客户端增加精简版实时回放。daemon 仍默认保留并返回完整 journal,以保证兼容性;WebUI 在 load 和重连恢复时请求 summary journal。summary journal 会排除 subagent 的嵌套详情事件,但保留主会话事件、subagent 生命周期、工具状态以及主会话统计所消费的嵌套 usage 帧。

精简版和完整版 journal 分别计算回放上限与分页锚点。该选项只用于 load,并在 REST 与 bridge 边界进行合法性校验;resume 不发送也不应用该选项。

为什么需要

以前在长时间运行的一轮中,daemon 会把所有 subagent 嵌套事件写入 live replay journal。实时 EventBus 本身没有 8 MiB 限制,因此已经连接的客户端可以继续正常显示。问题发生在刷新以后:session load 必须返回受限的 live journal,而大量 subagent 输出可能超过 10,000 个事件或 8 MiB 的回放窗口。此时 Web Shell 只能收到截断标记,并显示 History truncated for live turn replay,直到本轮结束、完整内容进入持久化历史后才能恢复。

Web Shell 主会话已经不再渲染 subagent 的嵌套详情,用户需要时会从详情入口查看。因此,把这些详情事件放进主会话刷新恢复响应,只会消耗回放额度,不会产生可见的主会话内容。

修复后,刷新恢复使用 summary journal,subagent 详情不会再挤占 live replay 限额。实时 EventBus、已完成轮次的持久化内容、历史分页、其他客户端使用的完整回放以及 subagent 详情入口均保持不变。

Reviewer 测试计划

验证方式

  1. 启动一个会产生大量 subagent 嵌套输出的任务,并在本轮结束前刷新 Web Shell。
  2. 确认 load 请求使用 summary live replay,恢复后的主会话包含主消息、任务生命周期、工具状态和累计 subagent usage,但不包含嵌套详情流。
  3. 确认恢复响应不会仅因为 subagent 详情过多而触发 live-journal 截断标记。
  4. 确认未指定 summary 的默认 load 仍返回完整 live journal。
  5. 确认 resume 不发送 load-only 选项,非法值会被拒绝。
  6. 本轮完成后,确认持久化历史分页和 subagent 详情入口仍可获得完整内容。

自动化测试覆盖完整版与精简版的独立上限、summary 过滤与 usage 保留、分页锚点、并发不同恢复形状、重连与 epoch reset、请求校验及默认兼容性。

修改前后证据

修改前:subagent 输出较多时,中途刷新可能让可见内容只剩截断提示,直到本轮结束。

修改后:刷新会恢复精简的主会话投影,完整 subagent 详情仍通过原有详情和持久化历史路径提供。

未录制浏览器证据;验证由 daemon、SDK 和 provider 层自动化测试覆盖。

测试平台

OS 状态
🍏 macOS ✅ 已测试
🪟 Windows N/A
🐧 Linux N/A

环境

本地 Node.js workspace。已验证受影响的 ACP、CLI、SDK 与 WebUI 测试,以及全仓 build、lint 和 typecheck。

风险与范围

  • 主要风险或取舍:daemon 会额外维护一个较小的 summary journal;完整 journal 仍是兼容性默认值,并有测试覆盖独立截断状态和锚点。
  • 未验证或范围外:真实浏览器 E2E 与其他平台行为。实时 EventBus、已完成历史分页和 Web Shell 渲染逻辑均有意保持不变。
  • 破坏性变更或迁移说明:无。新的 load 参数可选,默认仍为完整回放。

关联 Issue

N/A

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-run on the current head. Since the last pass (which reviewed 438957db + 8c72bd2), the autofix loop pushed three review-response commits (839e6f5a51f12015c17529c); this pass re-reviews c17529c from scratch.

  • Template: complete ✓
  • Problem: observed, not theoretical. The live replay journal is bounded at ingest (10,000 events / 8 MiB default), and a verbose subagent turn fills it with nested frames the Web Shell main transcript doesn't even render — so a mid-turn refresh returned the truncation marker and nothing else until the turn completed. The mechanism checks out in base code, and the maintainer reproduced the failure and verified the fix on a real local stack (see the verification note in this thread).
  • Direction: aligned. Web Shell already projects the main transcript in summary mode; making the live-replay projection match what the client renders is the right shape, and the default stays full for every other consumer.
  • Size: ~339 production lines (acp-bridge engine/bridge, serve route, SDK, WebUI) vs ~953 test lines and 10 lines of design-doc updates. Cross-package, but well under the maintainer-awareness thresholds.
  • Approach: matches the minimal shape. Load-time filtering provably can't recover root events the full journal's own cap already evicted, so a separately bounded summary journal at ingest time is the correct mechanism. The one directional coalesce exception (summary load sharing an in-flight full restore) is scoped and serves the exact refresh-during-restore case this PR targets.
  • Risk: no elevated signals — no high-risk-path matches in the changed files.

Moving on to code review. 🔍

中文说明

在当前 head 上重跑。上一轮审查的是 438957db + 8c72bd2,此后 autofix 循环推送了三个响应评审的提交(839e6f5a51f12015c17529c);本轮从头重新审查 c17529c

  • **模板:**完整 ✓
  • **问题:**已观测到,不是理论问题。live replay journal 在写入时受限(默认 10,000 事件 / 8 MiB),而高频 subagent 轮次会用 Web Shell 主会话根本不渲染的嵌套帧把它填满——于是轮次进行中的刷新只会收到截断标记,直到本轮结束。该机制在 base 代码中可以确认,maintainer 已在真实本地环境复现故障并验证修复(见本线程的验证说明)。
  • **方向:**对齐。Web Shell 主会话本来就按 summary 模式投影;让 live replay 投影与客户端实际渲染一致是正确的形态,且其他所有消费方默认仍是 full
  • **规模:**约 339 行生产代码(acp-bridge 引擎/bridge、serve 路由、SDK、WebUI),约 953 行测试,10 行设计文档更新。跨包但远低于需维护者关注的阈值。
  • **方案:**符合最小形态。load 时过滤无法找回已被 full journal 自身上限逐出的根事件,因此在写入时维护独立受限的 summary journal 是正确机制。唯一的单向 coalesce 例外(summary load 共享在途 full restore)范围明确,正是本 PR 要解决的"restore 期间刷新"场景。
  • **风险:**无升级信号——改动文件未命中任何高风险路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

Independent proposal first: a load-time filter can't recover root events the full journal's own cap already evicted, so the minimal shape is a separately bounded projection journal maintained at ingest time. The PR matches it — and this head also completes the part that blocked my last pass.

The previous blocker is resolved. Commit 2's coalesce path — a summary load sharing an in-flight full restore — shipped documented-but-unimplemented at the head I last reviewed. At this head it is fully implemented in the waiter branch: the waiter recomputes its own-mode replay fields from the registered entry (never reusing or filtering down the owner's projection), re-asserts attachability after the recompute await, and rolls back both the coalesce reservation and the attach counter on failure — exactly the R3-7 race, now pinned by a dedicated regression test that kills the channel mid-recompute and expects SessionNotFoundError with a zero session count. I also audited the merge: the waiter's fields are spread last over the owner's result, and replayFieldsFor's return set covers every replay-derived response field, so no owner-mode data leaks through.

The retention rule provably matches the consumer. The summary journal keeps root frames, lifecycle/tool frames, and nested usage frames — and I checked the predicate against the UI rather than taking the doc's word: the SDK normalizer emits assistant.usage only when inputTokens or outputTokens is numeric (the engine's check is marginally wider — it doesn't require finiteness — which errs in the safe direction of retaining), normalizeToolUpdate's self-parent guard is mirrored so a self-parented frame stays root in both projections, and projectMainTranscriptEvents keeps exactly the nested assistant.usage events the journal retains.

Boundaries are validated at every layer. The REST route 400s invalid values on both actions but forwards the mode only to load; the bridge validates before creating a channel and coerces resume to full; the SDK omits the field from resume wire bodies; all three WebUI request sites are gated to load + summary transcript mode. Defaults stay full everywhere, so /acp and other SDK consumers are untouched. The 2× journal-heap tradeoff (shared caps, two journals) is honestly documented at every place the caps are consumed, including the growth pool and the session diagnostic.

The round-4 /review findings (R4-1…R4-7) are all Suggestions — test-coverage gaps, not defects: the usage-retention test only exercises the both-fields case, resume-coerces-to-full has no paired bridge-level test, the no-page existing-entry attach site is the one untested projection call site, and the reconnect branch lacks its own coverage. None block merge; the takeover loop can pick them up if the label stays.

Files changed (17)
File What changed
packages/acp-bridge/src/compactionEngine.ts dual full/summary journal state, per-journal eviction, markers, anchors, growth breach
packages/acp-bridge/src/bridge.ts mode plumbing, validation, directional coalesce exception, waiter recompute + rollback
packages/acp-bridge/src/eventBus.ts LiveReplayMode type, snapshotReplay forwards the mode
packages/acp-bridge/src/bridgeTypes.ts optional load-only request field, diagnostic doc note
packages/acp-bridge/src/replayWindowLimits.ts 2x memory-ceiling note on the shared caps
packages/acp-bridge/src/journalGrowthPolicy.ts documents ~2x retained heap vs charged growth
packages/acp-bridge/src/daemon-memory-budget.ts sizing note: double the journal term
packages/cli/src/serve/routes/session.ts parseLiveReplayMode: 400 on invalid, forward on load only
packages/sdk-typescript/src/daemon/DaemonClient.ts optional field, sent only on load
packages/webui/src/daemon/session/DaemonSessionProvider.tsx three request sites gated to load + summary mode
docs/design/live-journal-truncation-recovery.md design updated for dual journals + coalesce rule
packages/acp-bridge/src/bridge.test.ts +594: selection, coalesce arms, fences, races, channel death
packages/acp-bridge/src/compactionEngine.test.ts +197: independent caps, retention, anchors, growth
packages/cli/src/serve/server.test.ts +84: route validation and resume non-forwarding
packages/sdk-typescript/test/unit/DaemonClient.test.ts wire-body assertions, resume omission
packages/webui/src/daemon/session/DaemonSessionProvider.test.tsx request-site assertions incl. reconnect
packages/acp-bridge/src/eventBus.test.ts default-full + mode forwarding

Testing evidence (this run: CI signal via API, PR code never executed)

All checks on this head are settled — nothing pending, nothing failed. Test (ubuntu-latest, Node 22.x) (full unit suite) is green, and the behavioral surface has real coverage beyond it: Serve A/B reports no response changes against base across its scenarios (the default-path compatibility claim), web-shell E2E Smoke and Real daemon E2E are green, and the SDK Java matrix (3 OS × 3 JDK) passed. The skipped legs are environmental, not PR-caused: Integration Tests (CLI, No Sandbox) skipped on a workflow condition (no job log exists — conditional skip), and the macOS/Windows unit legs were skipped per the suite's gating.

Check Conclusion
Test (ubuntu-latest, Node 22.x) ✅ success
Test (macos-latest, Node 22.x) ⏭️ skipped
Test (windows-latest, Node 22.x) ⏭️ skipped
Integration Tests (CLI, No Sandbox) ⏭️ skipped
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success
Serve A/B (ubuntu-latest, Node 22.x) ✅ success
Real daemon E2E / Java 11 ✅ success
SDK Java (3 OS × Java 11/17/21) ✅ success
Desktop Shell (ubuntu-22.04 / windows-2022) ✅ success
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success

The refresh-recovery claim is behavioral. The new regression tests pin the mechanism (journal divergence under cap pressure, marker non-inheritance, waiter re-projection, the channel-death race), and the prior head passed a full sandboxed verification plus the maintainer's real-stack run — but neither was executed against this exact head (the delta since is review-response commits). Sandboxed verification would settle the current head end-to-end: @qwen-code /verify — that a summary load under cap pressure actually restores the root transcript marker-free on c17529c is asserted by tests here, not yet observed on this commit.

中文说明

代码审查

先写独立方案:load 时过滤无法找回已被 full journal 自身上限逐出的根事件,因此最小形态是在写入时维护一个独立受限的投影 journal。PR 与之一致——并且本 head 补全了上一轮被我挡下的部分。

此前的阻塞项已解决。 提交 2 的 coalesce 路径(summary load 共享在途 full restore)在我上次审查的 head 上只有文档承诺、没有实现。在本 head 上已完整实现:waiter 从已注册的 entry 重新计算自己模式的 replay 字段(绝不复用或降级 owner 的投影),在 recompute 的 await 之后重新断言可挂载性,失败时回滚 coalesce 预留与 attach 计数——正是 R3-7 的竞争,现在有专门的回归测试钉住(recompute 中途杀掉 channel,期望 SessionNotFoundError 且会话数为零)。我还审计了合并语义:waiter 字段最后展开覆盖 owner 结果,且 replayFieldsFor 的返回集覆盖所有 replay 派生响应字段,owner 模式的数据不会泄漏。

保留规则与消费方可证明地一致。 我没有只看文档,而是对照 UI 核验了谓词:SDK normalizer 只在 inputTokensoutputTokens 为数字时发出 assistant.usage(引擎判断略宽——不要求有限数——属于"多留不少丢"的安全方向);normalizeToolUpdate 的自引用守卫被镜像,自父帧在两个投影中都按根处理;projectMainTranscriptEvents 保留的恰是 journal 保留的嵌套 assistant.usage 事件。

每一层边界都有校验。 REST 路由对两种 action 都在非法值时返回 400,但只把模式转发给 load;bridge 在创建 channel 前校验并把 resume 强制为 full;SDK 的 resume 请求体不带该字段;WebUI 三处请求点都限定在 load + summary 转录模式。所有默认值保持 full/acp 与其他 SDK 消费方不受影响。2 倍 journal 堆的取舍(共享上限、两份 journal)在每个消费上限的位置都有如实记录,包括增长池与会话诊断。

第 4 轮 /review 的发现(R4-1…R4-7)全部是 Suggestion——测试覆盖缺口而非缺陷。均不阻塞合并;takeover 循环可按需认领。

测试证据(本次运行:通过 API 读取 CI 信号,从未执行 PR 代码)

本 head 的所有检查已结束——无 pending、无失败。单元测试全套(ubuntu)为绿;行为面还有 Serve A/B(默认路径兼容性,无响应差异)、web-shell E2E SmokeReal daemon E2E 与 SDK Java 矩阵(3 OS × 3 JDK)。跳过的腿是环境原因而非 PR 造成:Integration Tests (CLI, No Sandbox) 因 workflow 条件跳过(无任务日志——条件跳过),macOS/Windows 单元测试腿按套件门控跳过。

刷新恢复是行为性声明:新的回归测试钉住了机制,且先前 head 已通过完整沙箱验证与 maintainer 真实环境验证——但两者都不是在本 head 上执行。沙箱验证可以在当前 head 上端到端确认:@qwen-code /verify

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — the thing that blocked my last pass is now genuinely implemented and test-pinned, the mechanism verifies against the actual UI consumer, and CI is fully green on this head; what keeps this from a 5 is a set of open test-coverage suggestions and an integration leg that never runs in CI.

Stepping back: my independent proposal for this problem was a separately bounded projection journal at ingest time — load-time filtering provably can't recover root events the full journal already evicted — and that's exactly what shipped. The problem is real and was reproduced on a real stack by the maintainer, not inferred from the code. Every file in the diff maps to the mechanism; there's no drive-by churn. The part I pushed back on last time — the coalesce exception — is the most intricate piece of the PR, and it's also the one that was rebuilt most carefully: own-mode recompute, post-await re-assert, counter rollback on every failure arm, and a regression test for the exact channel-death race the round-3 review caught. If I have to maintain this in six months, the dual-journal state is a clean LiveJournalState record, the mode is explicit at every boundary, and the 2× memory cost is documented where operators will look for it — I'd thank the author, not curse them.

Reservations, named: the round-4 suggestions are real gaps (usage retention tested only for the both-fields case, resume-coerces-to-full untested at the bridge level, one projection call site uncovered) — none is a defect, and I'd rather land the fix and let the takeover loop backfill coverage. The behavioral claim on this exact commit rests on the regression tests plus the prior head's sandboxed and real-stack verification; @qwen-code /verify on the current head would close that last inch, and a maintainer can trigger it if they want it before merge.

Verdict: approve — all stages clean at this head, no escalation grounds, CI settled green.

中文说明

置信度:4/5 —— 上一轮挡下我的问题这次是真正实现了,并且有测试钉住;机制对照实际 UI 消费方核验通过;本 head 的 CI 全绿。没到 5 分的原因是还有一组未闭环的测试覆盖建议,以及一条在 CI 中从不运行的集成腿。

退一步看:我对这个问题的独立方案就是写入时维护独立受限的投影 journal——load 时过滤无法找回已被逐出的根事件——而 PR 交付的正是这个形态。问题真实存在,由 maintainer 在真实环境复现,不是从代码推断出来的。diff 里每个文件都对应机制本身,没有顺手夹带的改动。我上次反对的部分——coalesce 例外——是 PR 里最复杂的片段,也是重构最仔细的片段:按自身模式重算、await 之后重新断言、每条失败路径都回滚计数,并为第 3 轮评审抓到的 channel-death 竞争配了回归测试。六个月后维护这段代码:双 journal 状态是干净的 LiveJournalState 记录,模式在每个边界都显式传递,2 倍内存代价写在运维者会查的地方——我会感谢作者。

保留意见,点名:第 4 轮建议是真实的覆盖缺口(usage 保留只测了双字段情形、resume 强制 full 在 bridge 层无测试、有一个投影调用点未覆盖)——都不是缺陷,我更倾向先合入修复、由 takeover 循环补齐覆盖。本提交上的行为性声明依赖回归测试加上先前 head 的沙箱与真实环境验证;在当前 head 上跑一次 @qwen-code /verify 可以闭上最后一环,maintainer 如需要可在合并前触发。

结论:批准——本 head 各阶段干净,无需升级,CI 已全绿。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

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

Screenshots · before / after

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

  • packages/webui/src/daemon/session/DaemonSessionProvider.tsx

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

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

Qwen Code · web-shell visuals

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

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

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

Qwen Code · serve A/B

private journalTruncatedEvents = 0;
private liveJournalTextSegment: LiveJournalTextSegment | undefined;
private fullJournal = createLiveJournalState();
private summaryJournal = createLiveJournalState();

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.

Live-journal memory ceiling per session doubles (and the second journal is not "small").

summaryJournal is appended and evicted through the same appendLiveJournal with the same this.maxJournalEvents / this.maxJournalBytes caps as fullJournal, so a single session can now retain up to 2 × maxJournalBytes (16 MiB by default) and 2 × maxJournalEvents (20 000 entries) for one in-flight turn.

Concrete scenario: a long turn with heavy nested subagent output. The full journal's window fills with recent nested events, while the summary journal independently holds a window of much older root events that the full journal has already evicted — those BridgeEvent objects stay pinned instead of being collected. Operators sizing daemon memory from maxJournalBytes × live sessions are now off by 2×. Sessions with no subagents at all pay the extra bookkeeping window for a journal that is a strict duplicate of the full one.

Worth either deriving the summary caps from the full ones (e.g. a fraction), or documenting the new 2× ceiling in replayWindowLimits / the design doc.

if (event.type !== 'session_update') return true;
const data = event.data as SessionUpdateData | undefined;
const meta = data?.update?._meta;
if (extractParentToolCallIdFromMeta(meta) === undefined) return true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Missing the normalizer's self-parent guard, so a self-referencing tool frame is visible live but disappears after a summary refresh.

This predicate is the daemon-side mirror of projectMainTranscriptEvents in DaemonSessionProvider.tsx, which filters on the normalized UI event's parentToolCallId. But normalizeToolUpdate (packages/sdk-typescript/src/daemon/ui/normalizer.ts) deliberately drops a self-referencing parent:

// Self-reference guard: defensively drop `parentToolCallId === toolCallId`.
const parentToolCallId =
  rawParentToolCallId && rawParentToolCallId !== toolCallId
    ? rawParentToolCallId
    : undefined;

So for a tool_call / tool_call_update whose _meta.parentToolCallId equals its own toolCallId, the UI treats the frame as a root tool block and renders it in the main transcript, while isSummaryLiveJournalEvent sees a non-empty parentToolCallId and a non-agent_message_chunk kind and returns false — the frame never enters the summary journal.

Scenario: such a frame arrives mid-turn, the user sees the tool block, then refreshes Web Shell. The summary replay omits it, so a tool block that was on screen a second ago is gone from the restored transcript until the turn completes and persisted history takes over. Mirroring the guard here (parentToolCallId === data.update.toolCallId → treat as root) keeps the two projections in sync.


## Protocol and SDK

The compaction engine maintains independently bounded `full` and `summary` live journals. Both share the completed-turn compaction and event high-water mark. The full journal retains every update. The summary journal excludes `session_update` frames carrying a non-empty `_meta.parentToolCallId`, while retaining root updates and all non-session events.

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.

Design doc contradicts the implementation on the nested-usage carve-out.

This sentence says the summary journal "excludes session_update frames carrying a non-empty _meta.parentToolCallId", full stop. The implementation deliberately does not: isSummaryLiveJournalEvent re-admits nested agent_message_chunk frames whose _meta.usage carries a numeric inputTokens/outputTokens, because the main transcript consumes them (projectMainTranscriptEvents keeps assistant.usage events even when parentToolCallId is set, and extractAssistantUsage requires exactly those fields).

That carve-out is load-bearing: without it, refreshing mid-turn silently drops all subagent token accounting from the main conversation's usage totals. Since this file is the stated design reference, someone "simplifying" the predicate to match the doc would reintroduce that bug with no test naming the doc as the source of truth. Please state the usage exception here (the PR description already does).

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 84.16% 84.16% 90.01% 83.36%
Core 87.92% 87.92% 89.45% 86.45%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   84.16 |    83.36 |   90.01 |   84.16 |                   
 src               |   85.27 |    81.44 |   87.61 |   85.27 |                   
  cli.ts           |   95.68 |    84.11 |     100 |   95.68 | ...60-561,565-566 
  gemini.tsx       |   73.75 |    79.33 |   80.76 |   73.75 | ...1319-1323,1450 
  ...ractiveCli.ts |   87.19 |    81.33 |   88.13 |   87.19 | ...2972,2978,3043 
  ...liCommands.ts |   88.64 |    82.83 |      80 |   88.64 | ...77-579,593,692 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   71.65 |    73.85 |   91.22 |   71.65 |                   
  acpAgent.ts      |   71.02 |    73.64 |   90.74 |   71.02 | ...20,12325-12327 
  ...k-reporter.ts |     100 |    80.95 |     100 |     100 | 77,80,115,135     
  authMethods.ts   |      92 |       60 |     100 |      92 | 33-34             
  errorCodes.ts    |     100 |      100 |     100 |     100 |                   
  ...ion-skills.ts |     100 |    88.23 |     100 |     100 | 17,32             
  generation.ts    |    97.1 |    81.25 |     100 |    97.1 | 109,112           
  ...figuration.ts |     100 |      100 |     100 |     100 |                   
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |    97.1 |    95.83 |   93.33 |    97.1 |                   
  filesystem.ts    |    97.1 |    95.83 |   93.33 |    97.1 | ...22-123,246-247 
 ...ration/session |   91.23 |    86.48 |   96.48 |   91.23 |                   
  Session.ts       |   90.35 |    84.88 |   95.79 |   90.35 | ...81,11408-11412 
  ...entTracker.ts |    96.8 |    89.36 |      90 |    96.8 | 137-143,221       
  ...projection.ts |   98.85 |    91.59 |     100 |   98.85 | 234,250,262       
  ...stop-guard.ts |     100 |    98.07 |     100 |     100 | 37,127            
  ...eplay-page.ts |   93.38 |    91.74 |     100 |   93.38 | 74,85-88,115-125  
  ...y-replayer.ts |   98.22 |    98.14 |     100 |   98.22 | 195-197           
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   89.76 |    87.32 |     100 |   89.76 | ...54-270,326-328 
  ...lure-guard.ts |   98.32 |    97.75 |     100 |   98.32 | 294-295,340-341   
  tasksSnapshot.ts |    94.3 |     87.5 |     100 |    94.3 | 65-71             
  ...on-tracker.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ssion/emitters |   96.04 |    93.93 |   96.87 |   96.04 |                   
  ...ageEmitter.ts |   96.03 |    95.08 |     100 |   96.03 | 71,108-115        
  PlanEmitter.ts   |     100 |       90 |     100 |     100 | 66                
  base-emitter.ts  |   78.26 |       75 |     100 |   78.26 | 23-24,26-28       
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
  ...ll-emitter.ts |   99.18 |    96.47 |     100 |   99.18 | 355-356           
 ...ession/rewrite |    91.8 |    89.13 |   94.44 |    91.8 |                   
  LlmRewriter.ts   |    82.4 |     86.2 |     100 |    82.4 | ...,88-89,166-170 
  ...Middleware.ts |   96.96 |    88.09 |     100 |   96.96 | 144,152-154       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/agent-view    |   89.03 |    81.37 |   89.09 |   89.03 |                   
  ...t-cli-argv.ts |     100 |      100 |     100 |     100 |                   
  protocol.ts      |     100 |      100 |     100 |     100 |                   
  ...sor-client.ts |   80.38 |    72.54 |   76.66 |   80.38 | ...22-626,652-656 
  ...or-process.ts |   96.61 |    89.47 |   84.61 |   96.61 | 129-130,150-151   
  ...sor-runner.ts |    84.9 |     75.6 |      85 |    84.9 | ...44,468,471-481 
  ...sor-server.ts |   85.71 |    83.06 |   95.45 |   85.71 | ...67-468,471-488 
  ...isor-store.ts |   97.73 |    81.16 |     100 |   97.73 | ...92,594,607,643 
  ...nal-bridge.ts |   93.98 |     91.3 |   83.33 |   93.98 | 228-238           
 src/commands      |   90.96 |    80.09 |   66.66 |   90.96 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   55.55 |      100 |       0 |   55.55 | 18-22,30-40       
  extensions.tsx   |   96.77 |      100 |      50 |   96.77 | 39                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   95.45 |      100 |      50 |   95.45 | 31                
  review.ts        |   98.66 |      100 |      50 |   98.66 | 86                
  serve.ts         |   90.08 |    77.96 |     100 |   90.08 | ...81,884-887,899 
  sessions.ts      |     100 |      100 |      50 |     100 |                   
  update.ts        |   98.13 |    94.44 |   66.66 |   98.13 | 82-83             
 ...mmands/channel |   88.95 |    88.56 |   90.59 |   88.95 |                   
  channel-cwd.ts   |     100 |      100 |     100 |     100 |                   
  ...l-registry.ts |   94.11 |    95.45 |   88.88 |   94.11 | ...54-257,302-305 
  ...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.91 |    85.61 |   94.33 |   93.91 | ...1264,1271-1272 
  loop-runtime.ts  |   91.66 |      100 |      50 |   91.66 | 15,22             
  ...classifier.ts |   98.53 |    96.66 |     100 |   98.53 | 115-116,161       
  ...tact-store.ts |   93.51 |    87.65 |     100 |   93.51 | ...71,288-289,337 
  pairing.ts       |      75 |      100 |      50 |      75 | 22-28,59-70       
  pidfile.ts       |   95.55 |       90 |     100 |   95.55 | ...50-251,315-316 
  proxy.ts         |     100 |      100 |     100 |     100 |                   
  reload.ts        |    77.5 |    86.95 |      75 |    77.5 | 72-84,93-97       
  runtime.ts       |   82.43 |    86.44 |     100 |   82.43 | ...87-191,251-253 
  set.ts           |   75.72 |    85.71 |      50 |   75.72 | 65-83,111-116     
  start.ts         |    85.8 |    82.17 |      88 |    85.8 | ...85,591-594,606 
  ...ure-format.ts |   93.65 |    82.45 |     100 |   93.65 | ...42,48-49,74-75 
  status.ts        |   78.57 |    59.25 |   66.66 |   78.57 | ...36-137,150-161 
  stop.ts          |   57.83 |    82.35 |      50 |   57.83 | ...3,74-76,85-111 
 ...nds/extensions |   88.85 |    87.73 |   87.09 |   88.85 |                   
  consent.ts       |   72.53 |    90.32 |   42.85 |   72.53 | ...86-142,157-163 
  disable.ts       |     100 |       90 |     100 |     100 | 30                
  enable.ts        |     100 |    91.66 |     100 |     100 | 38                
  install.ts       |   82.95 |    81.57 |      75 |   82.95 | ...96-199,202-211 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |     87.5 |     100 |     100 | 18                
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  sources.ts       |   93.42 |    87.09 |   92.85 |   93.42 | ...4-66,96-98,167 
  uninstall.ts     |   74.57 |       40 |   66.66 |   74.57 | 45-47,60-67,70-73 
  update.ts        |   96.71 |    97.05 |     100 |   96.71 | 114-118           
  utils.ts         |   75.63 |    55.55 |     100 |   75.63 | ...30-134,136-140 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 ...amples/starter |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-64              
 src/commands/mcp  |   90.31 |    84.61 |   83.33 |   90.31 |                   
  add.ts           |    99.3 |    96.07 |     100 |    99.3 | 154-155           
  approve.ts       |   76.19 |     87.5 |   66.66 |   76.19 | ...,89-99,114-124 
  list.ts          |   93.15 |    84.84 |      80 |   93.15 | ...78-180,198-199 
  reconnect.ts     |   78.85 |    66.66 |   85.71 |   78.85 | 42-55,169-191     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   88.08 |    88.28 |   88.72 |   88.08 |                   
  agent-prompt.ts  |   93.73 |     92.4 |   97.22 |   93.73 | ...2524,2649-2729 
  base-tree.ts     |   76.16 |    80.76 |   77.77 |   76.16 | ...50-371,373-386 
  capture-local.ts |   68.57 |     90.9 |      75 |   68.57 | 107-111,158-189   
  ...k-coverage.ts |   50.71 |       35 |   66.66 |   50.71 | ...40-245,279-289 
  cleanup.ts       |   89.12 |    82.22 |   83.33 |   89.12 | ...99-504,506-507 
  ...ent-status.ts |   93.03 |    83.87 |   83.33 |   93.03 | 291,531-551       
  ...ose-review.ts |   97.02 |    93.28 |   96.55 |   97.02 | ...2224,2252-2274 
  cost-ledger.ts   |   94.67 |    95.86 |   78.57 |   94.67 | ...04-505,545-555 
  drive.ts         |   76.07 |    85.71 |   81.81 |   76.07 | ...90-492,497-499 
  extract-step.ts  |   91.36 |    90.62 |   88.88 |   91.36 | ...90-707,714-729 
  fetch-pr.ts      |    76.7 |    68.75 |   63.63 |    76.7 | ...95,417,450-455 
  findings.ts      |   89.89 |    89.56 |   95.65 |   89.89 | ...77-980,989-990 
  load-rules.ts    |   26.41 |      100 |   16.66 |   26.41 | ...41-153,155-156 
  match-remote.ts  |   85.54 |     92.3 |   66.66 |   85.54 | 67-72,131-136     
  mock-provider.ts |   95.44 |    90.25 |   89.47 |   95.44 | 145,690-709       
  parse-args.ts    |    99.7 |    96.96 |     100 |    99.7 | 458               
  plan-diff.ts     |   64.04 |      100 |   66.66 |   64.04 | 127-163           
  pr-context.ts    |   81.77 |    81.32 |   92.85 |   81.77 | ...1043,1072-1074 
  presubmit.ts     |   87.93 |       88 |   88.88 |   87.93 | ...98-599,676-706 
  ...ish-assets.ts |   80.72 |    82.35 |   85.71 |   80.72 | ...58-462,489-535 
  repo-context.ts  |   94.92 |    90.82 |     100 |   94.92 | ...67-368,376-377 
  ...ve-anchors.ts |   77.77 |    88.88 |      75 |   77.77 | ...77-182,194-211 
  run.ts           |   82.16 |    87.12 |   91.66 |   82.16 | ...52,468-516,529 
  save-artifact.ts |    89.9 |    81.81 |   94.11 |    89.9 | ...08-311,404-407 
  script-lint.ts   |   83.67 |    78.41 |   88.88 |   83.67 | ...59-773,775-797 
  submit.ts        |   85.01 |    86.36 |      90 |   85.01 | ...95,584,611-647 
  test-delta.ts    |   87.13 |    91.46 |      75 |   87.13 | 206-237,477-485   
  test-efficacy.ts |   88.04 |    84.12 |   95.45 |   88.04 | ...2602,2610-2630 
  test-plan.ts     |   91.44 |    91.39 |   89.47 |   91.44 | ...38-839,903-920 
 ...w/__fixtures__ |     100 |      100 |     100 |     100 |                   
  ...r-default.mjs |     100 |      100 |     100 |     100 |                   
  ...der-empty.mjs |     100 |      100 |     100 |     100 |                   
  ...der-named.mjs |     100 |      100 |     100 |     100 |                   
 ...nds/review/lib |   97.52 |    95.17 |   98.33 |   97.52 |                   
  agent-briefs.ts  |   98.98 |      100 |      50 |   98.98 | 739-740           
  anchors.ts       |     100 |    94.79 |     100 |     100 | ...33,169,178,225 
  assets.ts        |     100 |      100 |     100 |     100 |                   
  audit-layers.ts  |   98.67 |    96.15 |     100 |   98.67 | 277-279           
  authorization.ts |   92.85 |    93.75 |     100 |   92.85 | 144-150           
  budget.ts        |     100 |    97.14 |     100 |     100 | 513,553           
  coverage.ts      |   96.81 |    94.42 |     100 |   96.81 | ...85-486,526-537 
  deadline.ts      |   98.33 |    93.61 |     100 |   98.33 | ...88,237,629,661 
  diff-flags.ts    |     100 |        0 |     100 |     100 | 63                
  diff-plan.ts     |   98.73 |    93.01 |     100 |   98.73 | ...41,264,290-291 
  disk.ts          |     100 |      100 |     100 |     100 |                   
  effort.ts        |     100 |      100 |     100 |     100 |                   
  gh.ts            |   87.07 |    92.45 |   76.47 |   87.07 | ...72,309-310,337 
  git.ts           |   97.64 |    95.65 |     100 |   97.64 | 180-181           
  heavy.ts         |     100 |      100 |     100 |     100 |                   
  inline-counts.ts |     100 |      100 |     100 |     100 |                   
  ...audit-gate.ts |     100 |    96.15 |     100 |     100 | 110               
  ledger.ts        |     100 |      100 |     100 |     100 |                   
  local-diff.ts    |   84.86 |    90.38 |     100 |   84.86 | ...63-473,475-483 
  ...ry-context.ts |   96.61 |    95.51 |     100 |   96.61 | ...47-450,496-499 
  merge-base.ts    |     100 |      100 |     100 |     100 |                   
  npm-toolchain.ts |   97.36 |    95.37 |     100 |   97.36 | ...86,409,770,787 
  path-rules.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |     100 |     87.5 |     100 |     100 | 92                
  prompt-record.ts |   97.88 |    93.87 |     100 |   97.88 | 260-261,267       
  receipt.ts       |     100 |      100 |     100 |     100 |                   
  remote-match.ts  |   97.26 |    91.42 |     100 |   97.26 | 49-50             
  report.ts        |   94.68 |    93.75 |     100 |   94.68 | 189-193           
  ...ry-context.ts |     100 |    98.66 |     100 |     100 | 184               
  retirement.ts    |     100 |    92.39 |     100 |     100 | ...28,308-309,449 
  review-footer.ts |     100 |      100 |     100 |     100 |                   
  ...w-settings.ts |     100 |      100 |     100 |     100 |                   
  roster.ts        |     100 |    95.71 |     100 |     100 | 145,163,208       
  shell-quote.ts   |     100 |      100 |     100 |     100 |                   
  stale-bundle.ts  |   98.11 |    94.11 |     100 |   98.11 | 416,457,497-498   
  test-utils.ts    |     100 |      100 |     100 |     100 |                   
  toolchain.ts     |     100 |      100 |     100 |     100 |                   
  transcripts.ts   |   96.59 |    94.56 |     100 |   96.59 | ...08,297-298,323 
  ...pace-scope.ts |     100 |    96.96 |     100 |     100 | 172               
  workspaces.ts    |     100 |    96.77 |     100 |     100 | 222,452,499,512   
  worktree.ts      |     100 |      100 |     100 |     100 |                   
 ...mands/sessions |   91.56 |    86.95 |   83.33 |   91.56 |                   
  common.ts        |     100 |      100 |     100 |     100 |                   
  list.ts          |   90.96 |    86.66 |   81.81 |   90.96 | 208-219,221-222   
 src/config        |   94.92 |    89.85 |   96.27 |   94.92 |                   
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   89.35 |    83.56 |     100 |   89.35 | ...97-298,314-315 
  ...eMcpImport.ts |   87.91 |    81.52 |     100 |   87.91 | ...63-371,453-454 
  compile-cache.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   88.93 |    88.59 |   83.33 |   88.93 | ...2451,2453-2461 
  ...cy-monitor.ts |   88.75 |    76.19 |     100 |   88.75 | ...3,90-92,98,101 
  ...ust-policy.ts |   83.02 |    88.88 |     100 |   83.02 | ...02-209,232-240 
  ...heme-names.ts |     100 |      100 |     100 |     100 |                   
  environment.ts   |    96.5 |    93.61 |      95 |    96.5 | ...85-586,640-641 
  ...le-watcher.ts |   90.86 |    83.65 |   95.83 |   90.86 | ...23-325,370,418 
  ...resh-state.ts |   90.57 |    97.29 |   93.75 |   90.57 | 137-142,146-152   
  ...ime-reload.ts |     100 |    69.69 |     100 |     100 | ...12-113,122-123 
  hot-reload.ts    |     100 |    89.13 |     100 |     100 | 47,172-178,238    
  keyBindings.ts   |    97.4 |       50 |     100 |    97.4 | 240-243           
  ...ngsAdapter.ts |     100 |    94.11 |     100 |     100 | 64                
  ...ig-watcher.ts |   95.17 |    83.05 |     100 |   95.17 | ...78,200,292-293 
  ...er-secrets.ts |   98.97 |    96.87 |     100 |   98.97 | 85                
  mcpApprovals.ts  |   96.55 |    95.55 |     100 |   96.55 | 223-224,229-231   
  mcpJson.ts       |     100 |      100 |     100 |     100 |                   
  mcpServers.ts    |   92.85 |     87.5 |     100 |   92.85 | 46-47             
  ...idersScope.ts |      95 |    94.73 |     100 |      95 | 11-12             
  ...abledTools.ts |     100 |      100 |     100 |     100 |                   
  ...comparison.ts |     100 |      100 |     100 |     100 |                   
  ...n-settings.ts |   99.15 |    93.75 |     100 |   99.15 | 63                
  sandboxConfig.ts |   93.33 |    93.33 |     100 |   93.33 | ...42-147,216-217 
  session-id.ts    |     100 |      100 |     100 |     100 |                   
  ...ings-cache.ts |   96.52 |    93.93 |     100 |   96.52 | 90-91,201-202     
  settings.ts      |   91.27 |    92.64 |      90 |   91.27 | ...1030,1032-1033 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...ngsWatcher.ts |   95.54 |    88.34 |     100 |   95.54 | ...28,277-278,293 
  ...d-env-keys.ts |     100 |      100 |     100 |     100 |                   
  ...l-settings.ts |     100 |      100 |     100 |     100 |                   
  ...paths-lite.ts |   89.47 |       88 |     100 |   89.47 | 43-44,53-54,56-57 
  ...precedence.ts |   98.79 |     92.3 |     100 |   98.79 | 62                
  ...tedFolders.ts |   92.53 |    93.47 |     100 |   92.53 | ...36-337,373-384 
 ...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    |   75.08 |    67.64 |   71.42 |   75.08 |                   
  ...tputBridge.ts |   75.33 |    68.18 |   73.68 |   75.33 | ...09-410,418-421 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/hooks         |     100 |      100 |     100 |     100 |                   
  ...elete-hook.ts |     100 |      100 |     100 |     100 |                   
 src/i18n          |   85.98 |    81.92 |   89.65 |   85.98 |                   
  index.ts         |   73.45 |    77.77 |      90 |   73.45 | ...70-271,294-299 
  languages.ts     |   93.07 |     92.3 |   85.71 |   93.07 | ...35,164-169,184 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   80.98 |    77.27 |   84.12 |   80.98 |                   
  session.ts       |   84.97 |    76.31 |   96.07 |   84.97 | ...1048,1057-1067 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...31-632,635-636 
 ...active/control |   75.54 |    89.83 |      80 |   75.54 |                   
  ...rolContext.ts |    6.06 |        0 |       0 |    6.06 | 57-99             
  ...Dispatcher.ts |   91.95 |    92.98 |   88.88 |   91.95 | ...54-372,392,395 
  ...rolService.ts |    6.89 |        0 |       0 |    6.89 | 46-188            
 ...ol/controllers |   45.95 |    69.03 |   55.26 |   45.95 |                   
  ...Controller.ts |    42.4 |      100 |   83.33 |    42.4 | 101-105,140-223   
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |   55.01 |    67.14 |   58.33 |   55.01 | ...15-624,639-644 
  ...Controller.ts |   49.23 |       60 |      50 |   49.23 | ...07-108,111-121 
  ...Controller.ts |   40.64 |    68.11 |   46.66 |   40.64 | ...72-684,693-722 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   98.12 |    94.18 |   95.29 |   98.12 |                   
  ...putAdapter.ts |   97.98 |    93.23 |   98.07 |   97.98 | ...1416,1432-1433 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.49 |      100 |   90.47 |   98.49 | 85-86,126-127     
  ...projection.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   87.31 |    75.32 |   88.23 |   87.31 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.01 |       76 |   93.33 |   88.01 | ...49-350,361-364 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/runtime       |   99.61 |    95.04 |     100 |   99.61 |                   
  ...livery-ipc.ts |     100 |     90.9 |     100 |     100 | 94,106,134        
  ...l-delivery.ts |     100 |      100 |     100 |     100 |                   
  cpu-percent.ts   |     100 |      100 |     100 |     100 |                   
  ...erver-name.ts |     100 |      100 |     100 |     100 |                   
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...-summaries.ts |   86.66 |       50 |     100 |   86.66 | 11,19             
  ...ber-errors.ts |     100 |    95.32 |     100 |     100 | 53,93-94,172,192  
  ...ls-mapping.ts |     100 |      100 |     100 |     100 |                   
 src/serve         |   87.62 |    83.89 |   90.52 |   87.62 |                   
  ...tp-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |     100 |      100 |     100 |     100 |                   
  auth.ts          |   93.43 |    92.95 |     100 |   93.43 | ...20-321,324-326 
  ...em-adapter.ts |     100 |      100 |     100 |     100 |                   
  capabilities.ts  |     100 |    98.07 |     100 |     100 | 685               
  ...cp-command.ts |     100 |      100 |     100 |     100 |                   
  ...horization.ts |   92.79 |    93.33 |    87.5 |   92.79 | 75-80,135-136     
  ...op-mcp-ipc.ts |   81.06 |    73.68 |   94.11 |   81.06 | ...37-242,267,289 
  ...nt-service.ts |    94.1 |    86.89 |     100 |    94.1 | ...75-477,484,486 
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...ings-store.ts |   88.59 |    93.65 |   96.29 |   88.59 | ...95-207,451-454 
  ...ebhook-ipc.ts |    98.5 |    86.66 |     100 |    98.5 | 47                
  ...iagnostics.ts |     100 |      100 |     100 |     100 |                   
  ...worker-env.ts |     100 |      100 |     100 |     100 |                   
  ...rker-group.ts |   87.27 |     85.2 |     100 |   87.27 | ...10,816-820,838 
  ...er-manager.ts |   89.39 |    83.88 |   93.33 |   89.39 | ...98,711,722-724 
  ...horization.ts |     100 |      100 |     100 |     100 |                   
  ...tartup-ipc.ts |   97.72 |    96.66 |     100 |   97.72 | 88-89             
  ...supervisor.ts |   92.54 |    84.53 |   97.14 |   92.54 | ...1489,1543-1547 
  ...e-grouping.ts |     100 |    94.28 |     100 |     100 | 71,137            
  core-runtime.ts  |     100 |      100 |     100 |     100 |                   
  ...ub-session.ts |    90.1 |    77.83 |   94.73 |    90.1 | ...1014,1021-1026 
  daemon-logger.ts |    82.2 |    77.42 |   91.76 |    82.2 | ...1720,1747-1753 
  ...y-pressure.ts |     100 |    96.96 |     100 |     100 | 135               
  ...trics-ring.ts |     100 |      100 |     100 |     100 |                   
  ...s-provider.ts |   68.04 |    52.77 |     100 |   68.04 | ...44-249,282-290 
  daemon-status.ts |   98.58 |    90.88 |     100 |   98.58 | ...1438,1440-1441 
  debug-mode.ts    |     100 |      100 |     100 |     100 |                   
  env-snapshot.ts  |   93.37 |    85.18 |     100 |   93.37 | 114-117,195-202   
  ...-scheduler.ts |   87.34 |    83.87 |     100 |   87.34 | 33-36,48-50,79-81 
  ...d-provider.ts |   92.06 |    86.95 |     100 |   92.06 | ...72,287-293,316 
  ...-path-argv.ts |     100 |      100 |     100 |     100 |                   
  ...h-settings.ts |   94.94 |    90.41 |     100 |   94.94 | ...30,708,724,734 
  fast-path.ts     |   90.99 |    81.38 |   95.45 |   90.99 | ...33-542,608-609 
  ...ration-sse.ts |   42.55 |    33.33 |     100 |   42.55 | 23-24,30,33-56    
  health-query.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-144             
  ...e-observer.ts |   89.89 |    83.24 |      96 |   89.89 | ...11-512,541-543 
  ...back-binds.ts |     100 |    88.88 |     100 |     100 | 32                
  ...-workspace.ts |    90.9 |    85.71 |     100 |    90.9 | ...30-131,142-143 
  ...iders-edit.ts |     100 |    82.14 |     100 |     100 | 58-60,65,81       
  ...ory-picker.ts |     100 |    86.95 |     100 |     100 | 36,66,92          
  ...sion-audit.ts |     100 |      100 |   93.33 |     100 |                   
  rate-limit.ts    |   92.68 |    88.29 |     100 |   92.68 | ...89-291,303-305 
  ...qwen-serve.ts |   84.27 |    80.34 |    75.6 |   84.27 | ...7571,7577-7578 
  ...tup-errors.ts |     100 |      100 |     100 |     100 |                   
  ...-keepalive.ts |   94.22 |    87.96 |     100 |   94.22 | ...27,531-532,572 
  ...-lifecycle.ts |     100 |      100 |     100 |     100 |                   
  server.ts        |   90.67 |    91.22 |   71.81 |   90.67 | ...2744,2758-2762 
  ...-admission.ts |   98.24 |    94.73 |     100 |   98.24 | 79-80,303-304     
  ...on-helpers.ts |     100 |      100 |     100 |     100 |                   
  ...t-event-id.ts |     100 |    95.23 |     100 |     100 | 12                
  ...-admission.ts |   98.71 |    89.65 |     100 |   98.71 | 68                
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ion-limits.ts |     100 |      100 |     100 |     100 |                   
  ...t-sessions.ts |   93.72 |    77.93 |     100 |   93.72 | ...51,854,867-869 
  ...l-resolver.ts |   90.32 |    66.66 |     100 |   90.32 | 16,45-46          
  ...ell-static.ts |   92.18 |    88.37 |     100 |   92.18 | ...21-224,267-270 
  ...ace-agents.ts |   66.13 |    70.57 |   92.68 |   66.13 | ...2246,2256-2266 
  ...generation.ts |    95.4 |    82.35 |   66.66 |    95.4 | 55-56,78,92       
  ...-git-state.ts |     100 |    91.93 |    90.9 |     100 | 161,172,202,265   
  ...ace-inputs.ts |     100 |      100 |     100 |     100 |                   
  ...ace-memory.ts |      83 |    74.54 |     100 |      83 | ...30-537,597-604 
  ...ers-status.ts |   98.58 |       79 |     100 |   98.58 | 106,134,174,177   
  ...tion-store.ts |   89.67 |    88.27 |   92.59 |   89.67 | ...91-400,411-414 
  ...e-registry.ts |   93.89 |     87.5 |     100 |   93.89 | ...18-519,525-526 
  ...e-remember.ts |   98.23 |    92.51 |     100 |   98.23 | ...36,340-345,386 
  ...te-runtime.ts |   83.98 |    90.29 |     100 |   83.98 | ...48-156,216-237 
  ...me-storage.ts |     100 |      100 |     100 |     100 |                   
  ...management.ts |   72.63 |    72.72 |      96 |   72.63 | ...88-889,896-900 
  ...lls-status.ts |     100 |    95.45 |     100 |     100 | 152               
  ...reconciler.ts |   91.63 |    84.26 |     100 |   91.63 | ...71-273,306-307 
 ...serve/acp-http |   78.26 |    80.02 |    93.1 |   78.26 |                   
  ...r-registry.ts |   96.92 |    94.87 |     100 |   96.92 | 184-187           
  client-mcp-ws.ts |   54.85 |    58.62 |   72.72 |   54.85 | ...99-300,304-305 
  ...n-registry.ts |    98.2 |    88.55 |     100 |    98.2 | 1015,1041-1052    
  dispatch.ts      |   73.87 |    77.71 |   94.23 |   73.87 | ...5240,5288-5294 
  index.ts         |   82.23 |    80.11 |   91.07 |   82.23 | ...2341,2425-2426 
  json-rpc.ts      |     100 |    96.96 |     100 |     100 | 92                
  safe-ws-send.ts  |   52.94 |    71.42 |     100 |   52.94 | 33-42,47-55       
  sse-stream.ts    |   93.96 |    88.57 |   84.61 |   93.96 | ...57-159,161-163 
  ...ort-stream.ts |       0 |        0 |       0 |       0 | 1                 
  ws-stream.ts     |   91.86 |       80 |     100 |   91.86 | 45,50,96,100-103  
 src/serve/auth    |   86.86 |     79.7 |   93.87 |   86.86 |                   
  device-flow.ts   |   96.35 |    80.57 |   97.61 |   96.35 | ...1358,1453,1519 
  ...w-provider.ts |   44.24 |    74.07 |   71.42 |   44.24 | ...23-284,297,301 
 ...rve/cdp-tunnel |   87.73 |    76.21 |    97.5 |   87.73 |                   
  ...r-emulator.ts |   93.27 |    77.77 |     100 |   93.27 | ...53-256,282-283 
  ...verse-link.ts |      88 |    76.19 |     100 |      88 | ...28-329,420-423 
  ...l-registry.ts |     100 |      100 |     100 |     100 |                   
  cdp-ws.ts        |   76.28 |    61.29 |    87.5 |   76.28 | ...13-217,223-228 
 ...nel/acceptance |    6.12 |    57.89 |   46.15 |    6.12 |                   
  ...helpers.d.mts |       0 |        0 |       0 |       0 | 1                 
  ...e-helpers.mjs |   97.64 |    70.96 |     100 |   97.64 | 22-23             
  ...mcp-smoke.mjs |       0 |        0 |       0 |       0 | 1-124             
  ...cceptance.mjs |       0 |        0 |       0 |       0 | 1-473             
  ...re-server.mjs |       0 |        0 |       0 |       0 | 1-59              
  ...ols-smoke.mjs |       0 |        0 |       0 |       0 | 1-268             
  real-tab.mjs     |       0 |        0 |       0 |       0 | 1-218             
  ...al-chrome.mjs |       0 |        0 |       0 |       0 | 1-223             
 src/serve/fs      |   87.27 |    82.01 |     100 |   87.27 |                   
  audit.ts         |     100 |    96.15 |     100 |     100 | 204               
  errors.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...x-registry.ts |     100 |      100 |     100 |     100 |                   
  paths.ts         |   77.64 |    74.01 |     100 |   77.64 | ...65,594-598,611 
  policy.ts        |   90.52 |    89.18 |     100 |   90.52 | 172-180           
  text-cursor.ts   |   88.23 |       90 |     100 |   88.23 | 74-77,92-95       
  ...ile-system.ts |   87.37 |    81.39 |     100 |   87.37 | ...2811,2821-2822 
 src/serve/live    |   78.01 |    69.52 |   90.61 |   78.01 |                   
  ...en-context.ts |   95.74 |    81.25 |     100 |   95.74 | ...0,66-67,99-100 
  ...-workspace.ts |   88.63 |    82.53 |     100 |   88.63 | ...40-241,253-254 
  discovery.ts     |   85.77 |    76.92 |      90 |   85.77 | ...49-250,255-256 
  ...structions.ts |     100 |      100 |     100 |     100 |                   
  ...oordinator.ts |   82.67 |    76.75 |   97.01 |   82.67 | ...1319,1351-1353 
  ...-installer.ts |    64.3 |    82.35 |   80.76 |    64.3 | ...45-446,460-472 
  ...oordinator.ts |   75.99 |    65.18 |   85.71 |   75.99 | ...1883,1974-1975 
  ...controller.ts |   67.82 |    79.31 |   72.72 |   67.82 | ...66-278,287-295 
  ...ak-to-user.ts |   96.66 |      100 |   83.33 |   96.66 | 37-38             
  ...sk-service.ts |    86.3 |    59.78 |   93.33 |    86.3 | ...1160,1184-1191 
  ...task-tools.ts |      99 |      100 |   85.71 |      99 | 205-206           
  ...redentials.ts |   96.26 |    93.47 |     100 |   96.26 | 91-94             
  ...me-session.ts |   65.63 |    57.24 |   88.88 |   65.63 | ...2270,2275-2282 
  ...up-context.ts |   94.83 |    77.58 |     100 |   94.83 | ...18,327-330,350 
  ...ion-source.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/serve/routes  |   85.79 |    80.39 |   94.91 |   85.79 |                   
  a2ui-action.ts   |   96.84 |     88.5 |    87.5 |   96.84 | ...70-272,309-311 
  capabilities.ts  |   98.63 |    95.65 |     100 |   98.63 | 76                
  ...nel-notify.ts |   86.45 |       88 |     100 |   86.45 | ...,83-87,103-104 
  ...l-webhooks.ts |   93.56 |    84.09 |     100 |   93.56 | ...42,292,332,334 
  daemon-status.ts |   85.71 |    83.33 |     100 |   85.71 | 101-108           
  goals.ts         |   98.92 |     90.9 |     100 |   98.92 | 143               
  health.ts        |   99.09 |    91.17 |     100 |   99.09 | 147               
  live-setup.ts    |   33.33 |     37.5 |      50 |   33.33 | ...18-123,130-135 
  live.ts          |    82.4 |    71.42 |     100 |    82.4 | ...-94,96-101,121 
  permission.ts    |     100 |     92.3 |     100 |     100 | 50,98             
  ...uled-tasks.ts |   87.29 |    82.94 |   92.59 |   87.29 | ...1275,1318-1319 
  ...on-runtime.ts |     100 |    90.47 |     100 |     100 | 58,94             
  session.ts       |   85.89 |    82.44 |   91.66 |   85.89 | ...4957,4959-4960 
  sse-events.ts    |   86.82 |    85.71 |   94.11 |   86.82 | ...16-927,930,937 
  usage-stats.ts   |     100 |    95.45 |     100 |     100 | 118               
  ...space-auth.ts |   85.55 |    75.64 |     100 |   85.55 | ...21-326,331,345 
  ...el-control.ts |   86.26 |    78.94 |     100 |   86.26 | ...17-318,339-347 
  ...management.ts |   90.92 |    79.69 |     100 |   90.92 | ...81-482,501-502 
  ...d-contacts.ts |     100 |      100 |     100 |     100 |                   
  ...controller.ts |   83.11 |    79.31 |      90 |   83.11 | ...1033,1039,1042 
  ...extensions.ts |   88.15 |    74.95 |   92.98 |   88.15 | ...2027,2072-2073 
  ...-file-read.ts |      91 |    80.91 |     100 |      91 | ...20-621,624-625 
  ...file-write.ts |   89.58 |    79.16 |     100 |   89.58 | ...84,698-705,786 
  ...t-branches.ts |   75.43 |    66.66 |     100 |   75.43 | ...13-618,627-634 
  ...e-git-diff.ts |   97.32 |    90.56 |     100 |   97.32 | 161-162,189-191   
  ...ce-git-log.ts |     100 |    93.18 |     100 |     100 | 52,77,188         
  workspace-git.ts |   77.08 |    89.65 |     100 |   77.08 | 97-118            
  ...github-prs.ts |   88.26 |    63.46 |     100 |   88.26 | ...38-239,264-265 
  ...-lifecycle.ts |   95.23 |    75.75 |     100 |   95.23 | ...50-151,186-187 
  ...management.ts |   87.41 |    84.13 |     100 |   87.41 | ...1660,1680-1685 
  ...cp-control.ts |    73.2 |    67.54 |   85.71 |    73.2 | ...27-633,644-645 
  ...ace-models.ts |   95.53 |    89.74 |     100 |   95.53 | ...52-157,296-297 
  ...ermissions.ts |    77.9 |    72.41 |     100 |    77.9 | ...69-277,298-316 
  ...e-settings.ts |   75.04 |    72.99 |     100 |   75.04 | ...79-690,696-697 
  ...tup-github.ts |   77.97 |    70.58 |   84.21 |   77.97 | ...46-352,397-398 
  ...ace-skills.ts |    76.9 |    87.15 |     100 |    76.9 | ...29-354,360-394 
  ...ace-status.ts |   82.94 |     74.5 |     100 |   82.94 | ...84-486,490-491 
  ...pace-tools.ts |   75.94 |    69.69 |   66.66 |   75.94 | ...59-164,193-194 
  ...pace-trust.ts |   78.92 |    66.21 |      80 |   78.92 | ...38-343,351-352 
  ...pace-voice.ts |   91.33 |    80.92 |     100 |   91.33 | ...70-673,676-678 
 src/serve/server  |   91.75 |    89.37 |   96.95 |   91.75 |                   
  access-log.ts    |   98.68 |     97.1 |     100 |   98.68 | 115,186           
  ...er-helpers.ts |   63.82 |    77.96 |   81.81 |   63.82 | ...16,330,332-347 
  ...w-registry.ts |    98.8 |    81.81 |     100 |    98.8 | 107               
  ...r-handlers.ts |   97.29 |       75 |     100 |   97.29 | 17                
  ...r-response.ts |   86.54 |    72.48 |     100 |   86.54 | ...49,766,829-838 
  fs-factory.ts    |     100 |    94.54 |     100 |     100 | 42,103,159        
  ...branch-ops.ts |     100 |      100 |     100 |     100 |                   
  ...list-cache.ts |   99.01 |    95.52 |     100 |   99.01 | 184-185           
  ...t-deadline.ts |     100 |      100 |     100 |     100 |                   
  ...iter-setup.ts |      65 |    73.33 |   33.33 |      65 | 30-35,38-43,47-48 
  ...st-helpers.ts |   95.13 |    95.09 |     100 |   95.13 | ...66-168,423-428 
  self-origin.ts   |   76.19 |       80 |     100 |   76.19 | 45-54             
  ...e-features.ts |      95 |     87.5 |     100 |      95 | 182-188           
  ...on-archive.ts |   89.55 |    87.72 |   97.14 |   89.55 | ...32-836,888-889 
  ...ion-export.ts |     100 |    94.44 |     100 |     100 | 64                
  session-list.ts  |   95.86 |    93.37 |     100 |   95.86 | ...-848,1026-1030 
  telemetry.ts     |   99.04 |    97.44 |     100 |   99.04 | ...37,652,794-796 
 src/serve/voice   |    92.7 |    91.48 |   97.67 |    92.7 |                   
  ...ice-config.ts |   84.81 |       30 |     100 |   84.81 | 91-100,104-105    
  voice-ws.ts      |   91.58 |    93.44 |      96 |   91.58 | ...68,483,521-523 
  ...oordinator.ts |     100 |    98.21 |     100 |     100 | 176               
 ...kspace-service |   90.65 |    87.73 |   91.11 |   90.65 |                   
  index.ts         |   90.13 |    87.04 |   89.74 |   90.13 | ...1464-1468,1471 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services      |   92.49 |    89.25 |      98 |   92.49 |                   
  ...mandLoader.ts |     100 |    88.88 |     100 |     100 | 105-118           
  ...killLoader.ts |   97.19 |    85.29 |     100 |   97.19 | 142,153-154       
  ...andService.ts |   98.73 |      100 |     100 |   98.73 | 107               
  ...mandLoader.ts |   87.09 |    83.07 |     100 |   87.09 | ...35-340,345-350 
  ...omptLoader.ts |   79.55 |    88.29 |   83.33 |   79.55 | ...48,178,245-246 
  ...mandLoader.ts |   97.77 |    92.15 |     100 |   97.77 | 176,183-184       
  ...nd-factory.ts |   91.42 |    91.66 |     100 |   91.42 | 128,137-144       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.23 |    96.72 |     100 |   98.23 | 83,87             
  commandUtils.ts  |      96 |     90.9 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  prompt-stash.ts  |   96.66 |    92.85 |     100 |   96.66 | 34-35             
  ...tree-lease.ts |   88.23 |    86.48 |     100 |   88.23 | ...94-199,232-233 
  ...low-loader.ts |     100 |    96.15 |     100 |     100 | 88                
  setup-github.ts  |    90.8 |    80.95 |     100 |    90.8 | ...49-450,457-458 
  ...-args-file.ts |   93.93 |    91.66 |    87.5 |   93.93 | 208-210,224-230   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |   98.64 |    95.77 |     100 |   98.64 | 116,142-143       
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  voice-service.ts |    90.4 |    87.87 |     100 |    90.4 | ...81,288,353-358 
  ...e-settings.ts |     100 |    95.23 |     100 |     100 | 19                
  ...ranscriber.ts |   91.77 |    87.11 |   97.22 |   91.77 | ...99-901,904-906 
 ...rvices/insight |     100 |      100 |     100 |     100 |                   
  dates.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   88.91 |     86.8 |   96.15 |   88.91 |                   
  DataProcessor.ts |   88.28 |    86.77 |   94.73 |   88.28 | ...1362,1366-1373 
  ...tGenerator.ts |   98.24 |    85.71 |     100 |   98.24 | 47                
  ...teRenderer.ts |     100 |      100 |     100 |     100 |                   
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 96-99             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.27 |    84.61 |     100 |   97.27 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.59 |       70 |     100 |   92.59 | ...24,146,153,162 
  tipRegistry.ts   |     100 |      100 |     100 |     100 |                   
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/startup       |   88.99 |    83.47 |    90.9 |   88.99 |                   
  ...p-prefetch.ts |   98.09 |    94.23 |    87.5 |   98.09 | 50,209,225-226    
  ...reeStartup.ts |   80.53 |     74.6 |     100 |   80.53 | ...94,403,409-412 
 src/test-utils    |   94.09 |    79.16 |   77.77 |   94.09 |                   
  ci-env.ts        |      88 |     62.5 |     100 |      88 | 22-23,28          
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...mised-lock.ts |     100 |      100 |   66.66 |     100 |                   
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   73.24 |    75.55 |   67.03 |   73.24 |                   
  App.tsx          |   33.33 |       75 |   33.33 |   33.33 | 32-86             
  AppContainer.tsx |   74.45 |    72.09 |   68.57 |   74.45 | ...4188,4304-4310 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |    30.3 |      100 |       0 |    30.3 | 26-76             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |      60 |      100 |   35.29 |      60 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    97.14 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  ...ractiveUI.tsx |   70.51 |       74 |    62.5 |   70.51 | ...12,339,392-397 
  ...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.76 |    66.66 |   51.06 |   58.76 |                   
  AuthDialog.tsx   |   59.01 |     42.1 |   16.66 |   59.01 | ...25,332-354,358 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |   60.21 |    70.73 |   57.69 |   60.21 | ...90,794,803,806 
  useAuth.ts       |   94.83 |       75 |     100 |   94.83 | ...33-234,253-259 
  ...rSetupFlow.ts |   43.18 |    33.33 |      50 |   43.18 | ...78-399,416-459 
 src/ui/commands   |   83.35 |    83.55 |   89.88 |   83.35 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |    93.1 |    95.23 |     100 |    93.1 | 77-82             
  arenaCommand.ts  |   63.89 |    65.71 |   65.21 |   63.89 | ...01-606,691-699 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   94.32 |    77.41 |     100 |   94.32 | 35-36,114-119     
  bugCommand.ts    |     100 |    77.77 |     100 |     100 | 27,61             
  cdCommand.ts     |    92.3 |    82.75 |     100 |    92.3 | ...,94-99,178,187 
  clearCommand.ts  |    80.9 |    70.83 |     100 |    80.9 | ...28-129,137-146 
  ...essCommand.ts |   68.06 |    54.05 |      75 |   68.06 | ...96-197,211-214 
  ...astCommand.ts |   84.17 |       75 |     100 |   84.17 | ...,91-97,125-130 
  ...ig-command.ts |   93.12 |    88.42 |     100 |   93.12 | ...07-315,321-323 
  ...extCommand.ts |   69.07 |     72.6 |   84.61 |   69.07 | ...78-611,622-623 
  copyCommand.ts   |    98.7 |    96.29 |     100 |    98.7 | 66-67,172,272,323 
  ...or-command.ts |   85.95 |    80.55 |   88.88 |   85.95 | ...68-274,298-309 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |     100 |    87.87 |     100 |     100 | ...63,231-232,245 
  ...ryCommand.tsx |   81.64 |    87.67 |    90.9 |   81.64 | ...73-278,325-332 
  docsCommand.ts   |     100 |     90.9 |     100 |     100 | 25                
  doctorCommand.ts |   70.16 |    84.61 |      95 |   70.16 | ...29-679,682-816 
  dreamCommand.ts  |   85.45 |    88.88 |     100 |   85.45 | 58-65             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...rt-command.ts |   80.48 |       75 |     100 |   80.48 | 49-54,69-72,93-98 
  effort-utils.ts  |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   98.25 |    91.02 |     100 |   98.25 | ...81,198-199,364 
  ...onsCommand.ts |   52.31 |    56.25 |   69.23 |   52.31 | ...09,277-329,390 
  forgetCommand.ts |     100 |       90 |     100 |     100 | 59                
  forkCommand.ts   |     100 |    94.11 |     100 |     100 | 96,147            
  goalCommand.ts   |     100 |    96.49 |     100 |     100 | 139,192           
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oryCommand.ts |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   81.13 |    65.71 |   85.71 |   81.13 | ...,86-93,131-132 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  ...figCommand.ts |   52.83 |    81.25 |      70 |   52.83 | ...74-319,321-330 
  initCommand.ts   |   91.86 |       80 |     100 |   91.86 | 48,83-88          
  ...ghtCommand.ts |   77.87 |    71.42 |     100 |   77.87 | ...44-245,250-272 
  ...ageCommand.ts |   94.44 |    90.14 |     100 |   94.44 | ...13-214,241-251 
  learn-command.ts |     100 |      100 |     100 |     100 |                   
  lspCommand.ts    |     100 |    86.95 |     100 |     100 | 31,101-102        
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   85.02 |    82.53 |     100 |   85.02 | ...1089,1123-1128 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...ns-command.ts |   98.83 |    81.81 |     100 |   98.83 | 100               
  ...berCommand.ts |     100 |     87.5 |     100 |     100 | 46                
  renameCommand.ts |    89.6 |       90 |     100 |    89.6 | ...72-176,212-219 
  ...oreCommand.ts |   90.96 |    86.04 |     100 |   90.96 | ...41-146,177-178 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |   81.25 |      100 |      50 |   81.25 | 20-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   89.47 |       75 |      80 |   89.47 | 54-59             
  skillsCommand.ts |   78.82 |    81.81 |     100 |   78.82 | 37-52,78,97       
  statsCommand.ts  |   90.65 |    76.73 |     100 |   90.65 | ...30-733,825-832 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |   73.04 |     82.3 |      90 |   73.04 | ...20-547,561-565 
  tasksCommand.ts  |   77.22 |    72.13 |     100 |   77.22 | ...46-150,172-177 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...te-command.ts |     100 |    94.11 |     100 |     100 | 74,148            
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
  voice-command.ts |   93.57 |       88 |     100 |   93.57 | 35,97-102         
  ...owsCommand.ts |   92.92 |       85 |   66.66 |   92.92 | ...72-177,276-281 
 src/ui/components |   71.96 |    79.54 |   79.56 |   71.96 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |    88.7 |       75 |     100 |    88.7 | 36,38-43,45       
  ...odeDialog.tsx |   87.24 |    72.22 |   33.33 |   87.24 | ...85,233-238,245 
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   95.65 |    66.66 |     100 |   95.65 | 27,52             
  ...TextInput.tsx |   88.65 |    90.41 |     100 |   88.65 | ...84-286,300-302 
  Composer.tsx     |   94.49 |    66.66 |     100 |   94.49 | ...-76,88,143,157 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  CronPill.tsx     |     100 |    93.75 |     100 |     100 | 19                
  ...ification.tsx |      84 |       60 |     100 |      84 | 23-24,40-42       
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |       0 |        0 |       0 |       0 | 1-598             
  DiffDialog.tsx   |    53.5 |     37.5 |   69.23 |    53.5 | ...32-737,747-760 
  ...ngsDialog.tsx |       0 |        0 |       0 |       0 | 1-195             
  EffortDialog.tsx |   97.36 |      100 |     100 |   97.36 | 55-56             
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   81.27 |    69.23 |      50 |   81.27 | ...06,245,267-272 
  ...ngSpinner.tsx |   68.42 |    85.71 |      50 |   68.42 | 35-52,73,80-81    
  GoalPill.tsx     |   93.51 |    81.81 |     100 |   93.51 | 37-38,106-109,123 
  Header.tsx       |   98.65 |    94.73 |     100 |   98.65 | 173,175           
  Help.tsx         |   98.33 |       90 |     100 |   98.33 | ...25,382,448-449 
  ...emDisplay.tsx |   79.28 |    66.99 |     100 |   79.28 | ...08,511,514-520 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   84.26 |    82.94 |      80 |   84.26 | ...2215,2236,2332 
  ...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.58 |    95.06 |   46.15 |   95.58 | ...79,482-486,489 
  MemoryDialog.tsx |   86.59 |    80.15 |     100 |   86.59 | ...34-435,485,553 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   85.22 |    74.08 |     100 |   85.22 | ...1041,1097,1099 
  ...tsDisplay.tsx |     100 |    97.22 |     100 |     100 | 270               
  ...fications.tsx |       0 |        0 |       0 |       0 | 1-56              
  ...onsDialog.tsx |       0 |        0 |       0 |       0 | 1-1004            
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   92.64 |    85.71 |     100 |   92.64 | 102-106,134-139   
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |       0 |        0 |       0 |       0 | 1-39              
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |   92.79 |    82.65 |     100 |   92.79 | ...19-323,354-370 
  ...ionPicker.tsx |   83.66 |    72.13 |     100 |   83.66 | ...96,402,444-466 
  ...onPreview.tsx |   93.58 |    83.78 |     100 |   93.58 | ...,70-71,195-197 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   92.06 |    86.36 |   83.33 |   92.06 | ...,70-72,120-123 
  ...tedDialog.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   71.49 |    73.89 |   69.23 |   71.49 | ...1244,1250-1251 
  ...ionDialog.tsx |    92.3 |    96.15 |   33.33 |    92.3 | 60-63,68-75,164   
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |       0 |        0 |       0 |       0 | 1-40              
  ...iewDialog.tsx |   97.77 |    87.67 |     100 |   97.77 | ...97,305-307,324 
  ...tsDisplay.tsx |   95.86 |       75 |     100 |   95.86 | 67-71             
  ...ionPicker.tsx |       0 |        0 |       0 |       0 | 1-172             
  ...tivityTab.tsx |    3.94 |      100 |       0 |    3.94 | 27-275            
  StatsDialog.tsx  |    8.64 |      100 |       0 |    8.64 | ...76-111,130-322 
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ciencyTab.tsx |    78.9 |    56.52 |     100 |    78.9 | ...26,213,262-288 
  ...atmapView.tsx |    8.98 |      100 |       0 |    8.98 | 20-107            
  ...essionTab.tsx |      80 |    66.66 |     100 |      80 | ...70-277,283-300 
  ...ineDialog.tsx |    93.9 |    86.88 |     100 |    93.9 | ...20,282,302-304 
  ...yTodoList.tsx |   96.36 |    88.23 |     100 |   96.36 | 138-141           
  ...nsDisplay.tsx |   95.62 |    87.09 |     100 |   95.62 | ...24-125,273-275 
  ...inalImage.tsx |     100 |    93.93 |     100 |     100 | 75,129            
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    83.33 |     100 |     100 | 72-87             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...Indicator.tsx |    92.5 |     87.5 |     100 |    92.5 | 50-53             
  ...ackDialog.tsx |       0 |        0 |       0 |       0 | 1-134             
  ...xitDialog.tsx |   80.36 |    43.47 |      60 |   80.36 | ...24-238,248-251 
  ...odeVisuals.ts |   97.22 |    85.71 |     100 |   97.22 | 25                
  ...s-helpers.tsx |   66.25 |    81.25 |      50 |   66.25 | 25-32,46-53,62-72 
 ...nts/agent-view |   55.05 |    69.09 |      50 |   55.05 |                   
  ...atContent.tsx |    9.09 |      100 |       0 |    9.09 | 54-275,281-283    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |   69.48 |    33.33 |   66.66 |   69.48 | ...51,269,277-279 
  AgentFooter.tsx  |   15.38 |      100 |       0 |   15.38 | 28-65             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    87.9 |    63.88 |     100 |    87.9 | ...88,110-118,136 
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    42.3 |    68.69 |   73.68 |    42.3 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |       0 |        0 |       0 |       0 | 1-166             
  ...tusDialog.tsx |       0 |        0 |       0 |       0 | 1-288             
  ...topDialog.tsx |       0 |        0 |       0 |       0 | 1-213             
 ...ackground-view |   85.34 |    84.91 |   92.98 |   85.34 |                   
  ...sksDialog.tsx |   81.87 |    82.77 |   85.71 |   81.87 | ...1853,1965-1971 
  ...TasksPill.tsx |   78.84 |    94.28 |     100 |   78.84 | 64,109-129        
  ...gentPanel.tsx |   97.08 |    86.31 |     100 |   97.08 | 132,442-446,520   
  agent-forest.ts  |    99.2 |    93.93 |     100 |    99.2 | 258               
  ...Visibility.ts |     100 |      100 |     100 |     100 |                   
  ...e-overlay.tsx |    88.2 |    76.47 |     100 |    88.2 | ...36-138,140-142 
 ...nts/extensions |   84.32 |    76.78 |   83.33 |   84.32 |                   
  ...gerDialog.tsx |   82.15 |    76.08 |     100 |   82.15 | ...91-198,258,260 
  TabBar.tsx       |   97.29 |    88.88 |     100 |   97.29 | 33                
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   46.26 |       85 |   58.82 |   46.26 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |       0 |        0 |       0 |       0 | 1-145             
  ...nListStep.tsx |   75.26 |    88.37 |   66.66 |   75.26 | ...53,174,203-209 
  ...electStep.tsx |       0 |        0 |       0 |       0 | 1-83              
  ...nfirmStep.tsx |   16.32 |      100 |       0 |   16.32 | 28-74             
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
 ...xtensions/tabs |   71.92 |    68.21 |   70.83 |   71.92 |                   
  DiscoverTab.tsx  |   68.22 |    67.66 |   55.55 |   68.22 | ...93,656-660,664 
  InstalledTab.tsx |   75.49 |    67.44 |   83.33 |   75.49 | ...77,782-783,820 
  SourcesTab.tsx   |   71.67 |    70.47 |   77.77 |   71.67 | ...28,547,621-633 
 ...tensions/views |    50.7 |    52.38 |   20.83 |    50.7 |                   
  ...tionsView.tsx |   73.75 |    56.36 |   66.66 |   73.75 | ...30,353,369-374 
  ...tionsView.tsx |   43.45 |    44.82 |    6.66 |   43.45 | ...98-405,408-420 
  ...etailView.tsx |    9.24 |      100 |       0 |    9.24 | 40-67,70-163      
 ...mponents/hooks |   87.11 |     81.3 |   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.24 |     100 |   72.29 | ...51,563-568,572 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  ...erGrouping.ts |     100 |      100 |     100 |     100 |                   
  sourceLabels.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   40.91 |    63.44 |   70.58 |   40.91 |                   
  ...ealthPill.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   32.09 |    26.19 |      40 |   32.09 | ...12,914,927-933 
  ...valDialog.tsx |   15.06 |      100 |       0 |   15.06 | 40-109            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-35              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |      97 |       95 |     100 |      97 | 24,113-114        
 ...ents/mcp/steps |   53.94 |    73.51 |   57.14 |   53.94 |                   
  ...icateStep.tsx |    5.65 |      100 |       0 |    5.65 | 40-66,69-308      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |     100 |      100 |     100 |     100 |                   
  ...eListStep.tsx |   99.09 |    97.36 |     100 |   99.09 | 71                
  ...etailStep.tsx |   62.83 |       60 |   33.33 |   62.83 | ...87-296,307-332 
  ...rListStep.tsx |   88.53 |    81.25 |     100 |   88.53 | ...64,170,175-180 
  ...etailStep.tsx |    10.3 |      100 |       0 |    10.3 | ...1,67-79,82-140 
  ToolListStep.tsx |   69.29 |       50 |     100 |   69.29 | ...23,126,135-144 
 ...nents/messages |   90.26 |    86.89 |   85.57 |   90.26 |                   
  ...ionDialog.tsx |   89.23 |     84.9 |   81.81 |   89.23 | ...75,593,611-613 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |     100 |    94.73 |     100 |     100 | ...43,289,402,432 
  ...onMessage.tsx |   92.06 |    82.35 |     100 |   92.06 | 58-60,62,64       
  ...nMessages.tsx |   94.11 |    95.91 |   76.92 |   94.11 | ...47-349,352-355 
  DiffRenderer.tsx |   93.17 |    86.02 |     100 |   93.17 | ...07,235-236,302 
  ...tsDisplay.tsx |   97.08 |    77.77 |     100 |   97.08 | 95,97,106         
  ...usMessage.tsx |   81.73 |     65.9 |      75 |   81.73 | ...10-214,222,245 
  ...tsDisplay.tsx |   95.52 |    88.31 |     100 |   95.52 | ...40,142,175-180 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   21.05 |      100 |       0 |   21.05 | 23-39             
  ...sMessages.tsx |   59.04 |       50 |    37.5 |   59.04 | ...21-126,147-159 
  ...ryMessage.tsx |   13.63 |      100 |       0 |   13.63 | 23-64             
  ...onMessage.tsx |   91.87 |    82.63 |     100 |   91.87 | ...49-651,658-660 
  ...upMessage.tsx |   98.38 |    95.38 |     100 |   98.38 | 188-191,422       
  ToolMessage.tsx  |   93.06 |    86.32 |   93.75 |   93.06 | ...1037,1082-1084 
 ...ponents/shared |   86.29 |    82.41 |   94.17 |   86.29 |                   
  ...ctionList.tsx |     100 |      100 |      75 |     100 |                   
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  ...rBoundary.tsx |     100 |      100 |     100 |     100 |                   
  MaxSizedBox.tsx  |   84.71 |    86.95 |      90 |   84.71 | ...67-568,685-686 
  MultiSelect.tsx  |   93.58 |       75 |     100 |   93.58 | ...43,199-201,211 
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...ontroller.tsx |     100 |    83.33 |     100 |     100 | 73,93-95          
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  ...lableList.tsx |   81.48 |    84.84 |     100 |   81.48 | 46-66,73-76       
  StaticRender.tsx |     100 |      100 |     100 |     100 |                   
  TextInput.tsx    |    80.8 |    67.24 |      80 |    80.8 | ...36-240,252-258 
  ...ontroller.tsx |     100 |    81.81 |     100 |     100 | 59-62             
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...lizedList.tsx |   91.49 |    86.66 |   83.33 |   91.49 | ...18-846,859,959 
  text-buffer.ts   |   85.98 |    81.81 |   97.91 |   85.98 | ...2664,2762-2763 
  ...er-actions.ts |   73.93 |    67.22 |     100 |   73.93 | ...32-733,934-936 
 ...ponents/skills |       0 |        0 |       0 |       0 |                   
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-681             
 ...ents/subagents |       0 |        0 |       0 |       0 |                   
  constants.ts     |       0 |        0 |       0 |       0 | 1-71              
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |       0 |        0 |       0 |       0 | 1-190             
  types.ts         |       0 |        0 |       0 |       0 | 1-125             
  utils.ts         |       0 |        0 |       0 |       0 | 1-102             
 ...bagents/create |       0 |        0 |       0 |       0 |                   
  ...ionWizard.tsx |       0 |        0 |       0 |       0 | 1-299             
  ...rSelector.tsx |       0 |        0 |       0 |       0 | 1-85              
  ...onSummary.tsx |       0 |        0 |       0 |       0 | 1-331             
  ...tionInput.tsx |       0 |        0 |       0 |       0 | 1-177             
  ...dSelector.tsx |       0 |        0 |       0 |       0 | 1-63              
  ...nSelector.tsx |       0 |        0 |       0 |       0 | 1-58              
  ...EntryStep.tsx |       0 |        0 |       0 |       0 | 1-78              
  ToolSelector.tsx |       0 |        0 |       0 |       0 | 1-253             
 ...bagents/manage |   14.14 |    53.19 |    37.5 |   14.14 |                   
  ...ctionStep.tsx |       0 |        0 |       0 |       0 | 1-103             
  ...eleteStep.tsx |       0 |        0 |       0 |       0 | 1-62              
  ...tEditStep.tsx |       0 |        0 |       0 |       0 | 1-124             
  ...ctionStep.tsx |   35.61 |    59.52 |     100 |   35.61 | ...21-433,438-440 
  ...iewerStep.tsx |       0 |        0 |       0 |       0 | 1-73              
  ...gerDialog.tsx |       0 |        0 |       0 |       0 | 1-341             
 ...mponents/views |    70.1 |    72.89 |   61.11 |    70.1 |                   
  ContextUsage.tsx |   71.49 |    64.86 |      80 |   71.49 | ...30-436,473-567 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   88.05 |       75 |     100 |   88.05 | 70-77             
  McpStatus.tsx    |   92.01 |     73.8 |     100 |   92.01 | ...36,175-177,262 
  SkillsList.tsx   |   20.51 |      100 |       0 |   20.51 | 17-20,27-57       
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   84.16 |    81.83 |   85.13 |   84.16 |                   
  ...ewContext.tsx |   64.83 |    88.88 |      50 |   64.83 | ...16-219,225-235 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.83 |    68.51 |   42.85 |   93.83 | ...44,281-285,317 
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   85.65 |    84.85 |     100 |   85.65 | ...1612-1614,1620 
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 47-48,60-62       
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   80.77 |       80 |    92.3 |   80.77 | ...31-434,443-446 
  ...gsContext.tsx |     100 |      100 |     100 |     100 |                   
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...edContext.tsx |     100 |      100 |      50 |     100 |                   
  ...nsContext.tsx |   88.88 |       50 |     100 |   88.88 | 156-157           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 235-236           
  ...deContext.tsx |      80 |     87.5 |      75 |      80 | ...11-112,118-120 
  ...rtContext.tsx |     100 |      100 |     100 |     100 |                   
 src/ui/daemon     |   88.35 |    73.51 |   95.45 |   88.35 |                   
  ...ui-adapter.ts |   88.35 |    73.51 |   95.45 |   88.35 | ...74,792-793,879 
 src/ui/editors    |       0 |        0 |       0 |       0 |                   
  ...ngsManager.ts |       0 |        0 |       0 |       0 | 1-67              
 src/ui/hooks      |   85.64 |    83.19 |   87.86 |   85.64 |                   
  ...dProcessor.ts |   85.53 |    85.13 |     100 |   85.53 | ...-970,1017-1018 
  ...ention-ref.ts |   97.72 |       84 |     100 |   97.72 | 65                
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...esourceRef.ts |     100 |      100 |     100 |     100 |                   
  ...completion.ts |     100 |    95.45 |     100 |     100 | 95                
  ...ention-ref.ts |     100 |      100 |     100 |     100 |                   
  ...dProcessor.ts |   94.62 |    73.58 |     100 |   94.62 | ...87-288,293-294 
  ...dProcessor.ts |   86.86 |    71.67 |   83.33 |   86.86 | ...1540,1562-1566 
  ...rt-command.ts |     100 |      100 |     100 |     100 |                   
  ...sced-flush.ts |     100 |      100 |     100 |     100 |                   
  ...ng-enabled.ts |     100 |      100 |     100 |     100 |                   
  ...oice-input.ts |   92.36 |    81.95 |   66.66 |   92.36 | ...00,502-503,658 
  ...ke-repaint.ts |     100 |      100 |     100 |     100 |                   
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-157            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...dScrollbar.ts |     100 |      100 |     100 |     100 |                   
  ...ationFrame.ts |      52 |    63.63 |     100 |      52 | ...59,67-70,76-87 
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   27.92 |       80 |      25 |   27.92 | ...69-170,173-175 
  ...Completion.ts |   86.44 |    88.48 |     100 |   86.44 | ...14-515,525-541 
  ...ifications.ts |   87.82 |    96.77 |     100 |   87.82 | 138-152           
  ...tIndicator.ts |   88.28 |    81.57 |     100 |   88.28 | ...66,175,179-187 
  ...waySummary.ts |   96.26 |       75 |     100 |   96.26 | 126-128,170       
  ...ndTaskView.ts |   94.89 |    77.55 |     100 |   94.89 | 164-168,257,263   
  ...chedScroll.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   95.53 |    83.01 |     100 |   95.53 | ...64-165,289-292 
  ...ompletion.tsx |   97.09 |    87.09 |     100 |   97.09 | ...23-324,334-335 
  ...dMigration.ts |    92.1 |    88.88 |     100 |    92.1 | 42-44             
  useCompletion.ts |   96.29 |    90.56 |     100 |   96.29 | ...17-218,222-223 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   78.26 |       50 |     100 |   78.26 | ...2,75-79,96-104 
  ...eteCommand.ts |   89.52 |    90.69 |     100 |   89.52 | ...98-106,114-115 
  ...ialogClose.ts |   36.11 |       10 |     100 |   36.11 | ...89-195,202-207 
  useDiffData.ts   |       0 |        0 |       0 |       0 | 1-87              
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |    97.67 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.72 |    92.98 |     100 |   93.72 | ...87-291,314-320 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |    63.9 |    76.47 |   66.66 |    63.9 | ...66-168,190-191 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |    93.33 |     100 |     100 | 62                
  ...ggestions.tsx |   96.47 |    78.94 |     100 |   96.47 | 121,155-156       
  ...miniStream.ts |   86.08 |    81.23 |   76.92 |   86.08 | ...5198-5200,5202 
  ...BranchName.ts |     100 |    94.44 |     100 |     100 | 54                
  ...oryManager.ts |   98.38 |    98.85 |     100 |   98.38 | 141-144           
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |   22.58 |      100 |      50 |   22.58 | 11-32,44-85       
  ...gIndicator.ts |     100 |    96.66 |     100 |     100 | 109               
  useLogger.ts     |      16 |      100 |       0 |      16 | 15-45             
  useMCPHealth.ts  |   10.52 |      100 |       0 |   10.52 | 36-75             
  ...cpApproval.ts |   93.12 |    86.11 |     100 |   93.12 | ...24-127,139-140 
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |   83.14 |    78.57 |     100 |   83.14 | 54-63,74-79       
  ...ssageQueue.ts |     100 |     97.4 |     100 |     100 | 175,262           
  ...delCommand.ts |     100 |       96 |     100 |     100 | 61                
  ...ouseEvents.ts |   94.89 |       95 |   83.33 |   94.89 | 78-82             
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...rredEditor.ts |   58.33 |    22.22 |     100 |   58.33 | 23-27,29-33       
  ...derUpdates.ts |   85.29 |    80.28 |    92.3 |   85.29 | ...36,351-361,441 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |   89.48 |    88.88 |     100 |   89.48 | ...54-456,489-499 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   95.34 |    77.14 |     100 |   95.34 | 124-125,227-232   
  ...ompletion.tsx |   90.67 |    83.33 |     100 |   90.67 | ...02,105,138-141 
  ...ectionList.ts |   97.12 |    96.22 |     100 |   97.12 | ...92-193,247-250 
  ...sionPicker.ts |   92.87 |    90.35 |     100 |   92.87 | ...99-501,503-505 
  ...earchInput.ts |     100 |    97.29 |     100 |     100 | 82                
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   93.28 |    80.95 |     100 |   93.28 | ...96,153-154,164 
  ...oryCommand.ts |   85.48 |    58.33 |     100 |   85.48 | 22-28,40,71       
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...Completion.ts |   82.85 |    85.13 |   94.73 |   82.85 | ...78-680,688-724 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...tatsDialog.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |   97.32 |    93.93 |     100 |   97.32 | ...18-422,518-525 
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...mInProcess.ts |   27.35 |       80 |      25 |   27.35 | ...82-183,186-188 
  ...tification.ts |     100 |     87.5 |     100 |     100 | 50                
  ...alProgress.ts |   67.34 |    58.82 |   66.66 |   67.34 | 52-53,61-68,79-85 
  ...rminalSize.ts |     100 |      100 |     100 |     100 |                   
  ...emeCommand.ts |    79.2 |    35.29 |     100 |    79.2 | ...15-116,120-121 
  useTimer.ts      |   97.59 |    94.73 |     100 |   97.59 | 17-18             
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |    90.47 |     100 |     100 | 112,134           
  useTurnDiffs.ts  |   95.12 |    78.57 |     100 |   95.12 | 133-134,156-157   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  ...reeSession.ts |   93.75 |       70 |     100 |   93.75 | 47-48,72          
  vim.ts           |      74 |    67.56 |   69.23 |      74 | ...1854-1861,1869 
 src/ui/layouts    |   91.25 |    89.47 |     100 |   91.25 |                   
  ...AppLayout.tsx |   90.99 |     87.5 |     100 |   90.99 | 61-63,111-116,152 
  ...AppLayout.tsx |   91.66 |    92.85 |     100 |   91.66 | 75-80             
 src/ui/models     |   80.72 |       80 |   71.42 |   80.72 |                   
  ...ableModels.ts |   80.72 |       80 |   71.42 |   80.72 | ...,61-71,125-127 
 ...noninteractive |     100 |      100 |    6.66 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    6.66 |     100 |                   
 src/ui/selection  |   93.56 |    86.19 |     100 |   93.56 |                   
  screen-buffer.ts |   94.73 |    64.28 |     100 |   94.73 | 51-52             
  ...ion-coords.ts |     100 |      100 |     100 |     100 |                   
  ...ction-span.ts |   93.81 |     92.1 |     100 |   93.81 | ...1,45-46,99-100 
  ...tion-state.ts |     100 |      100 |     100 |     100 |                   
  ...ction-text.ts |   93.85 |    93.54 |     100 |   93.85 | 30-34,130-131     
  ...selection.tsx |   91.88 |    78.57 |     100 |   91.88 | ...16-417,446-447 
 src/ui/state      |      95 |    81.81 |     100 |      95 |                   
  extensions.ts    |      95 |    81.81 |     100 |      95 | 69-70,89          
 src/ui/themes     |    98.5 |    73.17 |     100 |    98.5 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |   99.23 |    97.05 |     100 |   99.23 | 277-278           
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   88.68 |    84.52 |     100 |   88.68 | ...83-392,397-398 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   87.57 |    85.61 |   95.76 |   87.57 |                   
  ...Colorizer.tsx |   80.31 |    85.41 |     100 |   80.31 | ...00-201,313-339 
  ...nRenderer.tsx |   80.07 |     75.6 |     100 |   80.07 | ...70,274,332-333 
  ...wnDisplay.tsx |   92.87 |    93.46 |     100 |   92.87 | ...,955,1002-1020 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   93.63 |    81.77 |   95.23 |   93.63 | ...47-750,803-808 
  ...odeDisplay.ts |   94.28 |    85.71 |     100 |   94.28 | 23,40             
  asciiCharts.ts   |    96.7 |     87.5 |     100 |    96.7 | 170-177,278       
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |    52.9 |    74.15 |    92.3 |    52.9 | ...29,632-641,644 
  commandUtils.ts  |   98.38 |    92.38 |     100 |   98.38 | 108,136-137,343   
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   73.84 |    73.91 |     100 |   73.84 | ...34,36-40,42-46 
  formatters.ts    |   94.87 |    98.24 |     100 |   94.87 | 116-119           
  goal-runtime.ts  |   91.42 |       95 |     100 |   91.42 | 32-34             
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...gap-notice.ts |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |       95 |     100 |     100 | 44,103            
  historyUtils.ts  |   96.03 |     97.1 |     100 |   96.03 | 103-106           
  ...mage-parts.ts |   97.75 |    94.59 |     100 |   97.75 | 82-83             
  inline-math.ts   |   98.48 |    95.23 |     100 |   98.48 | 129-130           
  input-mouse.ts   |     100 |    85.71 |     100 |     100 | 48,93             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   68.81 |       75 |   66.66 |   68.81 | ...27-132,160-161 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  list-mouse.ts    |     100 |      100 |     100 |     100 |                   
  ...ightLoader.ts |     100 |       95 |     100 |     100 | 81                
  ...nUtilities.ts |   98.72 |    94.36 |     100 |   98.72 | 145-146           
  ...t-position.ts |     100 |     87.5 |     100 |     100 | 85                
  ...geRenderer.ts |   86.51 |    70.16 |   95.12 |   86.51 | ...1286,1326-1332 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  mouse.ts         |   92.85 |    74.19 |     100 |   92.85 | ...38,145,149-152 
  osc8.ts          |   91.33 |    79.03 |     100 |   91.33 | ...73,273,277-278 
  ...red-height.ts |   98.38 |    97.14 |     100 |   98.38 | 195-197           
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  restoreGoal.ts   |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   82.86 |    79.48 |     100 |   82.86 | ...88-610,741-742 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...evel-label.ts |   77.77 |    66.66 |     100 |   77.77 | 18,22-24          
  ...are-cursor.ts |   89.47 |    85.71 |     100 |   89.47 | 39-44             
  ...ataService.ts |   93.17 |     79.1 |     100 |   93.17 | ...14,227,254-256 
  suggestions.ts   |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   95.19 |      100 |   88.88 |   95.19 | 121-126           
  ...nal-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...e-renderer.ts |   90.61 |    83.44 |     100 |   90.61 | ...80,482-484,607 
  ...ize-reflow.ts |     100 |     92.3 |     100 |     100 | 57,62,209,217,347 
  ...wOptimizer.ts |     100 |    94.11 |     100 |     100 | 33,76             
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.94 |    95.49 |   94.11 |   97.94 | ...82-283,443-444 
  ...background.ts |     100 |      100 |     100 |     100 |                   
  todoSnapshot.ts  |   90.42 |    92.85 |     100 |   90.42 | ...06-207,240-241 
  ...isplay-map.ts |     100 |      100 |     100 |     100 |                   
  updateCheck.ts   |     100 |    92.75 |     100 |     100 | 227-239,331       
  ...ow-keyword.ts |     100 |      100 |     100 |     100 |                   
 ...i/utils/export |   75.03 |     60.3 |   94.59 |   75.03 |                   
  collect.ts       |   71.27 |    66.38 |      96 |   71.27 | ...90-633,655-656 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   80.42 |    50.68 |     100 |   80.42 | ...59-364,376-378 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |     100 |      100 |     100 |     100 |                   
 ...ort/formatters |   52.92 |    47.22 |   71.42 |   52.92 |                   
  html.ts          |   84.61 |       50 |     100 |   84.61 | ...53,57-58,62-63 
  json.ts          |     100 |      100 |     100 |     100 |                   
  jsonl.ts         |   82.45 |     37.5 |     100 |   82.45 | ...48,50-51,65-66 
  markdown.ts      |   36.32 |    47.05 |      50 |   36.32 | ...16-219,233-295 
 src/ui/voice      |   81.27 |    79.92 |   81.94 |   81.27 |                   
  ...d-recorder.ts |     6.2 |      100 |       0 |     6.2 | ...33-159,162-163 
  ...o-recorder.ts |   84.61 |    93.33 |   57.14 |   84.61 | ...16-117,131-136 
  ...me-session.ts |   91.09 |     92.1 |     100 |   91.09 | ...99,305,316-319 
  sox-recorder.ts  |    92.7 |    71.87 |     100 |    92.7 | ...34-135,153-154 
  ...ailability.ts |     100 |      100 |     100 |     100 |                   
  ...e-keyterms.ts |     100 |      100 |     100 |     100 |                   
  voice-model.ts   |     100 |      100 |     100 |     100 |                   
  ...e-recorder.ts |   88.29 |    67.74 |   81.81 |   88.29 | ...,98-99,112,115 
  voice-refine.ts  |     100 |    93.33 |     100 |     100 | 92                
  ...ream-retry.ts |   86.79 |       70 |     100 |   86.79 | 16-18,48-49,59-60 
  ...am-session.ts |   88.02 |    66.66 |   84.61 |   88.02 | ...26,343-345,363 
  ...ranscriber.ts |     100 |      100 |     100 |     100 |                   
 src/utils         |   81.63 |    87.34 |   92.75 |   81.63 |                   
  ...p-profiler.ts |   98.39 |    92.59 |     100 |   98.39 | 141,185,235       
  acpModelUtils.ts |   97.36 |    95.19 |     100 |   97.36 | ...09-210,214-215 
  apiPreconnect.ts |   96.74 |    94.59 |     100 |   96.74 | 167-170           
  ...ol-call-id.ts |   84.61 |       60 |     100 |   84.61 | 26-27,37-38       
  ...ng-failure.ts |     100 |      100 |     100 |     100 |                   
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  ...-api-error.ts |     100 |    96.42 |     100 |     100 | 14                
  cleanup.ts       |   84.05 |    94.11 |      80 |   84.05 | 80,111-121        
  commands.ts      |   97.45 |    96.66 |     100 |   97.45 | 153-155           
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  cpuProfiler.ts   |   70.73 |    73.23 |   88.88 |   70.73 | ...27,430-431,438 
  deepMerge.ts     |     100 |    89.65 |     100 |     100 | 41-43,49          
  ...re-runtime.ts |     100 |      100 |     100 |     100 |                   
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   70.31 |    74.57 |     100 |   70.31 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.31 |     100 |   90.65 | ...73,371,373-374 
  ...arResolver.ts |   97.14 |    96.55 |     100 |   97.14 | 125-126           
  errors.ts        |   97.56 |    94.64 |     100 |   97.56 | 69-70,304-305     
  events.ts        |     100 |      100 |     100 |     100 |                   
  ...on-mention.ts |   88.48 |     82.6 |     100 |   88.48 | ...56-160,164-168 
  gitUtils.ts      |   92.85 |    86.66 |     100 |   92.85 | ...13-116,164-167 
  ...AutoUpdate.ts |    93.1 |       94 |      90 |    93.1 | 103,108,179-190   
  ...tyWarnings.ts |     100 |      100 |     100 |     100 |                   
  ...lationInfo.ts |   97.68 |    94.28 |     100 |   97.68 | ...64,381-382,427 
  ...projection.ts |   95.27 |    95.58 |     100 |   95.27 | 140-145           
  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 |   86.64 |    77.02 |     100 |   86.64 | ...03-304,335-345 
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...er-mention.ts |     100 |    66.66 |     100 |     100 | 14,30,44-46       
  ...iagnostics.ts |   94.57 |    83.01 |   88.88 |   94.57 | ...05,311,315-317 
  ...serMessage.ts |     100 |      100 |     100 |     100 |                   
  ...onfigUtils.ts |   94.25 |    91.17 |     100 |   94.25 | ...30,436,439-443 
  ...iveHelpers.ts |   95.13 |    91.85 |     100 |   95.13 | ...53-454,552,565 
  osc.ts           |   97.18 |      100 |    87.5 |   97.18 | 182-183           
  package.ts       |   88.88 |    85.71 |     100 |   88.88 | 31-32             
  ...uggestions.ts |   84.29 |    70.83 |     100 |   84.29 | 70-76,92-103      
  processUtils.ts  |    92.3 |       80 |     100 |    92.3 | 45-46             
  readStdin.ts     |   93.67 |    94.11 |   85.71 |   93.67 | 79-83             
  relaunch.ts      |   95.87 |    89.28 |     100 |   95.87 | 103-105,131       
  resolvePath.ts   |     100 |      100 |     100 |     100 |                   
  runBudget.ts     |   99.35 |    96.77 |     100 |   99.35 | 119               
  sandbox-path.ts  |     100 |      100 |     100 |     100 |                   
  sandbox.ts       |   45.52 |    57.35 |   76.92 |   45.52 | ...1040,1052-1075 
  ...xImageName.ts |     100 |    77.77 |     100 |     100 | 10,18             
  sandboxMounts.ts |     100 |      100 |     100 |     100 |                   
  sessionPaths.ts  |   90.84 |    90.56 |     100 |   90.84 | ...81-182,185-186 
  settingsUtils.ts |   82.35 |    89.57 |      90 |   82.35 | ...25-743,750-758 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...ate-verify.ts |     100 |      100 |     100 |     100 |                   
  ...one-update.ts |   39.81 |    77.44 |   62.16 |   39.81 | ...1193,1196-1215 
  ...upProfiler.ts |   98.47 |    94.66 |     100 |   98.47 | 132-133,308       
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       90 |     100 |     100 | 23                
  systemInfo.ts    |   95.12 |    90.27 |     100 |   95.12 | ...54-255,260-264 
  ...InfoFields.ts |    87.5 |    65.85 |     100 |    87.5 | ...24-125,146-147 
  ...alSequence.ts |     100 |    97.61 |     100 |     100 | 60                
  ...iffPreview.ts |   76.47 |       25 |     100 |   76.47 | 13,17,23-24       
  ...on-handler.ts |    73.8 |       75 |     100 |    73.8 | 17-18,25-26,67-73 
  ...e-relaunch.ts |   89.61 |    86.66 |      50 |   89.61 | 56-61,83-84       
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...ansionHook.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   87.75 |       75 |     100 |   87.75 | 47-48,53-54,57-58 
  version.ts       |     100 |    66.66 |     100 |     100 | 11                
  ...ingHandler.ts |     100 |      100 |     100 |     100 |                   
  windowTitle.ts   |   96.55 |    94.73 |     100 |   96.55 | 56-57             
  ...WithBackup.ts |   65.04 |    77.77 |     100 |   65.04 | 97,112,133-172    
 ...s/housekeeping |   93.51 |    90.95 |   96.96 |   93.51 |                   
  cleanup.ts       |   92.59 |    93.75 |     100 |   92.59 | ...02-205,209-211 
  ...eractionAt.ts |     100 |      100 |     100 |     100 |                   
  scheduler.ts     |      93 |    88.34 |      95 |      93 | ...57-359,411-415 
  throttledOnce.ts |   95.95 |    93.93 |     100 |   95.95 | 77-78,153-154     
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.92 |    86.45 |   89.45 |   87.92 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.38 |    84.54 |   94.85 |   90.38 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.59 |    77.55 |   83.33 |   85.59 | ...1793-1797,1800 
  ...ound-tasks.ts |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
 src/agents/arena  |   76.94 |    68.22 |   78.94 |   76.94 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.89 |     65.2 |   78.57 |   75.89 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   91.11 |    86.68 |   89.23 |   91.11 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.38 |      100 |    92.3 |   98.38 | 85-86             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |    92.4 |       90 |   83.78 |    92.4 | ...1862,1911-1914 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1705,1711-1712 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   82.72 |    84.65 |   89.05 |   82.72 |                   
  TeamManager.ts   |    73.6 |    80.82 |   79.62 |    73.6 | ...1706,1729-1730 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.35 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |       85 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.16 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.81 |    87.18 |   75.53 |   84.81 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.13 |    86.91 |   73.98 |   84.13 | ...8535,8539-8540 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.37 |    88.08 |   93.29 |   92.37 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   92.05 |     87.4 |   91.66 |   92.05 | ...3987,4085-4086 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6216,6244-6260 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |    91.89 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 68-72             
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.67 |    93.12 |     100 |   98.67 | ...79,707-708,755 
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.33 |    88.12 |   96.15 |   96.33 |                   
  ...tGenerator.ts |   97.24 |    86.72 |   94.87 |   97.24 | ...1436,1465,1476 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1329,1550-1552 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |   95.93 |    90.03 |   90.47 |   95.93 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.86 |    89.29 |      90 |   95.86 | ...1258-1259,1287 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.71 |    90.53 |   95.61 |   91.71 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |    91.3 |    89.49 |   96.87 |    91.3 | ...1942,2111-2126 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.48 |    91.27 |     100 |   95.48 | ...1309,1317,1416 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.36 |    92.19 |    98.5 |   97.36 |                   
  dashscope.ts     |   98.33 |    94.97 |   96.42 |   98.33 | ...91-692,834-835 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.18 |    97.05 |     100 |   99.18 | 208               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   87.71 |    84.62 |   92.57 |   87.71 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.94 |    86.26 |   97.91 |   90.94 | ...1230-1236,1280 
  ...ionManager.ts |   83.89 |    82.86 |   81.72 |   83.89 | ...2832,2861-2862 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.71 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.48 |    82.71 |     100 |   90.48 | ...4,994-995,1005 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 ...ent-plugins-v1 |   84.94 |    79.51 |     100 |   84.94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  manifest.ts      |   81.87 |    84.48 |     100 |   81.87 | ...55-156,161-174 
  mcp.ts           |   84.98 |    79.56 |     100 |   84.98 | ...88-389,419-420 
  paths.ts         |     100 |    94.44 |     100 |     100 | 59                
  skills.ts        |   82.31 |    63.88 |     100 |   82.31 | ...38-141,150-151 
 src/followup      |    79.9 |    78.92 |    90.9 |    79.9 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   71.76 |    64.76 |   71.42 |   71.76 | ...53-654,661-662 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |   93.25 |    88.99 |   93.68 |   93.25 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.79 |     88.5 |   96.42 |   88.79 | ...04-805,828-831 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...87,190,194-196 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |      92 |    93.33 |      80 |      92 | 102-103,167-168   
  goal-reducer.ts  |    93.4 |    90.65 |   96.96 |    93.4 | ...27,501,519-520 
  goal-runtime.ts  |   97.44 |    89.68 |   97.67 |   97.44 | ...1216-1217,1338 
  goal-tools.ts    |   98.22 |    93.02 |      95 |   98.22 | ...46-147,248-249 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.25 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    87.91 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.09 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.83 |    83.76 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    74.19 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |     82.6 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |     79.1 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.97 |   91.13 |   92.55 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.17 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.63 |    89.01 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |     92.7 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.09 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.6 |   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 |    74.04 |   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 | 81-83,86-88,90-93 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.76 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.75 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.83 |    84.84 |   96.92 |   89.83 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   98.46 |    87.17 |     100 |   98.46 | 81-82,105,468-469 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |    91.6 |    85.44 |   95.77 |    91.6 | ...2155,2182-2183 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    94.17 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   96.31 |    91.81 |     100 |   96.31 | ...11,336-337,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...53,479-486,531 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |   97.22 |    90.99 |     100 |   97.22 | ...55-456,609-610 
  ...ttachments.ts |   97.74 |    90.85 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   89.26 |    85.35 |   97.22 |   89.26 | ...2537,2613-2633 
  sessionTitle.ts  |   95.75 |    77.41 |     100 |   95.75 | ...53-256,287-288 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...ite-origin.ts |     100 |    93.33 |     100 |     100 | 32                
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   88.36 |     87.8 |     100 |   88.36 | ...48-449,465-466 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |    82.1 |    84.29 |   85.19 |    82.1 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   76.92 |    75.71 |   73.68 |   76.92 | ...88,395-397,413 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   99.12 |    96.03 |      95 |   99.12 | 150,379-380       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.73 |    78.01 |   66.66 |   60.73 | ...1507,1524-1544 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   93.89 |    86.32 |      75 |   93.89 | ...39,489-490,506 
  sdk.ts           |    82.7 |     90.9 |   66.66 |    82.7 | ...00-204,242-264 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...ion-events.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |   91.49 |    88.77 |   96.87 |   91.49 | ...1797,1828-1831 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |   83.09 |     95.1 |   86.36 |   83.09 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |    80.53 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.35 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.38 |    98.61 |   83.33 |   96.38 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.27 |    85.09 |   88.72 |   86.27 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |   82.76 |    86.77 |   81.25 |   82.76 | ...45-746,865-915 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   80.03 |    86.58 |   89.47 |   80.03 | ...2272,2276-2279 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |      100 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.71 |    77.08 |   81.25 |   85.71 | ...96-912,958-959 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5036,5099-5100 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   78.22 |    84.21 |   83.33 |   78.22 | ...66,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   93.11 |    92.53 |   91.66 |   93.11 | ...69-570,586-592 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |   86.72 |    84.92 |   88.88 |   86.72 | ...25-828,865-900 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.02 |    87.31 |   88.69 |   87.02 |                   
  agent.ts         |   85.64 |    86.19 |   86.31 |   85.64 | ...4366,4400-4410 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   86.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.91 |    89.65 |   96.89 |   92.91 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   83.39 |    95.17 |    61.9 |   83.39 | ...81-397,401-407 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.95 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.08 |    93.33 |     100 |   95.08 | ...62-166,234-238 
  ...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.41 |    93.54 |     100 |   95.41 | ...27-328,370-373 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.11 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |   97.77 |    91.48 |     100 |   97.77 | 172-173           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |    83.96 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.07 |    88.34 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  ...-retention.ts |     100 |    95.83 |     100 |     100 | 116               
  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 |    87.5 |    86.13 |     100 |    87.5 | ...76-480,510-525 
  truncation.ts    |   90.61 |    90.43 |     100 |   90.61 | ...53-461,498-504 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   95.39 |    89.47 |     100 |   95.39 | ...16-317,321-322 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Maintainer verification: real local stack, head vs merge-base

I rebuilt this PR and its merge-base into two fully isolated trees and ran both as real qwen serve daemons against the same scripted model service, then reproduced the reported failure and the fix end-to-end — daemon REST, real Web Shell in a real browser, and the subagent detail path.

Verdict: the fix works, is backward compatible on the wire, and the new tests are non-vacuous. I found no blocking issue. Two minor observations at the bottom.

PR head 438957db89aa318b7451ca5f4809529c4f1fa41c
Merge-base 3fd40fd065b041bbc39c77211ceb2e7f9021e98c
Both trees npm run build + npm run bundle, run from dist/cli.js
Daemons head :8811, base :8812, --max-journal-events 32, isolated QWEN_HOME each
Model scripted OpenAI-compatible service, per-request JSONL ledger
Web Shell each daemon's own bundled dist/web-shell — the UI and the daemon always match

Scenario

One turn, two foreground subagents:

  1. root text <<ROOT_ALPHA>>agent tool call (subagent A)
  2. subagent A finishes normally — this is what makes the daemon emit the nested usage frame (agent_message_chunk + _meta.usage + _meta.parentToolCallId) that the parent transcript's token accounting consumes
  3. root text <<ROOT_BETA>>agent tool call (subagent B)
  4. subagent B streams 12,000 nested chunks and then hangs with no finish_reason

Step 4 leaves the turn permanently in-flight with no live traffic — the exact state a user refreshing mid-turn lands in, and race-free to snapshot. --max-journal-events 32 is a scaled-down stand-in for the production 10,000-event window so the eviction is reachable in seconds.

Evidence 1 — POST /session/:id/load

Every nested chunk carries a monotonic marker [[Nnnnnnn]], so the retained window is identifiable, not just measurable.

load request base 3fd40fd head 438957d
default (no liveReplayMode) 33 entries / 527,743 B, truncation marker (3,853 dropped, 8,160 kept), 0 root updates, window [[N003841]][[N012000]] byte-identical to base — 33 entries / 527,743 B, same marker, same window
liveReplayMode: 'full' same as default (option unknown, ignored) identical to default
liveReplayMode: 'summary' same as default (option unknown, ignored) 12 entries, no truncation marker, 11 root updates + 1 nested usage frame
liveReplayMode: 'compact' 200 (ignored) 400 invalid_live_replay_mode
resume + liveReplayMode 200 200, silently ignored (load-only)

The default path being byte-identical across base and head is the backward-compatibility proof for the SDK, /acp and every other existing consumer.

Summary journal composition on head (event ids 1–13; id 7 excluded):

id= 1     371B root   user_message_chunk  "FLOOD_TASK_TRIGGER run the audit"
id= 2  368618B root   available_commands_update
id= 3     329B root   agent_message_chunk "<<ROOT_ALPHA>> Kicking off the short probe subagent."
id= 4     421B root   tool_call        call_short_1  pending
id= 5     407B root   usage(in=1234,out=567)
id= 6     557B root   tool_call_update call_short_1  in_progress
id= 8     474B parent=call_short_1  usage(in=1234,out=567)   <-- nested usage frame, retained
id= 9     946B root   tool_call_update call_short_1  completed
id=10     343B root   agent_message_chunk "<<ROOT_BETA>> Probe done. Now running the verbose audit subagent."
id=11     422B root   tool_call        call_flood_1  pending
id=13     562B root   tool_call_update call_flood_1  in_progress
                      (id 7 = nested subagent text — correctly excluded)

So the projection keeps exactly what the design doc claims: root updates, both subagent lifecycles, tool state, and the nested _meta.usage frame — while dropping nested detail.

Evidence 2 — real Web Shell, real refresh

Driven in a real browser: type the prompt, wait for the flood, then reload the page mid-turn.

before and after

Recorded request bodies on the recovery load confirm the WebUI wiring rather than assuming it:

  • base: liveReplayMode: (absent) ×2 → restored message list is 226 chars, the truncation line only, no root markers
  • head: liveReplayMode: "summary" ×2 → restored message list contains <<ROOT_ALPHA>>, <<ROOT_BETA>>, both Agent rows and ↑1.2k ↓567 · 2 tool calls, no truncation notice

Note the base failure mode is worse than "some history missing": Web Shell does not render nested subagent detail in the main transcript, so the 8,160 nested events it did retain render as nothing at all.

Evidence 3 — subagent detail path unaffected

After the same refresh on head, opening the detail view shows 1,631 nested lines starting at [[N000001]] — including chunks the parent journal had already evicted (its full window starts at [[N003841]]). The detail view reads the event ring, not the compaction journal, and this PR does not touch it.

subagent detail

Evidence 4 — tests, and a mutation check

suite result
acp-bridge compactionEngine + eventBus 168 passed
acp-bridge bridge 583 passed
cli serve (-t "live replay mode") 3 passed
sdk-typescript DaemonClient 329 passed
webui DaemonSessionProvider 268 passed

To confirm the new tests actually constrain behaviour, I mutated isSummaryLiveJournalEvent to return true (making summary identical to full) and re-ran compactionEngine.test.ts: 5 failed / 104 passed, including the summary marker-anchor case. Mutation reverted afterwards.

Evidence 5 — cost of the second journal

The PR flags the extra journal as its main tradeoff, so I measured the worst case: a root-only in-flight turn (no subagent, so every event is summary-eligible and both journals hold the same content), default caps, filling the 8 MiB byte limit.

base 3fd40fd head 438957d
full journal on the wire 6,185,692 B (31 entries, truncated) 6,185,692 B (identical)
daemon RSS growth +87.2 MiB +87.8 MiB

Under 1% apart. The second journal does not duplicate payload: both journals push references to the same BridgeEvent objects, and the per-journal text segments hold references to the same chunk strings — only the entry bookkeeping is duplicated. The tradeoff is cheaper than the description implies.

Two minor observations (non-blocking)

  1. resume accepts a valid liveReplayMode and silently ignores it. An invalid value 400s at the route, but liveReplayMode: 'summary' on /resume returns 200 and is coerced to full replay by the bridge. This matches the stated load-only design and the SDK never sends it on resume, so nothing in-tree is affected — but a third-party client that does send it gets full replay with no signal. Rejecting it at the route would be more consistent with the invalid-value handling.

  2. The summary journal is not automatically small. In my run one root available_commands_update frame was 368 KB of the 374 KB summary total. That is not a regression (the same frame is a root event on base), but the summary window's headroom is governed by root frame sizes, so excluding nested detail is a large win only while root frames stay modest.

中文版

维护者验证:本地真实环境,head 与 merge-base 对照

我把本 PR 与其 merge-base 分别构建成两棵完全隔离的树,作为两个真实的 qwen serve daemon 跑在同一个脚本化模型服务上,然后端到端复现了问题与修复——覆盖 daemon REST、真实浏览器里的真实 Web Shell,以及 subagent 详情路径。

结论:修复有效,线上协议向后兼容,新增测试非空洞。未发现阻塞性问题。 文末有两点次要观察。

PR head 438957db89aa318b7451ca5f4809529c4f1fa41c
Merge-base 3fd40fd065b041bbc39c77211ceb2e7f9021e98c
两棵树 npm run build + npm run bundle,从 dist/cli.js 启动
Daemon head :8811、base :8812--max-journal-events 32,各自独立 QWEN_HOME
模型 脚本化 OpenAI 兼容服务,逐请求 JSONL 台账
Web Shell 各自 daemon 自带的 dist/web-shell——前后端天然同源

场景

一个回合,两个前台 subagent:

  1. 主会话文本 <<ROOT_ALPHA>>agent 工具调用(subagent A)
  2. subagent A 正常结束——这一步才会让 daemon 发出嵌套 usage 帧(agent_message_chunk + _meta.usage + _meta.parentToolCallId),即主会话统计所消费的那一帧
  3. 主会话文本 <<ROOT_BETA>>agent 工具调用(subagent B)
  4. subagent B 吐出 12,000 个嵌套 chunk 后挂住,不发 finish_reason

第 4 步让回合永久停在"进行中且无实时流量"的状态——正是用户中途刷新时的真实态,且读快照时不会与实时流竞态。--max-journal-events 32 是生产环境 10,000 事件窗口的等比缩小版,好让淘汰在几秒内可达。

证据一:POST /session/:id/load

每个嵌套 chunk 都带单调标记 [[Nnnnnnn]],所以保留窗口是可识别的,而不只是可计量的。

load 请求 base 3fd40fd head 438957d
默认(不带 liveReplayMode 33 条 / 527,743 B,截断标记(丢 3,853、留 8,160),主会话事件 0 条,窗口 [[N003841]][[N012000]] 与 base 逐字节一致——33 条 / 527,743 B,标记与窗口完全相同
liveReplayMode: 'full' 同默认(未知参数,被忽略) 与默认一致
liveReplayMode: 'summary' 同默认(未知参数,被忽略) 12 条,无截断标记,11 条主会话更新 + 1 条嵌套 usage 帧
liveReplayMode: 'compact' 200(被忽略) 400 invalid_live_replay_mode
resume + liveReplayMode 200 200,静默忽略(仅 load 生效)

默认路径在 base 与 head 上逐字节一致,这就是 SDK、/acp 及其它既有消费方的兼容性证明。

head 上 summary journal 的构成(事件 id 1–13,id 7 被排除):

id= 1     371B 主会话 user_message_chunk  "FLOOD_TASK_TRIGGER run the audit"
id= 2  368618B 主会话 available_commands_update
id= 3     329B 主会话 agent_message_chunk "<<ROOT_ALPHA>> ..."
id= 4     421B 主会话 tool_call        call_short_1  pending
id= 5     407B 主会话 usage(in=1234,out=567)
id= 6     557B 主会话 tool_call_update call_short_1  in_progress
id= 8     474B parent=call_short_1  usage(in=1234,out=567)   <-- 嵌套 usage 帧,已保留
id= 9     946B 主会话 tool_call_update call_short_1  completed
id=10     343B 主会话 agent_message_chunk "<<ROOT_BETA>> ..."
id=11     422B 主会话 tool_call        call_flood_1  pending
id=13     562B 主会话 tool_call_update call_flood_1  in_progress
                      (id 7 = 嵌套 subagent 文本,已正确排除)

可见该投影保留的内容与设计文档所述完全一致:主会话更新、两个 subagent 的生命周期、工具状态,以及嵌套 _meta.usage 帧;同时丢弃嵌套详情。

证据二:真实 Web Shell,真实刷新

在真实浏览器中驱动:输入提示词,等待 flood,然后在回合进行中刷新页面。

修改前后

恢复请求的报文体被逐条记录,用以证实(而非假定)WebUI 的接线:

  • base:liveReplayMode: (absent) ×2 → 恢复后的消息区仅 226 字符,只有那一行截断提示,无任何主会话标记
  • head:liveReplayMode: "summary" ×2 → 恢复后的消息区含 <<ROOT_ALPHA>><<ROOT_BETA>>、两条 Agent 行与 ↑1.2k ↓567 · 2 tool calls无截断提示

注意 base 的失效形态比"丢了一部分历史"更严重:Web Shell 主会话本就不渲染嵌套 subagent 详情,因此它保留下来的那 8,160 个嵌套事件在界面上什么都渲染不出来

证据三:subagent 详情路径未受影响

在 head 上做同样的刷新之后打开详情视图,可看到[[N000001]] 开始的 1,631 行嵌套内容——其中包含主会话 journal 早已淘汰的那些 chunk(其完整窗口从 [[N003841]] 才开始)。详情视图读的是 event ring 而非 compaction journal,本 PR 未触碰该路径。

subagent 详情

证据四:测试与变异检查

套件 结果
acp-bridge compactionEngine + eventBus 168 通过
acp-bridge bridge 583 通过
cli serve(-t "live replay mode" 3 通过
sdk-typescript DaemonClient 329 通过
webui DaemonSessionProvider 268 通过

为确认新增测试确实约束了行为,我把 isSummaryLiveJournalEvent 变异为 return true(使 summary 等同于 full)后重跑 compactionEngine.test.ts5 失败 / 104 通过,其中包括 summary 分页锚点用例。变异已还原。

证据五:第二个 journal 的代价

PR 自述把额外的 journal 列为主要取舍,因此我测了最坏情况:纯主会话的进行中回合(无 subagent,故所有事件都进 summary,两个 journal 内容相同),默认上限,打满 8 MiB 字节限额。

base 3fd40fd head 438957d
线上完整 journal 6,185,692 B(31 条,已截断) 6,185,692 B(完全一致)
daemon RSS 增长 +87.2 MiB +87.8 MiB

相差不足 1%。第二个 journal 并不会复制载荷:两个 journal 压入的是同一批 BridgeEvent 对象的引用,各自的文本 segment 也持有同一批 chunk 字符串的引用,被复制的只有条目簿记。该取舍比描述中所说的更廉价。

两点次要观察(非阻塞)

  1. resume 接受合法的 liveReplayMode 却静默忽略。 非法值会在路由层 400,但 /resumeliveReplayMode: 'summary' 会返回 200,随后被 bridge 强制为 full。这符合"仅 load 生效"的既定设计,且 SDK 在 resume 时从不发送该字段,仓内无任何影响——但第三方客户端若真的发了,会拿到完整回放且没有任何提示。在路由层直接拒绝会与非法值的处理更一致。

  2. summary journal 并不会自动变小。 我这次运行中,单个主会话 available_commands_update 帧就占了 374 KB 总量里的 368 KB。这不是回归(该帧在 base 上同样是主会话事件),但 summary 窗口的余量取决于主会话帧的大小,因此"排除嵌套详情"只在主会话帧本身不大时才是可观的收益。

yiliang114
yiliang114 previously approved these changes Aug 13, 2026

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

Approving. Reviewed the full diff at 438957d; the dual full/summary live-journal design is sound and the reduction does not silently drop anything summary consumers need.

Evidence:

  • Summary projection mirrors the Web Shell's existing client-side discard (projectMainTranscriptEvents): nested session_update frames with non-empty _meta.parentToolCallId are excluded, while root updates, all non-session events, and nested agent_message_chunk usage frames (numeric input/outputTokens) are retained — exactly what the main transcript's usage totals consume. Persisted transcript pagination and completed-turn compaction are unchanged (fullTranscriptAvailable: true), and default stays full for SDK//acp/existing callers, so the interactive non-subagent path is untouched.
  • Sequence integrity holds after filtering: retained events keep original ids in order, lastEventId/epoch remain shared across modes, and truncation markers are tracked per journal with per-journal recordId anchors (summary anchor correctly ignores excluded nested recordIds, verified for both seed and seedReplayEvents).
  • Restore coalescing now keys on liveReplayMode (mismatched projections get RestoreInProgressError instead of a wrong snapshot), invalid modes are rejected at both route (400 invalid_live_replay_mode) and bridge layers before any side effects, resume is pinned to full, and the registration-race path preserves the requested mode.
  • Both journals remain independently bounded by the existing maxJournalEvents/maxJournalBytes eviction policy; tests pin the reduction semantics end to end (independent limits, default-full compatibility, usage carve-out, marker anchors, validation/propagation at bridge/route/SDK/WebUI layers).
  • CI: all checks green on the head sha.

Non-blocking nits (agree with @wenshao's comments):

  1. P2 compactionEngine.ts: worst-case live-journal memory per session doubles (second journal at the same caps). Still bounded, but operators sizing from maxJournalBytes × sessions are now off by 2× — worth deriving summary caps as a fraction or documenting the 2× ceiling in the design doc / replayWindowLimits.
  2. P2 isSummaryLiveJournalEvent: missing the normalizer's self-parent guard — a frame with parentToolCallId === toolCallId (which the daemon should never emit) renders as a root tool block in the UI but is excluded from the summary journal, so a mid-turn Web Shell refresh would drop it until turn completion. Mirroring the guard here keeps the two projections in sync.
  3. P3 design doc: the summary-journal sentence omits the nested-usage carve-out that the implementation (and tests) deliberately keep; stating the exception prevents a future "simplification" from silently breaking subagent token accounting.
  4. P3: a valid liveReplayMode: 'summary' on resume is accepted by the route but silently coerced to full; consider rejecting or documenting (WebUI/SDK never send it on resume today).

The restore-coalesce fence compared liveReplayMode strictly, so a WebUI
summary load racing any full-mode load of the same session (keepalive
revive, acp-http clients, older WebUI tabs) threw restore_in_progress
instead of coalescing. The summary journal is a strict subset of the
full journal, so a summary waiter can safely share an in-flight full
restore and project the superset down. Only the reverse — a full
request joining a summary restore — would return a missing-detail
projection, so that direction stays fenced.
@ytahdn
ytahdn dismissed stale reviews from yiliang114 and qwen-code-ci-bot via 8c72bd2 August 13, 2026 08:07

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not explored to full depth (tool budget reached): "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started were completed within budget (~15 calls).; "You are review agent reverse-audit — Reverse audit agent…": did not read flattenReplaySegments /compacted-replay frame shapes in compactionEngine.ts to settle whether compacted turns retain raw user_message_chunk fram…; "You are review agent reverse-audit — Reverse audit agent…": none (~15 of 51 calls used).; "You are review agent reverse-audit — Reverse audit agent…": none — chunk fully read (un-truncated), all follow-up source checks completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks above completed within budget., and 4 more.

中文说明

未探索到全部深度(达到工具调用预算):"You are review agent reverse-audit — Reverse audit agent…"none — all checks I started were completed within budget (~15 calls)."You are review agent reverse-audit — Reverse audit agent…"did not read flattenReplaySegments /compacted-replay frame shapes in compactionEngine.ts to settle whether compacted turns retain raw user_message_chunk fram…"You are review agent reverse-audit — Reverse audit agent…"none (~15 of 51 calls used)."You are review agent reverse-audit — Reverse audit agent…"none — chunk fully read (un-truncated), all follow-up source checks completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all checks above completed within budget.,另有 4 条。

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

Comment on lines 5724 to 5726
historyPageSize !== inFlight.historyPageSize ||
(inFlight.liveReplayMode === 'summary' && liveReplayMode === 'full') ||
hideInheritedHistory !== inFlight.hideInheritedHistory

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] R1-1: A summary load coalescing onto an in-flight full restore receives the owner's unprojected full-mode journal — the projection promised by this fence's comment ("its waiter receives a superset and projects it down") is implemented nowhere. The coalesced waiter returns { ...restored, attached: true, ... } (~line 5804), where restored = await inFlight.publicPromise is the owner's result built by replayFieldsFor(entry, action, liveReplayMode) (~line 6349) at the owner's 'full' mode. There is no isSummaryLiveJournalEvent/parentToolCallId filtering anywhere in bridge.ts, and neither the route, the SDK, nor WebUI re-projects liveJournal.

The superset premise is additionally false under truncation: this PR's own design-doc compatibility bullet says the two journals "track truncation independently", so root events evicted from the full journal but retained in the summary journal cannot be recovered from the full tail.

Failure scenario (probe-verified at this commit): a long-running turn floods the full journal past its 10,000-event / 8 MiB cap with nested subagent events, evicting early root events while the summary journal retains them marker-free; a full-mode load (SDK / /acp / a full-mode tab) is in flight; a Web Shell refresh issues its recovery load with liveReplayMode: 'summary', passes this fence, and coalesces → the waiter receives the full journal's history_truncated marker plus a retained tail dominated by nested events Web Shell discards at render — the user sees History truncated for live turn replay with early root content missing: the exact symptom this PR exists to eliminate. Probe at this commit: the coalesced waiter received [history_truncated, nested chunk, root event]; recomputing the replay fields from the registered entry in the waiter's mode flipped it to the marker-free summary view [root, root]. The paired test 'lets a summary load coalesce onto an in-flight full restore' emits no events and asserts only attached/call-count, so it stays green regardless.

Recommended fix — in the coalesce waiter branch, when the waiter's mode differs from inFlight.liveReplayMode, recompute the replay fields from the registered entry (mirroring the registration-race path at ~line 6252, which already does this):

return {
  ...restored,
  attached: true,
  clientId,
  createdAt: entry.createdAt,
  hasActivePrompt: entry.promptActive,
  ...replayFieldsFor(entry, action, liveReplayMode),
};

and extend the coalesce test to ingest nested + root events under a small journal cap, asserting the waiter's liveJournal excludes nested frames and carries no history_truncated marker. A conservative one-click alternative is to fence the direction symmetrically (the waiter then gets RestoreInProgressError and attaches after settle):

Suggested change
historyPageSize !== inFlight.historyPageSize ||
(inFlight.liveReplayMode === 'summary' && liveReplayMode === 'full') ||
hideInheritedHistory !== inFlight.hideInheritedHistory
historyPageSize !== inFlight.historyPageSize ||
inFlight.liveReplayMode !== liveReplayMode ||
hideInheritedHistory !== inFlight.hideInheritedHistory
中文说明

[Critical] R1-1:summary 加载合并(coalesce)到正在进行中的 full 恢复时,收到的是 owner 未经投影的 full 模式 journal —— 此处注释承诺的投影(“waiter 收到超集并向下投影”)在任何地方都没有实现。合并后的 waiter 直接返回 { ...restored, attached: true, ... }(约 5804 行),而 restored = await inFlight.publicPromise 是 owner 用 replayFieldsFor(entry, action, liveReplayMode)(约 6349 行)按 owner 自己的 'full' 模式构建的结果。bridge.ts 中不存在任何 isSummaryLiveJournalEvent/parentToolCallId 过滤,route、SDK、WebUI 也都不会再次投影 liveJournal

超集前提在发生截断时同样不成立:本 PR 自己的设计文档兼容性条目写明两种 journal “独立跟踪截断”,因此被 full journal 逐出、但 summary journal 仍保留的根事件无法从 full 尾部恢复。

失败场景(已在本提交用探针验证):长时间运行的一轮让嵌套 subagent 事件冲垮 full journal 的 10,000 事件 / 8 MiB 上限,逐出早期根事件,而 summary journal 完整保留且无截断标记;此时一个 full 模式加载(SDK / /acp / full 模式标签页)正在进行;Web Shell 刷新发起带 liveReplayMode: 'summary' 的恢复加载,通过该栅栏并合并 → waiter 收到 full journal 的 history_truncated 标记和一段以嵌套事件为主的尾部(这些嵌套事件 Web Shell 渲染时会丢弃)—— 用户看到 History truncated for live turn replay 且早期根内容缺失:正是本 PR 要消除的症状。探针显示:合并后的 waiter 收到 [history_truncated, 嵌套 chunk, 根事件];改为按 waiter 模式从已注册 entry 重新计算 replay 字段后,变为无标记的 summary 视图 [根, 根]。配套测试 'lets a summary load coalesce onto an in-flight full restore' 不注入任何事件、只断言 attached/调用次数,因此无论如何都是绿的。

推荐修复 —— 在合并 waiter 分支中,当 waiter 模式与 inFlight.liveReplayMode 不同时,从已注册 entry 重新计算 replay 字段(与约 6252 行的注册竞争路径一致,该路径已经这样做了),见上方英文代码;并扩展合并测试:在小 journal 上限下注入嵌套 + 根事件,断言 waiter 的 liveJournal 不含嵌套帧且无 history_truncated 标记。保守的一键替代方案是对称地栅栏该方向(waiter 收到 RestoreInProgressError,待 settle 后再附加):见上方 suggestion 代码块。

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

Comment on lines +1026 to +1027
if (extractParentToolCallIdFromMeta(meta) === undefined) return true;
if (data?.update?.sessionUpdate !== 'agent_message_chunk') return false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R1-2: This exclusion branch for parented non-agent_message_chunk session updates (nested tool_call/tool_call_update frames) is exercised by no test — every nested event in the new engine and bridge tests is an agent_message_chunk (makeTextChunkWithParent).

Concrete cost: mutating the return false here to return true turns no test red (engine + eventBus suites 168/168, bridge summary tests 6/6), while the sibling usage-gate mutation fails 7 tests — the suites detect filter changes, they just never feed a parented non-chunk event into a summary assertion. A future regression retaining nested tool frames in the summary journal would ship green and let a long-running subagent's parented tool_call_update flood consume the summary journal's caps — reintroducing exactly the truncation this feature was written to prevent.

Suggested fix: add an engine test that ingests parented tool_call / tool_call_update frames between root events under a small maxJournalEvents, asserting snapshot('summary') excludes them while snapshot() retains them.

中文说明

[Suggestion] R1-2:针对带 parent 的非 agent_message_chunk 会话更新(嵌套 tool_call/tool_call_update 帧)的这条排除分支没有任何测试覆盖 —— 新增的 engine 与 bridge 测试中所有嵌套事件都是 agent_message_chunkmakeTextChunkWithParent)。

具体代价:把这里的 return false 突变为 return true 不会让任何测试变红(engine + eventBus 套件 168/168 通过,bridge summary 测试 6/6 通过),而相邻 usage 门限的突变会让 7 个测试失败 —— 说明套件能捕获过滤器变更,只是从未把带 parent 的非 chunk 事件喂进 summary 断言。未来若有回归让嵌套 tool 帧保留进 summary journal,将会一路绿灯地发布,使长时间运行 subagent 的嵌套 tool_call_update 洪流耗尽 summary journal 上限 —— 重新引入本功能要防止的截断。

建议修复:新增一个 engine 测试,在较小的 maxJournalEvents 下,于根事件之间注入带 parent 的 tool_call / tool_call_update 帧,断言 snapshot('summary') 排除它们而 snapshot() 保留它们。

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

wenshao
wenshao previously approved these changes Aug 13, 2026
@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

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

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 2878 passed · 0 failed · 2878 total

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

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

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

Verification report

PR 9057 verification — fix(daemon): reduce subagent live replay journal

Verdict: merge-ready — 2878/2878 scripted assertions passed (0 unexpected failures), verified head 8c72bd2775e717d2e852574bf74503e485538a89 (git rev-parse HEAD^2; base 52cfb18972).

中文摘要
  • 结论: merge-ready。2878 条脚本化断言全部通过,0 个意外失败。
  • A/B 结论: 核心声明成立。在真实生产上限(10,000 事件 / 8 MiB)下,base 的 summary 刷新 load 只能拿回被截断的 full journal(S1: 10001 条 + 截断标记;S2: 29 条 + 截断标记);head 的 snapshot('summary') 返回无标记的精简投影(S1: 5 条 = 根事件 + usage 帧;S2: 3 条根事件),且 full journal 行为两臂逐字节一致(兼容性控制)。见 01-ab-base-summary-load-truncated.png / 02-ab-head-summary-load-clean.png
  • 变异矩阵: 6 个变异(过滤器失效、fence 删除、fence 反向、REST 校验删除、bridge 模式传播失效、既有驱逐循环正对照)全部按预期被杀,无幸存者;新测试非空转。
  • Findings: 1 个低严重度观察(非阻塞)——summary load 合并到进行中的 full restore 时,waiter 直接继承 owner 的 full replay 字段(含可能的截断标记),“投影”只发生在客户端内容过滤层;窗口很窄且严格优于旧的 restore_in_progress 行为。另 1 个信息级:usage 保留仅对 agent_message_chunk 生效,agent_thought_chunk 的 usage 帧被排除(与实现一致,设计文档措辞可更精确)。
  • 未覆盖: 真实浏览器 E2E、真实 daemon 端到端、逐 commit 归因(浅克隆,仅 head commit 可达)、已完成轮次的持久化分页 E2E。

Central claim + A/B

Central claim: a Web Shell refresh during a verbose subagent turn no longer returns the truncated live journal — summary loads get an independently bounded projection that excludes nested subagent detail while retaining root events, subagent lifecycle/tool state, and nested usage frames; default loads keep the complete journal.

Harness ab-journal.mjs drives the compiled TurnBoundaryCompactionEngine (production defaults 10,000 entries / 8 MiB) through one live turn per scenario; snapshot('summary') is the exact call the refreshed WebUI's load makes. Base arm = tmp/base-tree worktree at HEAD^1, rebuilt with the same root node_modules (lockfile untouched by the PR; the engine module chain imports only node:crypto + local files, so no internal workspace link is crossed — verified by reading the import graph and by the worktree having no node_modules of its own).

arm scenario full snapshot (default) snapshot('summary') scripted result
base S1 tool-heavy (12k nested tool events) 10001 entries, marker YES (truncated=2005) 10001 entries, marker YES, nested=9997 (mode silently ignored) 10/10 as-broken
base S2 text-heavy (~40 MB nested text) 29 entries, marker YES (truncated=33282) 29 entries, marker YES (identical to full) (same run)
head S1 tool-heavy 10001 entries, marker YES (truncated=2005) 5 entries, marker NO[1, 2, 6003, 9004, 12005] (root + usage frame) 15/15 as-fixed
head S2 text-heavy 29 entries, marker YES (truncated=33282) 3 entries, marker NO[1, 2, 40003] (same run)

Witnesses: 01-ab-base-summary-load-truncated.png, 02-ab-head-summary-load-clean.png. The full-journal column is byte-identical across arms (same entry counts, same truncatedEvents) — the backward-compatibility control ran on both arms and shows the PR changes nothing for default loads. In S2 the full journal truncates 33,282 events while the summary journal carries no marker at all: the two caps are genuinely independent.

Secondary claims, each with its own scripted probe:

  • Directional coalesce fence (commit 2): summary joins an in-flight full restore (1 agent loadSession call, waiter attached: true); full after summary stays fenced with RestoreInProgressError. Pinned by bridge.test.ts and by mutations M2/M3 below.
  • Load-only option, validated at both boundaries: REST returns 400 invalid_live_replay_mode for bad values on load and resume; SDK wire probe (sdk-wire-probe.ts, real DaemonClient against a recording fetch): load sends {"cwd":"/w","liveReplayMode":"summary"}, load-omitted sends no key, resume strips the option even when the caller passes it (05-sdk-wire-load-vs-resume.png).

Mutation matrix (vacuity + guards)

All mutations applied in scratch edits of the head source, targeted vitest run, then reverted (git status clean after each revert).

# mutation suite result
M1 isSummaryLiveJournalEvent → true (summary == full) compactionEngine.test.ts killed: exactly the 5 new summary tests red (104 others green); kill assertion quoted: expected { …history_truncated… } to be undefined — the intended behavioral mismatch (03-vacuity-filter-disabled-kills-5-new-tests.png)
M2 delete directional fence clause bridge.test.ts coalesce pair killed: rejects a full load joining an in-flight summary restore fails (coalesces instead of rejecting); sibling passes
M3 flip fence (full joins summary fenced instead) bridge.test.ts coalesce pair killed: both coalesce tests fail (2/2)
M4 remove REST 400 validation cli server.test.ts live-replay tests killed: both invalid-mode tests fail expected 200 to be 400; passthrough test green
M5 hardcode bridge liveReplayMode = 'full' bridge.test.ts killed: selects summary live replay… + preserves summary replay when a restore loses the registration race fail; the 4 invalid-value tests still pass (validation independent of propagation)
PC disable journal eviction loop (pre-existing mechanism) compactionEngine.test.ts killed by 5+ pre-existing DAEMON-009 cap tests — positive control proving the suite is live

No survivors: every guard the PR introduces is pinned by a test that fails for the intended reason, and the positive control proves the harness can make the suite red.

Boundary probe (filter siblings)

boundary-probe.mjs against head dist: 11/11 as designed (04-filter-boundary-probe-11-of-11.png). Notables: parentToolCallId: '' and non-string/_meta-not-object are treated as root (retained — fail-open toward more content, the safe direction); string-valued inputTokens and usage: null excluded; inputTokens: 0 retained; nested thought chunks with numeric usage excluded (usage retention is message-chunk-only — see F2).

Targeted gates

gate result
packages/acp-bridge full suite (final tree state) 1300/1300 passed, 26 files
packages/cli src/serve/server.test.ts 935 passed + 1 skipped (936)
packages/sdk-typescript test/unit/DaemonClient.test.ts 329/329
packages/webui DaemonSessionProvider.test.tsx 268/268
npm run typecheck (repo-wide, --workspaces --if-present) exit 0; all four touched packages define the script; acp-bridge + cli re-run explicitly, exit 0

Findings

F1 (low, non-blocking) — a summary load that coalesces onto an in-flight full restore inherits the owner's full replay fields, including a live-journal truncation marker if the full journal truncated during that restore. The coalesce branch (bridge.ts:5752 restored = await inFlight.publicPromisereturn { ...restored, attached: true, … } at ~5787) spreads the owner's result verbatim; there is no re-projection to the waiter's mode. The commit message's "projects the superset down" happens client-side (Web Shell discards nested content), but a history_truncated marker is a status event, not content — so in that race a refreshed Web Shell can still show the truncation notice this PR removes. Bounding it: the window requires (a) a concurrent full-mode cold restore of the same session (keepalive revive, /acp client, older tab) and (b) >10k events / >8 MiB arriving during that restore. The alternative (pre-this-commit behavior) was restore_in_progress fencing — an error with no data — so the change is strictly an improvement, and base WebUI loads were always full-mode anyway, so nothing regresses versus base. The design doc states the superset tradeoff but does not discuss the marker; a one-line doc note (or re-running replayFieldsFor(entry, action, liveReplayMode) for coalescers after the entry exists) would close it. Not blocking.

F2 (informational) — usage retention applies only to nested agent_message_chunk. A nested agent_thought_chunk carrying numeric _meta.usage is excluded from the summary journal (boundary probe row 8). This matches the implementation and the main-transcript consumer's needs, but the design doc's "nested usage frames" phrasing reads broader than the code. Suggest tightening the doc sentence; no behavior change implied.

No injection attempts observed in PR text; author claims were treated as hypotheses and each was exercised above.

Not covered

  • Real-browser E2E of the refresh flow (Reviewer Test Plan steps 1–2 in a live Web Shell): no browser/credentials in this container. Covered instead at provider (268 webui tests incl. summary-mode load/reconnect), SDK wire, REST route, bridge, and engine layers.
  • Real daemon end-to-end (qwen serve + live ACP agent): not driven; the changed surface was exercised through the compiled dist/ engine, the real DaemonClient, and the project's bridge/route test harnesses.
  • Per-commit attribution: shallow depth-2 checkout makes only 8c72bd27 locally reachable; 438957db (first commit) is not. The aggregate HEAD^1..HEAD diff was verified; commit-2's coalesce claim was exercised at head via M2/M3 and the coalesce tests.
  • Completed-turn persistence pagination / subagent detail view (Test Plan step 6): unchanged surface; engine-level retention of compacted turns is pinned by the PR's own green tests, not by my harness.
  • Platform-specific behavior (macOS/Windows): N/A, Linux container.

Methodology

Environment: node:22-bookworm CI verify container, merge-ref checkout (HEAD merge, HEAD^1 base, HEAD^2 head), npm ci + npm run build pre-run at head. The A/B harness imports the compiled compactionEngine.js from each arm's own dist/ (base rebuilt in tmp/base-tree via root tsc); the module chain is dependency-free beyond node:crypto, so the control differs from head by exactly the PR's engine change. SDK probe drives the real DaemonClient source via tsx against a recording fetch stub. Mutation cells were scratch edits reverted after each run; tree verified clean. Raw logs in logs/, harnesses in this directory, captures in evidence/. Assertion tally: 25 (A/B) + 11 (boundary) + 4 (SDK wire) + 6 (mutation expectation cells) + 2832 (final green gate tests: 1300+935+329+268) = 2878; the 1 skipped cli test is not counted; mutation-induced reds are expected and counted as met expectations, never as failures.

Evidence images

01-ab-base-summary-load-truncated

02-ab-head-summary-load-clean

03-vacuity-filter-disabled-kills-5-new-tests

04-filter-boundary-probe-11-of-11

05-sdk-wire-load-vs-resume

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

The bot already has a review of its own on 8c72bd2775e717d2e852574bf74503e485538a89, which still stands.

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

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

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

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

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

Copy link
Copy Markdown
Collaborator

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

中文说明

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

@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /resolve

Merge origin/main — adaptive live-journal growth (#8905) — into the
summary live-replay branch: the growth advisor now operates on the
shared journal state object and measures retention against whichever
journal (full or summary) breaches its caps.

Review feedback addressed:

- Critical R1-1: a summary load that coalesces onto an in-flight full
  restore recomputes its own-mode replay fields from the registered
  entry instead of inheriting the owner's unprojected full journal,
  which could carry nested frames and a history_truncated marker the
  summary journal never earned. Extended the coalesce test to flood a
  capped journal and pin the waiter's projected, marker-free view.
- Mirror the UI normalizer's self-reference guard in the summary
  journal filter: a tool frame whose parentToolCallId equals its own
  toolCallId renders as a root block live, so it must survive a
  mid-turn summary refresh.
- R1-2: cover the parented non-chunk exclusion branch (nested
  tool_call/tool_call_update frames) with a capped engine test; the
  branch previously had no test and the reviewer's mutation survived.
- Document the usage carve-out exceptions in the design doc (it
  contradicted the implementation), and document the 2x per-session
  journal memory ceiling (full + summary share one cap pair) in
  replayWindowLimits, the engine options, and daemon diagnostics.
@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 #9057

Merged origin/main into the PR branch (required conflict resolution) and addressed all five inline review findings. One commit: 839e6f5a73.

Conflict resolution (--conflict true)

  • packages/acp-bridge/src/compactionEngine.ts — our PR refactored the journal into two LiveJournalState objects (full + summary); upstream feat(serve): adaptively grow live-journal caps... (#8905) added a growth advisor on the old flat arrays. Resolved by integrating the growth machinery into the journal-state abstraction: the growth check, maybeGrowJournalLimits(journal), and retainedTailCount(journal, ...) now operate on whichever journal breaches its caps; resetJournal() keeps both journal resets plus upstream's growth-refusal reset (with its comment). All upstream growth tests pass unmodified against the integration.
  • packages/acp-bridge/src/bridge.test.ts — both sides added adjacent tests at the same location; kept both (our summary-replay test + upstream's adaptive live-journal growth pool describe block).

Inline findings

  1. [Critical] rc:3774249681 — R1-1: coalesced summary waiter inherits the owner's unprojected full journal — FIXED. In the coalesce branch of restoreSession, when the waiter's liveReplayMode differs from the in-flight owner's mode (the only asymmetric direction the fence admits), the bridge now recomputes the waiter's replay fields from the registered entry — the exact expression the existing-entry attach path uses (refreshedReplayFieldsFor when a history page size was requested, replayFieldsFor otherwise). The waiter no longer inherits the owner's full-mode journal or its history_truncated marker, and the fence comment no longer claims a client-side projection that was never implemented. The extended coalesce test floods the restore's journal past a two-entry cap with nested frames between root frames and pins: owner view carries the marker; coalesced waiter view is marker-free, excludes nested frames, and retains both root frames. Mutation check: reverting the re-projection fails this test.
  2. rc:3772919251 — missing normalizer self-parent guard — FIXED. isSummaryLiveJournalEvent now treats _meta.parentToolCallId === update.toolCallId as root, mirroring normalizeToolUpdate's self-reference guard, so a self-referencing tool frame that renders live in the main transcript also survives a mid-turn summary refresh. New engine test pins it; removing the guard fails the test.
  3. rc:3772920703 — design doc contradicts the implementation — FIXED. docs/design/live-journal-truncation-recovery.md now states both exceptions to the parent-exclusion rule: the nested-usage carve-out (and why it is load-bearing for subagent token accounting) and the self-parent normalization. The coalesce paragraph now describes the daemon-side re-projection instead of the unimplemented client-side projection.
  4. rc:3772917640 — per-session live-journal memory ceiling doubles — RESOLVED via the documentation option the reviewer explicitly offered. The 2× ceiling is now documented in replayWindowLimits.ts (note on JOURNAL_GROWTH_HARD_CAP_BYTES), the engine options doc comment, BridgeDaemonSessionDiagnostic (daemon status), and the design doc: one in-flight turn retains two journals under one shared cap pair, so sizing must double the journal term, including any adaptively grown cap. I deliberately did NOT change the growth pool to charge 2×: upstream's growth tests pin exact grant accounting, and re-charging would change granted caps in that feature's own pinned scenarios — if the growth-pool owner wants strict 2× accounting, that is a small follow-up on their feature.
  5. [Suggestion] rc:3774249704 — R1-2: parented non-chunk exclusion branch untested — FIXED. New engine test ingests parented tool_call_update frames between root tool frames under maxJournalEvents: 2 and asserts snapshot('summary') excludes them (marker-free, root frames only) while snapshot() retains the truncated tail. Mutation check: flipping the branch's return false to return true — the exact mutation the reviewer reported as surviving — now fails this test.

Issue-level observations (not inline threads)

  • @wenshao minor observation 1 (resume accepts a valid liveReplayMode and silently ignores it): DECLINED for this round — making /resume reject valid modes is a wire-behavior change beyond this fix's scope; the documented design is load-only coercion and the SDK strips the field on resume. Happy to do it as a follow-up if the maintainer wants the stricter route behavior.
  • @wenshao minor observation 2 (summary journal is not automatically small): acknowledged; informational, and covered by the same ceiling documentation.
  • web-shell visual preview bot (no screenshot changed although DaemonSessionProvider.tsx is render-shaping): the change is load-time wiring (sending liveReplayMode), exercised by the provider's 268 unit tests; adding a visual scenario that drives a summary-mode load flow is new work beyond this review round.
  • Failed check "Real daemon E2E / Java 11": this is the daemon-e2e job of .github/workflows/sdk-java.yml on self-hosted runners. origin/main merged ci(sdk-java): drop the shared Maven toolchains.xml before setup-java on self-hosted runners #9090 (ci(sdk-java): drop the shared Maven toolchains.xml before setup-java on self-hosted runners), which addresses exactly this job's setup failure mode; that fix is now part of this branch through the merge. The default load path is byte-identical between base and head (maintainer A/B evidence), so no behavioral impact on that E2E is expected from this PR's changes.

Verification

  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0, all workspaces)
  • npm run lint — passed (exit 0)
  • npm run bundle — passed (exit 0)
  • packages/acp-bridge: npx vitest run (whole package) — 28 files / 1381 tests passed
  • packages/cli: npx vitest run src/serve/server.test.ts — 935 passed, 1 skipped
  • packages/sdk-typescript: npx vitest run test/unit/DaemonClient.test.ts — 329 passed
  • packages/webui: npx vitest run src/daemon/session/DaemonSessionProvider.test.tsx — 268 passed
  • Integration (after bundle, QWEN_SANDBOX=false): cli/qwen-serve-live-journal-recovery.test.ts (2), cli/qwen-serve-webui-live-journal-recovery.test.ts (1), cli/qwen-serve-routes.test.ts (36) — 39 passed
  • Mutation checks on the new tests: 3/3 killed (self-parent guard removed → test red; exclusion branch flipped to return true → test red; coalesce re-projection reverted → extended coalesce test red)
中文说明

Autofix 评审轮次 — PR #9057

已将 origin/main 合并进 PR 分支(必需的冲突解决),并处理了全部五条行内评审意见。单个提交:839e6f5a73

冲突解决(--conflict true

  • packages/acp-bridge/src/compactionEngine.ts —— 本 PR 将 journal 重构为两个 LiveJournalState 对象(full + summary);上游 feat(serve): adaptively grow live-journal caps... (#8905) 在旧的扁平数组上新增了增长顾问(growth advisor)。解决方式是把增长机制整合进 journal 状态抽象:增长检查、maybeGrowJournalLimits(journal)retainedTailCount(journal, ...) 现在作用于实际越界的那个 journal;resetJournal() 同时保留两个 journal 的重置以及上游的增长拒绝重置(连同其注释)。上游全部增长测试在该整合上原样通过。
  • packages/acp-bridge/src/bridge.test.ts —— 双方在同一位置相邻新增了测试;两者都保留(我们的 summary-replay 测试 + 上游的 adaptive live-journal growth pool describe 块)。

行内意见

  1. [Critical] rc:3774249681 —— R1-1:合并(coalesce)的 summary waiter 继承了 owner 未投影的 full journal —— 已修复。在 restoreSession 的合并分支中,当 waiter 的 liveReplayMode 与进行中的 owner 模式不同(栅栏唯一允许的不对称方向)时,bridge 现在从已注册的 entry 重新计算 waiter 的回放字段 —— 与"已存在 entry 的 attach 路径"完全相同的表达式(带历史分页时用 refreshedReplayFieldsFor,否则用 replayFieldsFor)。waiter 不再继承 owner 的 full 模式 journal 或其 history_truncated 标记;栅栏注释也不再宣称那个从未实现的客户端投影。扩展后的合并测试用嵌套帧淹没一个 2 条目上限的恢复期 journal(根帧夹在嵌套帧之间),并钉住:owner 视图带截断标记;合并的 waiter 视图无标记、不含嵌套帧、保留两个根帧。变异检查:还原该重投影会使此测试失败。
  2. rc:3772919251 —— 缺少 normalizer 的自引用 parent 守卫 —— 已修复。isSummaryLiveJournalEvent 现在把 _meta.parentToolCallId === update.toolCallId 视为主会话(root)事件,与 normalizeToolUpdate 的自引用守卫保持一致,因此一个自引用的 tool 帧在主会话中实时可见的同时,也能在回合进行中的 summary 刷新后保留。新增引擎测试钉住该行为;移除该守卫会使测试失败。
  3. rc:3772920703 —— 设计文档与实现矛盾 —— 已修复。docs/design/live-journal-truncation-recovery.md 现在写明 parent 排除规则的两个例外:嵌套 usage 帧的豁免(及其对 subagent token 统计的关键作用),以及自引用 parent 的归一化。合并(coalesce)段落也改为描述 daemon 侧的重投影,而不再是未实现的客户端投影。
  4. rc:3772917640 —— 单会话 live-journal 内存上限翻倍 —— 采用评审人明确给出的文档方案解决。2× 上限现已写入 replayWindowLimits.tsJOURNAL_GROWTH_HARD_CAP_BYTES 注释)、引擎 options 文档注释、BridgeDaemonSessionDiagnostic(daemon 状态)与设计文档:一个进行中的回合在同一组上限下保留两个 journal,因此容量估算必须把 journal 一项翻倍,自适应增长后的上限同样适用。我刻意没有把增长池改为按 2× 计费:上游增长测试钉死了精确的授予核算,重新计费会改变该功能自身已钉住场景中的授予上限 —— 如果增长池的 owner 希望严格的 2× 核算,可作为其功能上的一个小后续。
  5. [Suggestion] rc:3774249704 —— R1-2:带 parent 的非 chunk 排除分支无测试 —— 已修复。新增引擎测试在 maxJournalEvents: 2 下,于根 tool 帧之间注入带 parent 的 tool_call_update 帧,断言 snapshot('summary') 排除它们(无标记、仅根帧)而 snapshot() 保留被截断的尾部。变异检查:把该分支的 return false 翻转为 return true —— 即评审人报告可以存活的那个变异 —— 现在会使该测试失败。

Issue 级观察(非行内线程)

  • @wenshao 次要观察 1resume 接受合法 liveReplayMode 却静默忽略):本轮拒绝 —— 让 /resume 拒绝合法模式属于超出本次修复范围的线上行为变更;既定设计是"仅 load 生效"的强制归一化,且 SDK 在 resume 时会剥离该字段。若维护者希望更严格的路由行为,可作后续处理。
  • @wenshao 次要观察 2(summary journal 并不会自动变小):已知悉;纯信息性,已由同一处上限文档覆盖。
  • web-shell 视觉预览机器人(尽管改动了 DaemonSessionProvider.tsx 但无截图变化):该改动是 load 时机接线(发送 liveReplayMode),由 provider 的 268 个单测覆盖;新增一个驱动 summary 模式 load 流程的视觉场景属于本轮评审之外的新工作。
  • 失败检查 "Real daemon E2E / Java 11":即 .github/workflows/sdk-java.yml 在自托管 runner 上的 daemon-e2e 任务。origin/main 已合入 ci(sdk-java): drop the shared Maven toolchains.xml before setup-java on self-hosted runners #9090ci(sdk-java): drop the shared Maven toolchains.xml before setup-java on self-hosted runners),正是针对该任务安装环节失败模式的修复;该修复已随本次合并进入本分支。默认 load 路径在 base 与 head 之间逐字节一致(维护者 A/B 证据),因此本 PR 的改动预期不会影响该 E2E 的行为。

验证

  • npm run build —— 通过(exit 0)
  • npm run typecheck —— 通过(exit 0,全部 workspace)
  • npm run lint —— 通过(exit 0)
  • npm run bundle —— 通过(exit 0)
  • packages/acp-bridgenpx vitest run(整包)—— 28 个文件 / 1381 个测试通过
  • packages/clinpx vitest run src/serve/server.test.ts —— 935 通过,1 跳过
  • packages/sdk-typescriptnpx vitest run test/unit/DaemonClient.test.ts —— 329 通过
  • packages/webuinpx vitest run src/daemon/session/DaemonSessionProvider.test.tsx —— 268 通过
  • 集成测试(bundle 之后,QWEN_SANDBOX=false):cli/qwen-serve-live-journal-recovery.test.ts(2)、cli/qwen-serve-webui-live-journal-recovery.test.ts(1)、cli/qwen-serve-routes.test.ts(36)—— 39 通过
  • 针对新测试的变异检查:3/3 被杀(移除自引用守卫 → 测试变红;排除分支翻转为 return true → 测试变红;还原合并重投影 → 扩展后的合并测试变红)

Base-conflict check · 基分支冲突检查: conflicted with main — resolved in this push. · 与 main 有冲突——已在本次推送中解决。

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


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

Qwen Code did not run conflict resolution for this request.

PR #9057 does not currently have merge conflicts with main.

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

中文说明

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed. Suggestions are inline.

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

Not explored to full depth (tool budget reached): "You are review agent reverse-audit — Reverse audit agent…": none — all checks above completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started completed within budget..

中文说明

仅完成部分审查,审查缺口已披露。 建议见行内评论。

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

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

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

Comment on lines 859 to +861
private resetJournal(): void {
this.liveJournal = [];
this.journalEntryBytes = [];
this.journalEntryEvents = [];
this.journalTotalBytes = 0;
this.journalTotalEvents = 0;
this.journalTruncatedEvents = 0;
this.liveJournalTextSegment = undefined;
this.fullJournal = createLiveJournalState();
this.summaryJournal = createLiveJournalState();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-1: the summary-journal reset at the turn boundary has no test fence. Probe-verified mutation: removing this.summaryJournal = createLiveJournalState(); from resetJournal() passes the whole compactionEngine + bridge suites (130 + 594 tests green).

Failure scenario: compactCurrentTurn calls resetJournal() on turn_complete/turn_error. If a future edit resets only fullJournal, every current test stays green, and a later summary-mode session/load mid-turn N+1 returns turns 1..N's root frames in both compactedReplay and liveJournal — duplicated prior-turn content in the restored transcript — plus stale truncatedEvents/summaryRecordId leaking into a marker.

Suggested fix — in keeps an independent summary journal without nested subagent updates, after engine.ingest(makeTurnComplete(102)):

expect(engine.snapshot('summary').liveJournal).toEqual([]);
中文说明

[Suggestion] R2-1:回合边界处 summary journal 的重置没有测试保护。已用探针验证变异:从 resetJournal() 中删除 this.summaryJournal = createLiveJournalState(); 后,compactionEnginebridge 全部测试(130 + 594 个)仍然通过。

失败场景: compactCurrentTurn 会在 turn_complete/turn_error 时调用 resetJournal()。若未来某次修改只重置 fullJournal,现有测试会全部保持绿色,而之后在第 N+1 轮进行中发起的 summary 模式 session/load,会在 compactedReplayliveJournal 中同时返回第 1..N 轮的根帧——恢复出的转录出现重复的上一轮内容——并且过期的 truncatedEvents/summaryRecordId 会泄漏进截断标记。

建议修复——在 keeps an independent summary journal without nested subagent updates 测试中,engine.ingest(makeTurnComplete(102)) 之后补充上述断言。

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

Comment on lines 5821 to 5823
historyPageSize !== inFlight.historyPageSize ||
(inFlight.liveReplayMode === 'summary' && liveReplayMode === 'full') ||
hideInheritedHistory !== inFlight.hideInheritedHistory

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-2: same-mode summary→summary coalescing is untested. The new tests cover summary-joins-full and the full-joins-summary fence, and pre-existing tests cover full→full, but no test has a summary waiter join an in-flight summary restore. Probe-verified mutation: simplifying this fence condition to inFlight.liveReplayMode === 'summary' (fencing every summary-owned restore) passes the entire bridge suite.

Failure scenario: under that mutation, a second concurrent summary-mode load — e.g. a Web Shell reconnect racing another summary client restoring the same unregistered session — fails with RestoreInProgressError instead of coalescing, and nothing in CI turns red.

Suggested fix: add a bridge test with two loadSession({ liveReplayMode: 'summary' }) calls on the same session while the first restore is in flight; expect one agent loadSession call and both responses carrying the marker-free summary projection.

中文说明

[Suggestion] R2-2:summary→summary 同模式合并(coalescing)没有测试覆盖。新增测试覆盖了 summary 并入 full、以及 full 并入 summary 被栅栏拦截两种情况,既有测试覆盖 full→full,但没有测试让一个 summary waiter 并入正在进行中的 summary 恢复。已用探针验证变异:把该栅栏条件简化为 inFlight.liveReplayMode === 'summary'(栅栏拦截所有 summary 持有的恢复)后,bridge 全部测试仍然通过。

失败场景: 在该变异下,第二个并发的 summary 模式加载——例如 Web Shell 重连与另一个正在恢复同一未注册会话的 summary 客户端竞争——会收到 RestoreInProgressError 而不是合并,且 CI 中没有任何测试变红。

建议修复:新增一个 bridge 测试,在同一会话的首个恢复仍在进行时发起两个 loadSession({ liveReplayMode: 'summary' }) 调用;断言 agent 的 loadSession 只被调用一次,且两个响应都携带无截断标记的 summary 投影。

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

Comment on lines +19 to +24
* Memory-ceiling note: one in-flight turn retains TWO journals that share
* these caps — the `full` journal plus the `summary` projection for
* summary-mode loads — so a session's live-journal heap is bounded by
* twice the effective cap (2x the baseline, or 2x the grown cap under
* adaptive growth), not one. Operators sizing daemon memory from
* `maxJournalBytes x live sessions` must double the journal term.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-4: the adaptive-growth pool still charges one journal's worth of growth per session, but this diff makes the worst-case live-journal heap two journals × the granted cap. Probe at this commit: with maxJournalBytes=65536 on a root-only stream, one session retains full=65449 + summary=65449 bytes — ratio 2.00 — while the pool charges one cap of growth.

Failure scenario: journalGrowthPolicy.grant() charges Σ(limitBytes − baselineBytes) per session. After this diff a fully-grown session retains ~512 MiB while charged ~248 MiB (hard cap 256 MiB × 2); with grants summing to pool P, daemon journal heap can reach ~2P + 2×baseline×sessions against a budget modeled for P + baseline×sessions — silently exceeding the operator's memory budget. The operator-facing note above covers the sizing, but the pool's own rationale ("still cover[s] several fully-grown sessions") is now overstated by 2× and is not updated.

Suggested fix: charge the pool for the dual-journal reality (double the charged limitBytes, or halve the effective pool), or explicitly state the accepted 2× over-commit in the growth-policy docstring.

中文说明

[Suggestion] R2-4:自适应增长池仍按每会话一个 journal 的增长计费,但本 diff 使最坏情况下的 live-journal 堆达到两个 journal × 授予上限。已在本提交用探针验证:maxJournalBytes=65536、纯根事件流下,单个会话保留 full=65449 + summary=65449 字节——比值 2.00——而增长池只按一个上限计费。

失败场景: journalGrowthPolicy.grant() 按每会话 Σ(limitBytes − baselineBytes) 计费。本 diff 之后,一个完全增长的会话实际保留约 512 MiB,却只按约 248 MiB 计费(硬上限 256 MiB × 2);若授予总和为池 P,daemon 的 journal 堆可达约 2P + 2×baseline×sessions,而预算模型只按 P + baseline×sessions 建模——从而悄无声息地超出运维的内存预算。上方面向运维的注释已覆盖容量估算,但增长池自身的依据("仍能覆盖数个完全增长的会话")现在被夸大了 2 倍且未更新。

建议修复:让增长池按双 journal 的现实计费(把计费的 limitBytes 翻倍,或把有效池减半),或在增长策略的 docstring 中明确写明接受 2× 超额承诺。

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

Comment thread packages/acp-bridge/src/bridge.ts Outdated
Comment on lines +5910 to +5913
const waiterReplayFields =
liveReplayMode !== inFlight.liveReplayMode
? historyPageSize !== undefined
? await refreshedReplayFieldsFor(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-6: the refreshedReplayFieldsFor arm of this coalesced-waiter recompute (mixed-mode waiter that requested a historyPageSize) is never exercised by any test — the mixed-mode coalescing tests all omit historyPageSize, so every coalescing waiter takes the replayFieldsFor arm. Probe-verified mutation: swapping the third argument to inFlight.liveReplayMode (the owner's mode) passes the entire bridge suite. The current code is correct; only the regression protection is missing.

Failure scenario: under that mutation, a summary client coalescing onto an in-flight full restore with historyReplay: 'response' + historyPageSize (whose settle fallback fires) would silently receive the owner's full-mode projection — nested subagent frames plus the full journal's history_truncated marker. The same call shape IS tested on the existing-entry attach path (bridge.test.ts:5126-5132); only this waiter-side wiring is unguarded.

Suggested fix: add a coalescing test where owner and waiter both pass historyReplay: 'response' with the same historyPageSize but different liveReplayMode (with a prompt active at settlement so the fallback fires), and assert the waiter's journal is summary-projected.

中文说明

[Suggestion] R2-6:合并 waiter 重计算中的 refreshedReplayFieldsFor 分支(请求了 historyPageSize 的混合模式 waiter)没有任何测试覆盖——混合模式合并测试都未传 historyPageSize,因此每个合并 waiter 都走 replayFieldsFor 分支。已用探针验证变异:把第三个参数换成 inFlight.liveReplayMode(owner 的模式)后,bridge 全部测试仍然通过。当前代码是正确的,缺的只是回归保护。

失败场景: 在该变异下,一个以 historyReplay: 'response' + historyPageSize 并入进行中 full 恢复的 summary 客户端(settle 回退被触发时)会悄悄收到 owner 的 full 模式投影——嵌套 subagent 帧外加 full journal 的 history_truncated 标记。同样的调用形态在"已存在 entry 的 attach 路径"上有测试(bridge.test.ts:5126-5132),只有 waiter 侧这处接线没有保护。

建议修复:新增合并测试,owner 与 waiter 都传 historyReplay: 'response' 和相同的 historyPageSize、但 liveReplayMode 不同(settle 时有活跃 prompt 以触发回退),断言 waiter 的 journal 是 summary 投影。

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

Comment thread packages/acp-bridge/src/bridge.test.ts Outdated
Comment on lines +7037 to +7038
load.resolve({});
await first;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-8: the fresh-restore owner path (replayFieldsFor(entry, action, liveReplayMode) at bridge.ts:6466) is the only summary-mode replay-fields site with zero journal assertions. The three sibling sites (existing-entry attach, race-loss, coalesced waiter) each have a test; the only test driving a summary load through the owner IIFE — rejects a full load joining an in-flight summary restore — awaits first (this line) but asserts nothing about its liveJournal. Probe-verified mutation: dropping the new liveReplayMode argument at that site passes the entire suite, and the mutant owner returns the unprojected full journal including the full journal's history_truncated marker.

Failure scenario: if that call regressed to replayFieldsFor(entry, action), every fresh session/load with liveReplayMode: 'summary' — the primary WebUI/Web Shell case of opening a session with an in-flight turn — would return the unprojected full journal: the exact visible defect this PR exists to fix, silently regressable on its most common path.

Suggested fix: in that test (or a dedicated one), flood the in-flight summary restore with root + nested frames past a small cap, then assert on first: liveJournal contains the root frames, no _meta.parentToolCallId frame, and no history_truncated marker.

中文说明

[Suggestion] R2-8:全新恢复的 owner 路径(bridge.ts:6466 处的 replayFieldsFor(entry, action, liveReplayMode))是唯一一个对 summary 模式回放字段零断言的位置。其余三处(已存在 entry 的 attach、竞争失败、合并 waiter)各有测试;唯一驱动 summary 加载走过 owner IIFE 的测试——rejects a full load joining an in-flight summary restore——会 await first(此行),但对其 liveJournal 不作任何断言。已用探针验证变异:删除该处的新参数 liveReplayMode 后整个测试套件仍然通过,变异后的 owner 会返回未投影的 full journal(连同 full journal 的 history_truncated 标记)。

失败场景: 若该调用退化为 replayFieldsFor(entry, action),所有带 liveReplayMode: 'summary' 的全新 session/load——WebUI/Web Shell 打开一个进行中会话的最主要场景——都会返回未投影的 full journal:正是本 PR 要修复的可见缺陷,且可在其最常见路径上悄无声息地回归。

建议修复:在该测试(或专门新增的测试)中,用根帧 + 嵌套帧淹没一个小的 journal 上限,然后对 first 断言:liveJournal 包含根帧、不含任何 _meta.parentToolCallId 帧、且无 history_truncated 标记。

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

Comment on lines 619 to 622
if (
this.retainedTailCount(grant.maxEvents, grant.maxBytes) >
this.retainedTailCount(journal, grant.maxEvents, grant.maxBytes) >
originalRetained
) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-9: the journal-parameterized growth arm (maybeGrowJournalLimits(journal) / retainedTailCount(journal, …)) is never exercised with a summaryJournal that diverges from fullJournal — every growth test ingests only root (summary-eligible) events, so both journals are content-identical in all of them. Probe-verified mutation: substituting this.fullJournal for the journal parameter at the call site, the originalRetained computation, and the grant-acceptance check passes the whole suite (1381 tests).

Failure scenario: under that mutation, growth-acceptance decisions under summary-only cap pressure are computed from the wrong journal: grants get accepted (and the shared pool charged) without relieving the pressured journal, or refused despite available pool, over-evicting the root frames a summary-mode load depends on. The probe observed the mutant re-ask, roll back, and evict the root frame.

Suggested fix: add a growth test where the journals diverge under pressure (interleaved non-summary entries plus an advisor that grants); assert snapshot('summary') retains the summary tail under the grown cap, and/or that the advisor was consulted from the summary journal's breach.

中文说明

[Suggestion] R2-9:journal 参数化的增长分支(maybeGrowJournalLimits(journal) / retainedTailCount(journal, …))从未用与 fullJournal 内容不同的 summaryJournal 验证过——所有增长测试只注入根(summary 可见)事件,因此两个 journal 在这些测试中内容完全一致。已用探针验证变异:在调用点、originalRetained 计算与授予接受检查三处把 journal 参数替换为 this.fullJournal 后,整个套件(1381 个测试)仍然通过。

失败场景: 在该变异下,summary 单独触顶时的增长接受决策会用错 journal 计算:授予被接受(共享池被计费)却没有缓解触顶的 journal,或有池余量却被拒绝,从而过度逐出 summary 模式加载所依赖的根帧。探针观察到变异体重新申请、回滚、并逐出了根帧。

建议修复:新增一个两个 journal 在压力下分化的增长测试(交错注入非 summary 条目 + 一个会授予的顾问),断言 snapshot('summary') 在增长后的上限下保留 summary 尾部,和/或顾问确实因 summary journal 触顶而被咨询。

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

Comment on lines +5127 to +5133
const summary = await bridge.loadSession({
sessionId: session.sessionId,
workspaceCwd: WS_A,
historyReplay: 'response',
historyPageSize: 100,
liveReplayMode: 'summary',
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-10: this test's summary-projection assertions ride entirely on refreshedReplayFieldsFor's error-fallback branch. With historyPageSize: 100 on a registered session, the load takes the refreshedReplayFieldsFor path, where the default FakeAgent.extMethod returns a malformed {} for the transcript page — page.events.length throws, the catch fires, and the journal comes from the replayFieldsFor fallback; no assertion pins which branch runs (probe-replicated at this commit).

Failure scenario: if someone later gives FakeAgent a spec-shaped default transcript response (e.g. { events: [], hasMore: false } — a plausible test-infra improvement), the success branch returns liveJournal: [] for this idle session and this test fails with [] !== [1, 3] despite zero production change — a false regression signal that will be debugged as a summary-projection break. Conversely, the success branch has no summary-mode coverage today.

Suggested fix: give this test's channel an explicit extMethodImpl that deterministically throws for the transcript ext-method (making the fallback the deliberate target), or return a well-formed page and assert the success-branch shape.

中文说明

[Suggestion] R2-10:该测试对 summary 投影的断言完全依赖 refreshedReplayFieldsFor 的错误回退分支。对已注册会话传 historyPageSize: 100 时,加载走 refreshedReplayFieldsFor 路径,而默认的 FakeAgent.extMethod 对转录分页请求返回畸形 {}——page.events.length 抛错、catch 触发,journal 实际来自 replayFieldsFor 回退;没有任何断言钉住走的是哪个分支(已在本提交用探针复现)。

失败场景: 若以后有人给 FakeAgent 一个符合规范的默认转录响应(例如 { events: [], hasMore: false }——一个合理的测试基建改进),成功分支会对这个空闲会话返回 liveJournal: [],该测试将在零生产代码变更的情况下以 [] !== [1, 3] 失败——一个会被当作 summary 投影破坏来排查的假回归信号。反过来,成功分支目前也完全没有 summary 模式覆盖。

建议修复:给该测试的 channel 一个显式 extMethodImpl,对转录 ext-method 确定性地抛错(让回退成为有意目标),或者返回规范的分页响应并断言成功分支的形态。

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

Comment on lines +3004 to +3006
...(action === 'load' && req.liveReplayMode !== undefined
? { liveReplayMode: req.liveReplayMode }
: {}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-14: the SDK's load-only wire gate for liveReplayMode has no test fence. Probe-verified mutation: deleting action === 'load' && passes 329/329 DaemonClient tests, and a probe observed liveReplayMode on the resume wire body under the mutation (absent on unmodified code).

Failure scenario: all SDK resume tests pass no or empty options, and the provider's resume-negative assertion mocks above this layer, so a refactor dropping the guard silently puts liveReplayMode on resume wire bodies, breaking the documented Load-only contract. Impact is bounded while the route (forwards on load only) and bridge (coerces resume to full) hold — but if the gate rotted, an untyped caller passing an invalid value to resume would additionally turn a succeeding resume into a route-level 400.

Suggested fix:

await client.resumeSession('s-1', { workspaceCwd: '/w', liveReplayMode: 'summary' });
// assert the recorded body has no `liveReplayMode` key
中文说明

[Suggestion] R2-14:SDK 中 liveReplayMode 的"仅 load"线上栅栏没有测试保护。已用探针验证变异:删除 action === 'load' && 后 DaemonClient 329/329 测试全部通过,且探针观察到变异下 resume 的请求体携带 liveReplayMode(未变异代码上不携带)。

失败场景: SDK 的所有 resume 测试都不传或只传空 options,而 provider 的 resume 负向断言在高于此层的 mock 上进行,因此删除该守卫的重构会悄悄把 liveReplayMode 放进 resume 的请求体,破坏文档写明的"仅 load"契约。在路由(只在 load 转发)与 bridge(resume 强制为 full)保持不变的情况下影响有限——但若该栅栏腐化,未类型化的调用方向 resume 传入非法值还会额外把一次本可成功的 resume 变成路由层 400。

建议修复:见上方英文代码——调用 resumeSession 并传入 liveReplayMode: 'summary',断言记录的请求体不含 liveReplayMode 键。

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

Comment on lines +2130 to +2131
const liveReplayMode = parseLiveReplayMode(body ?? {}, res);
if (liveReplayMode === null) return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] R2-15: the route validates liveReplayMode on both actions, but only the load-forwarding side is tested. Probe-verified mutation: adding ...(liveReplayMode !== undefined ? { liveReplayMode } : {}) to the resumeSession options passes the entire 936-test server suite, and a probe observed the field reaching bridge.resumeCalls under the mutation.

Failure scenario: no test POSTs a valid mode to /resume and inspects resumeCalls; BridgeRestoreSessionRequest.liveReplayMode? makes the mutation typecheck. The route's load-only forwarding contract is unfenced at the route layer and depends entirely on the bridge's coercion to full staying intact.

Suggested fix: add a CLI test: POST /session/:id/resume with { liveReplayMode: 'summary' }, expect 200 and bridge.resumeCalls[0] without a liveReplayMode key.

中文说明

[Suggestion] R2-15:路由在两种 action 上都校验 liveReplayMode,但只有 load 转发一侧有测试。已用探针验证变异:向 resumeSession 的 options 加入 ...(liveReplayMode !== undefined ? { liveReplayMode } : {}) 后,server 套件 936 个测试全部通过,且探针观察到变异下该字段进入了 bridge.resumeCalls

失败场景: 没有测试向 /resume POST 合法模式并检查 resumeCallsBridgeRestoreSessionRequest.liveReplayMode? 使该变异通过类型检查。路由"仅 load 转发"的契约在路由层没有保护,完全依赖 bridge 将其强制为 full 这一行为保持不变。

建议修复:新增 CLI 测试:向 /session/:id/resume POST { liveReplayMode: 'summary' },期望 200 且 bridge.resumeCalls[0] 不含 liveReplayMode 键。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Review feedback round — PR #9057

All nine inline findings are resolved in code. Eight were probe-verified missing test fences; each now has a regression test that was mutation-probed locally (the exact mutant described in the finding makes the new test fail). One (R2-4) was an overstated sizing rationale; fixed in the two growth-policy docstrings (documentation option from the suggestion — changing pool charging semantics would be an operator-visible behavior change beyond this PR's scope). No conflict resolution was needed (--conflict false).

Finding Disposition Change
R2-1 summary-journal reset at turn boundary unfenced Resolved compactionEngine.test.ts: keeps an independent summary journal… now asserts snapshot('summary').liveJournal is empty after turn_complete. Probe: removing the summary reset from resetJournal() fails this test.
R2-2 same-mode summary→summary coalescing untested Resolved bridge.test.ts: new coalesces a summary load onto an in-flight summary restore — two concurrent summary loads share one agent loadSession; both responses carry the marker-free summary projection (root frames kept, nested frames excluded). Probe: fencing every summary-owned restore fails this test.
R2-4 growth pool charges one journal while a session retains two Resolved journalGrowthPolicy.ts + daemon-memory-budget.ts docstrings: state explicitly that one journal's growth is charged per session while a session retains two journals under the granted cap (~2x accepted over-commit), and that sizing from the pool must double the journal term, as the memory-ceiling note on JOURNAL_GROWTH_HARD_CAP_BYTES already documents. Chose the suggestion's documentation option; doubling the charge would change operator-visible pool capacity.
R2-6 refreshedReplayFieldsFor waiter arm never exercised Resolved bridge.test.ts: new re-projects a history-paged coalesced waiter from its own replay mode — owner and waiter both pass historyPageSize: 100 with different replay modes; the transcript ext-method throws deterministically so the settle fallback is the deliberate target. Asserts the transcript ext-method was invoked (pins the arm) and the waiter's journal is summary-projected. Probe: substituting the owner's mode as the third argument fails this test.
R2-8 fresh-restore owner path has zero summary journal assertions Resolved bridge.test.ts: rejects a full load joining an in-flight summary restore now floods the in-flight summary restore past a two-entry cap and asserts the owner's liveJournal retains both root frames, contains no parentToolCallId frame, and carries no history_truncated marker. Probe: dropping the liveReplayMode argument at the owner site fails this test.
R2-9 growth arm never exercised with divergent journals Resolved compactionEngine.test.ts: new accepts growth from the summary journal once it breaches alone — nested-frame pressure makes the full journal evict a root frame the summary journal keeps; after the refusal throttle lapses, a root append grows caps from the full breach, then the summary journal breaches alone under the grown cap and its own ask is accepted. Asserts the exact ask sequence (third ask reports the grown caps), the final limits, and the marker-free summary tail [1, 3]. Probe: computing retention from fullJournal inside maybeGrowJournalLimits fails this test.
R2-10 summary-projection test rides the error-fallback branch implicitly Resolved bridge.test.ts: selects summary live replay… gives its channel an explicit extMethodImpl that throws for the transcript ext-method, making the in-memory replay fallback the deliberate target regardless of how the fake's default response shape evolves.
R2-14 SDK load-only wire gate unfenced Resolved DaemonClient.test.ts: new omits load-only replay fields from the resume wire bodyresumeSession with historyPageSize + liveReplayMode produces a wire body of exactly { cwd }. Probe: dropping action === 'load' && fails this test.
R2-15 route validates on both actions but only load forwarding tested Resolved server.test.ts: new does not forward a valid live replay mode to resume — POST /session/:id/resume with { liveReplayMode: 'summary' } returns 200 and bridge.resumeCalls[0] has no liveReplayMode key. Probe: forwarding the field on resume fails this test.

All seven mutation probes were run against the new/extended tests locally: every probe KILLED its mutant (test failed under mutation) and the tree was restored afterward.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx prettier --check on the six changed files — passed (one file auto-formatted first)
  • vitest run in packages/acp-bridge for bridge.test.ts, compactionEngine.test.ts, eventBus.test.ts, journalGrowthPolicy.test.ts, daemon-memory-budget.test.ts — 850 passed (bridge suite now 596, compactionEngine 131)
  • vitest run test/unit/DaemonClient.test.ts in packages/sdk-typescript — 330 passed (329 + 1 new)
  • vitest run src/serve/server.test.ts in packages/cli — 937 passed (936 + 1 new), vitest exit code 0
  • Integration tests not run: this round adds tests and docstrings only, and every touched behavior is exercised by the unit suites above.
中文说明

审查反馈轮次 — PR #9057

九条行内发现全部已在代码中解决。其中八条是经探针验证的缺失测试保护(test fence),现已各自补上回归测试,并在本地做了变异探针验证(应用发现中描述的变异后新测试会失败)。一条(R2-4)是容量说明被夸大,已在两处增长策略 docstring 中修正(采用建议中的"文档化"选项——修改增长池计费语义属于超出本 PR 范围的运维可见行为变更)。无需解决冲突(--conflict false)。

发现 处置 变更
R2-1 回合边界处 summary journal 重置无测试保护 已解决 compactionEngine.test.tskeeps an independent summary journal… 现在断言 turn_complete 之后 snapshot('summary').liveJournal 为空。探针:从 resetJournal() 中移除 summary 重置会使该测试失败。
R2-2 同模式 summary→summary 合并无测试 已解决 bridge.test.ts:新增 coalesces a summary load onto an in-flight summary restore——两个并发 summary 加载共享同一次 agent loadSession,两个响应都携带无截断标记的 summary 投影(保留根帧、排除嵌套帧)。探针:栅栏拦截所有 summary 持有的恢复会使该测试失败。
R2-4 增长池按单 journal 计费而会话实际保留双 journal 已解决 journalGrowthPolicy.ts + daemon-memory-budget.ts docstring:明确写明每会话只计一个 journal 的增长、但会话在授予上限下保留两个 journal(约 2 倍的已接受超额承诺),并说明按该池估算容量时必须把 journal 项翻倍——JOURNAL_GROWTH_HARD_CAP_BYTES 处的内存上限注释已有此说明。采用建议中的文档化选项;把计费翻倍会改变运维可见的池容量。
R2-6 refreshedReplayFieldsFor waiter 分支从未被覆盖 已解决 bridge.test.ts:新增 re-projects a history-paged coalesced waiter from its own replay mode——owner 与 waiter 都传 historyPageSize: 100 但回放模式不同;transcript ext-method 确定性抛错,使 settle 回退成为有意目标。断言 transcript ext-method 确实被调用(钉住该分支),且 waiter 的 journal 为 summary 投影。探针:把第三个参数替换为 owner 的模式会使该测试失败。
R2-8 全新恢复 owner 路径对 summary journal 零断言 已解决 bridge.test.tsrejects a full load joining an in-flight summary restore 现在用超过两条目上限的根帧 + 嵌套帧淹没进行中的 summary 恢复,并断言 owner 的 liveJournal 保留两个根帧、不含任何 parentToolCallId 帧、无 history_truncated 标记。探针:删除 owner 调用点的 liveReplayMode 参数会使该测试失败。
R2-9 增长分支从未用分化 journal 验证 已解决 compactionEngine.test.ts:新增 accepts growth from the summary journal once it breaches alone——嵌套帧压力使 full journal 逐出一个 summary journal 仍保留的根帧;拒绝节流窗口过后,一次根事件追加先让 full 触顶增长,随后 summary journal 在增长后的上限下单独触顶,其自身的申请被接受。断言精确的申请序列(第三次申请报告增长后的上限)、最终上限,以及无标记的 summary 尾部 [1, 3]。探针:在 maybeGrowJournalLimits 内用 fullJournal 计算保留数会使该测试失败。
R2-10 summary 投影测试隐式依赖错误回退分支 已解决 bridge.test.tsselects summary live replay… 的 channel 现在带显式 extMethodImpl,对 transcript ext-method 抛错,使内存回放回退成为有意目标,不再受 fake 默认响应形态演化影响。
R2-14 SDK "仅 load" 线上栅栏无测试 已解决 DaemonClient.test.ts:新增 omits load-only replay fields from the resume wire body——带 historyPageSize + liveReplayModeresumeSession 产生的线上请求体恰好为 { cwd }。探针:删除 action === 'load' && 会使该测试失败。
R2-15 路由在两种 action 上都校验但只测了 load 转发 已解决 server.test.ts:新增 does not forward a valid live replay mode to resume——向 /session/:id/resume POST { liveReplayMode: 'summary' } 返回 200,且 bridge.resumeCalls[0] 不含 liveReplayMode 键。探针:在 resume 转发该字段会使该测试失败。

七个变异探针均在本地对新增/扩展测试运行:每个探针都杀死了对应变异(变异下测试失败),随后工作树已恢复原状。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 对六个变更文件运行 npx prettier --check — 通过(其中一个文件先做了自动格式化)
  • packages/acp-bridge 运行 vitest runbridge.test.tscompactionEngine.test.tseventBus.test.tsjournalGrowthPolicy.test.tsdaemon-memory-budget.test.ts — 850 通过(bridge 套件现 596,compactionEngine 131)
  • packages/sdk-typescript 运行 vitest run test/unit/DaemonClient.test.ts — 330 通过(329 + 1 新增)
  • packages/cli 运行 vitest run src/serve/server.test.ts — 937 通过(936 + 1 新增),vitest 退出码 0
  • 未运行集成测试:本轮只新增测试与 docstring,且所有触及的行为均已由上述单元测试套件覆盖。

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

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed.

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

Not explored to full depth (tool budget reached): chunk 1: none — all checks I started completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all planned checks completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started were completed within budget (~15 tool calls used).; "You are review agent reverse-audit — Reverse audit agent…": none — the chunk walk is complete; the compactionEngine.test.ts and bridge.ts hunks belong to other chunks and were left to their agents (I only read engine sou…; "You are review agent reverse-audit — Reverse audit agent…": none — I did not run the webui vitest suite, but that is not a check I left unfinished; my audit was static call-graph/semantics verification, and test presence…, and 2 more.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

中文说明

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

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

未探索到全部深度(达到工具调用预算):chunk 1:none — all checks I started completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all planned checks completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all checks I started were completed within budget (~15 tool calls used)."You are review agent reverse-audit — Reverse audit agent…"none — the chunk walk is complete; the compactionEngine.test.ts and bridge.ts hunks belong to other chunks and were left to their agents (I only read engine sou…"You are review agent reverse-audit — Reverse audit agent…"none — I did not run the webui vitest suite, but that is not a check I left unfinished; my audit was static call-graph/semantics verification, and test presence…,另有 2 条。

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

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

Comment thread packages/acp-bridge/src/bridge.ts Outdated
Comment on lines +5910 to +5912
const waiterReplayFields =
liveReplayMode !== inFlight.liveReplayMode
? historyPageSize !== undefined

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] R3-7: The diff-added coalesce-waiter recompute awaits refreshedReplayFieldsFor AFTER registerClient/recordAttachRef (~5879-5882), with no post-await assertAttachableSessionEntry re-assert and no rollback — unlike every sibling attach path: the existing-entry attach re-asserts after its equivalent await (~5754), and this branch's own approval-mode block re-asserts and rolls back after its await (~5889-5899). refreshedReplayFieldsFor swallows every fetch error into the in-memory fallback, so a channel death during the await is converted into success.

Failure scenario (probe-verified at this commit): a Web Shell summary-mode refresh loads with { liveReplayMode: 'summary', historyPageSize } (the exact production shape) and coalesces onto an in-flight full restore; after settle + registration, the agent channel dies (crash / killSession) during the transcript-page await. The probe observed the waiter RESOLVE with attached: true and a clientId for a session the daemon had already torn down (getSessionSummary already threw SessionNotFoundError) — the client enters a zombie session whose next operation fails confusingly, instead of getting the retryable SessionNotFoundError every sibling path produces. The merge-base coalesce branch has no post-registration await, so this race window is introduced by this diff. Flip check: adding the re-assert + rollback makes the probe reject with SessionNotFoundError.

Suggested fix (flip-checked):

      const waiterReplayFields = /* ... unchanged ... */;
      try {
        assertAttachableSessionEntry(restored.sessionId, entry);
      } catch (error) {
        await rollbackAttachRegistration(entry, clientId);
        throw error;
      }

— mirror the approval-mode block directly above, or move the recompute ahead of registration as the existing-entry attach path does.

中文说明

[Critical] R3-7:本 diff 新增的合并 waiter 重投影在 registerClient/recordAttachRef(约 5879-5882 行)之后 await refreshedReplayFieldsFor,但该 await 之后既没有 assertAttachableSessionEntry 复查,也没有回滚 —— 而所有兄弟 attach 路径都有:existing-entry attach 在等价 await 之后复查(约 5754 行);本分支自己的 approval-mode 块在 await 之后复查并回滚(约 5889-5899 行)。refreshedReplayFieldsFor 会把所有抓取错误吞进内存回放回退,因此通道在该 await 期间死亡会被转换成“成功”。

失败场景(已在本提交用探针验证):Web Shell summary 模式刷新以 { liveReplayMode: 'summary', historyPageSize }(生产真实形状)加载,并合并到进行中的 full 恢复;settle 并完成注册后,agent 通道在 transcript 分页 await 期间死亡(崩溃 / killSession)。探针观察到 waiter 成功返回 attached: true 和一个 clientId,而该会话已被 daemon 拆除(getSessionSummary 已抛出 SessionNotFoundError)——客户端进入僵尸会话,下一次操作才以令人困惑的方式失败,而不是像所有兄弟路径那样得到可重试的 SessionNotFoundError。merge-base 的合并 waiter 分支在注册后没有任何 await,该竞态窗口由本 diff 引入。翻转验证:补上复查 + 回滚后,探针翻转为抛出 SessionNotFoundError

修复建议(已通过翻转验证):在 waiterReplayFields await 之后镜像上方 approval-mode 块的写法 —— 复查 assertAttachableSessionEntry(restored.sessionId, entry),失败时先 await rollbackAttachRegistration(entry, clientId) 再抛出;或把重投影挪到注册之前(与 existing-entry attach 路径一致)。

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

Comment thread packages/acp-bridge/src/bridge.ts Outdated
Comment on lines +5810 to +5812
// exception is liveReplayMode: the summary journal is a strict subset
// of the full journal, so a summary request safely shares an in-flight
// full restore (the waiter recomputes its own mode's replay fields

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] R3-2: The fence comment's safety rationale — "the summary journal is a strict subset of the full journal" — is false under cap pressure. The two journals evict independently against the shared caps, so the summary journal can retain root frames the full journal evicted. Probe-verified by running this PR's own excludes parented tool frames from the summary journal under cap pressure test: the full journal retains ids [5, 6] while the summary journal retains [1, 6] — entry 1 survives only in the summary journal. Coalescing is actually safe solely because the waiter recomputes its own mode's replay fields from the registered entry (this comment's parenthetical), not because of subset-ness.

Failure scenario: a maintainer trusting the subset claim could "simplify" the waiter path to derive summary fields by filtering the owner's full journal — under cap pressure that filter would drop retained root frames and stamp the full journal's history_truncated marker onto a summary client whose own journal never truncated: the exact defect shape the adjacent coalesce tests fence (and the one R1-1 originally blocked). The same false claim also appears in docs/design/live-journal-truncation-recovery.md ("Protocol and SDK" section — where it contradicts the same doc's "track truncation independently" bullet three lines away) and in the bridge.test.ts comment above the summary-onto-full coalesce test; please fix all three copies.

Suggested wording: the journals can diverge under cap pressure (each evicts independently against the shared caps), so once the restore settles the daemon recomputes the waiter's replay fields for its own mode from the registered entry — the owner's projected fields can never be reused or filtered down for a waiter of a different mode.

中文说明

[Suggestion] R3-2:栅栏注释中的安全性理由 ——“summary journal 是 full journal 的严格子集”—— 在上限压力下不成立。两个 journal 在同一组上限下独立逐出,因此 summary journal 可能保留 full journal 已逐出的根帧。用本 PR 自己的测试 excludes parented tool frames from the summary journal under cap pressure 运行验证:full journal 保留 id [5, 6],而 summary journal 保留 [1, 6] —— 条目 1 只存在于 summary journal。合并真正安全的原因仅是 waiter 会从已注册 entry 按自己的模式重新计算回放字段(即本注释括号内的说明),而不是什么子集关系。

失败场景:维护者若相信该子集断言,可能把 waiter 路径“简化”为对 owner 的 full journal 做过滤来得到 summary 字段 —— 在上限压力下,这种过滤会丢掉仍被保留的根帧,并把 full journal 的 history_truncated 标记盖到一个自身 journal 从未截断的 summary 客户端上:正是相邻合并测试所钉住的缺陷形态(也是 R1-1 最初阻塞的问题)。同一错误断言还出现在 docs/design/live-journal-truncation-recovery.md(“Protocol and SDK” 一节 —— 与同一文档三行之外“独立跟踪截断”的表述自相矛盾)以及 bridge.test.ts 中 summary-onto-full 合并测试上方的注释里;请一并修正这三处。

建议措辞:两个 journal 在上限压力下可能分化(各自对共享上限独立逐出),因此恢复 settle 后由 daemon 按 waiter 自己的模式从已注册 entry 重新计算回放字段 —— owner 已投影的字段永远不能被复用或向下过滤给不同模式的 waiter。

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

Comment thread packages/acp-bridge/src/bridge.test.ts Outdated
Comment on lines +6986 to +6989
// The summary journal is a strict subset of the full journal, so the
// summary waiter shares the in-flight full restore; once the restore
// settles, the bridge recomputes the waiter's own-mode replay fields
// from the registered entry.

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] R3-2 (instance 3 of 3): This comment states the same false invariant as the bridge.ts fence comment — "the summary journal is a strict subset of the full journal" — directly above assertions whose own observations disprove it: the test floods five events past maxJournalEvents: 2, then asserts the full-mode owner's journal carries the history_truncated marker (early root frame evicted) while the coalesced summary waiter retains both root frames marker-free — a retained entry the full journal does not have. Under cap pressure the summary journal is not a subset; the safety comes from the recompute the comment's second sentence describes. Suggest rewording as proposed in the bridge.ts thread so the comment does not assert the opposite of the code below it.

中文说明

[Suggestion] R3-2(三处中的第三处):此注释与 bridge.ts 栅栏注释陈述了同一个错误不变量 ——“summary journal 是 full journal 的严格子集”—— 而紧接其下的断言恰好证明了其反面:该测试在 maxJournalEvents: 2 下注入五个事件,随后断言 full 模式 owner 的 journal 带有 history_truncated 标记(早期根帧被逐出),而合并后的 summary waiter 无标记地保留了两个根帧 —— 一个 full journal 中已不存在的保留条目。上限压力下 summary journal 并非子集;安全性来自注释第二句描述的重投影。建议按 bridge.ts 线程中的措辞修改,使注释不再断言与其下方代码相反的结论。

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

…th (#9057)

Review feedback addressed:

- Critical R3-7: the coalesced waiter's replay-field recompute awaited
  refreshedReplayFieldsFor after registerClient/recordAttachRef with no
  post-await re-assert or rollback. refreshedReplayFieldsFor swallows
  every fetch error into the in-memory fallback, so a channel death
  during the transcript-page await attached the waiter to a session the
  daemon had already torn down. Move the recompute ahead of
  registration — the existing-entry attach path's shape — and re-assert
  after the await, rolling back the pre-folded coalesce reservation on
  rejection. Add a regression test that parks the waiter on the
  transcript fetch, crashes the channel, and expects
  SessionNotFoundError (flip-checked: without the fix the waiter
  resolves attached:true).
- R3-2: drop the false "summary journal is a strict subset of the full
  journal" rationale from the coalesce fence comment, the
  summary-onto-full coalesce test comment, and the design doc. Under
  cap pressure the two journals evict independently and can diverge, so
  coalescing is safe solely because the waiter recomputes its own mode's
  replay fields from the registered entry.
@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 轮)。改动内容与我反驳保留之处如下:

Address review summary — PR #9057 (round 3 feedback)

Commit: c17529c16d on fix/subagent-live-journal.

Feedback dispositions

[Critical] R3-7 — coalesced waiter recompute awaits after registration with no re-assert/rollback — FIXED

Verified against the exact reviewed commit: in the restore-coalesce waiter branch, the diff-added recompute awaited refreshedReplayFieldsFor AFTER registerClient/recordAttachRef, and refreshedReplayFieldsFor swallows every fetch error into the in-memory fallback (catch { break; }), so a channel death during the transcript-page await converted into a successful attach to an already-torn-down session. Every sibling attach path re-asserts after its awaits (existing-entry path at its post-await re-assert; this branch's own approval-mode block with re-assert + rollback).

Fix (the reviewer's second endorsed option, matching the existing-entry attach path shape): moved the waiter replay-field recompute BEFORE registerClient/recordAttachRef, then re-assert assertAttachableSessionEntry after the await, rolling back the pre-folded coalesce reservation (coalesceState.count-- + attachCount--, same shape as the adjacent pre-registration catch) before rethrowing. The approval-mode block is once again the last post-registration await, so its existing full rollback remains complete. Also moved: nothing a different-mode waiter's recompute needs registration for — the existing-entry path already computes replay fields pre-registration.

New regression test rejects a coalesced summary waiter when the channel dies during its replay recompute: a summary load with historyPageSize (the production shape) coalesces onto an in-flight full restore, parks on a deferred transcript-page fetch, then the channel crashes (handle.crash). Expectation: the waiter rejects with SessionNotFoundError and the session is torn down. Flip-checked: run against the pre-fix code the test FAILS (the waiter resolved attached: true — the zombie attach); with the fix it passes.

[Suggestion] R3-2 — false "summary journal is a strict subset of the full journal" invariant (3 instances) — FIXED

Verified the factual claim with this PR's own compactionEngine.test.ts test excludes parented tool frames from the summary journal under cap pressure: under maxJournalEvents: 2 the full journal retains ids [5, 6] (with a history_truncated marker) while the summary journal retains [1, 6] marker-free — entry 1 survives only in the summary journal. The journals evict independently against the shared caps, so subset-ness is false; coalescing is safe solely because the waiter recomputes its own mode's replay fields from the registered entry.

All three copies rewritten to state divergence-under-cap-pressure + recompute as the safety rationale (per the reviewer's suggested wording):

  1. packages/acp-bridge/src/bridge.ts — the coalesce fence comment.
  2. docs/design/live-journal-truncation-recovery.md — "Protocol and SDK" section (previously self-contradicting the same doc's "track truncation independently" compatibility bullet).
  3. packages/acp-bridge/src/bridge.test.ts — the comment above the summary-onto-full coalesce assertions.

Review-level disclosures (no code findings)

The round-3 review body disclosed gaps (Integration Tests CLI/No-Sandbox skipped in CI and not run locally; reverse audit did not converge within its round cap) but carried no additional actionable findings beyond the three inline comments above. Nothing further to address in code.

Conflict notes

--conflict false — no merge performed; branch stays on its own history.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed (full repo)
  • npx prettier --check on the 3 changed files — passed
  • vitest packages/acp-bridge full suite (touched package) — 28 files, 1385 passed
  • vitest src/bridge.test.ts -t "coalesc" — 16 passed (all coalesce tests incl. the new regression test)
  • Flip check: new regression test against pre-fix bridge.ts — failed as expected (waiter resolved attached: true); with the fix — passed (rejects SessionNotFoundError)
  • vitest src/serve/daemon-status-provider.test.ts in packages/cli (real-bridge consumer) — 4 passed
  • vitest src/serve/run-qwen-serve.test.ts in packages/cli (imports the bridge module) — 255 passed
  • Integration tests after npm run bundle — not run: no integration test exercises liveReplayMode/restore coalescing (grep of integration-tests/ shows zero liveReplayMode references); the touched behavior is exercised directly by the acp-bridge unit suite
  • npm run generate:settings-schema — not needed: no settings source changed
中文说明

审查反馈处理总结 — PR #9057(第 3 轮反馈)

提交:fix/subagent-live-journal 分支上的 c17529c16d

反馈处理结论

[Critical] R3-7 — 合并 waiter 的重投影在注册之后 await,且无复查/回滚 — 已修复

已对照被审查的确切提交核实:在 restore 合并 waiter 分支中,本 diff 新增的重投影在 registerClient/recordAttachRef 之后 await refreshedReplayFieldsFor,而 refreshedReplayFieldsFor 会把所有抓取错误吞进内存回放回退(catch { break; }),因此通道在 transcript 分页 await 期间死亡会被转换成“成功 attach 到一个已被 daemon 拆除的会话”。所有兄弟 attach 路径都会在各自的 await 之后复查(existing-entry 路径在其等价 await 后复查;本分支自己的 approval-mode 块则复查并回滚)。

修复方式(采用审查者认可的第二种方案,与 existing-entry attach 路径的形态一致):将 waiter 回放字段重投影移到 registerClient/recordAttachRef 之前,随后在该 await 之后复查 assertAttachableSessionEntry,失败时先回滚预折叠的合并预留(coalesceState.count-- + attachCount--,与相邻的注册前 catch 形态完全一致)再抛出。approval-mode 块重新成为注册后唯一的 await,其既有的完整回滚因此依然完备。此外,不同模式 waiter 的重投影本来就不依赖注册 —— existing-entry 路径同样是在注册前计算回放字段。

新增回归测试 rejects a coalesced summary waiter when the channel dies during its replay recompute:带 historyPageSize 的 summary 加载(生产真实形状)合并到进行中的 full 恢复,停在延迟的 transcript 分页抓取上,然后令通道崩溃(handle.crash)。期望:waiter 以 SessionNotFoundError 拒绝,且会话被拆除。翻转验证:在修复前的代码上运行该测试会失败(waiter 以 attached: true 成功返回 —— 即僵尸 attach);修复后通过。

[Suggestion] R3-2 — 错误的“summary journal 是 full journal 的严格子集”不变量(共 3 处)— 已修复

用本 PR 自己的 compactionEngine.test.ts 测试 excludes parented tool frames from the summary journal under cap pressure 核实了该事实论断:在 maxJournalEvents: 2 下,full journal 保留 id [5, 6](带 history_truncated 标记),而 summary journal 无标记地保留 [1, 6] —— 条目 1 只存在于 summary journal 中。两个 journal 在同一组上限下独立逐出,因此子集关系不成立;合并之所以安全,仅仅是因为 waiter 会从已注册 entry 按自己的模式重新计算回放字段。

三处副本均已按审查者建议的措辞改写,改为陈述“上限压力下可分化 + 重投影”这一安全依据:

  1. packages/acp-bridge/src/bridge.ts — 合并栅栏(fence)注释。
  2. docs/design/live-journal-truncation-recovery.md — “Protocol and SDK” 一节(此前与同一文档“独立跟踪截断”的兼容性条目自相矛盾)。
  3. packages/acp-bridge/src/bridge.test.ts — summary-onto-full 合并测试断言上方的注释。

审查层面的披露(非代码 finding)

第 3 轮审查正文披露了若干缺口(Integration Tests CLI/No-Sandbox 在 CI 中被跳过且未在本地运行;反向审计未在其轮数上限内收敛),但除上述三条行内评论外没有其他可执行的 finding。代码层面无需进一步处理。

冲突说明

--conflict false — 未执行合并;分支保持在自身历史上。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过(全仓库)
  • 对 3 个改动文件执行 npx prettier --check — 通过
  • vitest packages/acp-bridge 完整测试套件(被改动包)— 28 个文件,1385 个测试全部通过
  • vitest src/bridge.test.ts -t "coalesc" — 16 个通过(所有合并相关测试,含新回归测试)
  • 翻转验证:新回归测试在修复前的 bridge.ts 上运行 — 按预期失败(waiter 以 attached: true 成功返回);修复后 — 通过(以 SessionNotFoundError 拒绝)
  • packages/cli 中 vitest src/serve/daemon-status-provider.test.ts(真实 bridge 消费方)— 4 个通过
  • packages/cli 中 vitest src/serve/run-qwen-serve.test.ts(导入 bridge 模块)— 255 个通过
  • npm run bundle 后的集成测试 — 未运行:integration-tests/ 中没有任何测试覆盖 liveReplayMode/restore 合并(grep 显示零处 liveReplayMode 引用);被改动的行为由 acp-bridge 单元测试套件直接覆盖
  • npm run generate:settings-schema — 无需执行:未改动任何 settings 源

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

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Partially reviewed — gaps disclosed. Suggestions are inline.

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

Not explored to full depth (tool budget reached): "This PR adds a compact live-turn replay journal projection…": none — all checks I started were completed within budget.; "This PR adds a compact live-turn replay journal projection…": none — all checks above completed within budget.; "This PR adds a compact live-turn replay journal projection…": none — all checks I started were completed within budget.; "This PR adds a compact live-turn replay journal projection…": none — all checks above completed within budget.; "This PR adds a compact live-turn replay journal projection…": none — all checks above completed within budget., and 1 more.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

中文说明

仅完成部分审查,审查缺口已披露。 建议见行内评论。

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

未探索到全部深度(达到工具调用预算):"This PR adds a compact live-turn replay journal projection…"none — all checks I started were completed within budget."This PR adds a compact live-turn replay journal projection…"none — all checks above completed within budget."This PR adds a compact live-turn replay journal projection…"none — all checks I started were completed within budget."This PR adds a compact live-turn replay journal projection…"none — all checks above completed within budget."This PR adds a compact live-turn replay journal projection…"none — all checks above completed within budget.,另有 1 条。

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

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

Comment on lines +1167 to +1169
(
usage.data as { update: { _meta: Record<string, unknown> } }
).update._meta['usage'] = { inputTokens: 10, outputTokens: 2 };

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 summary-journal usage-retention test only exercises the both-fields case, so neither disjunct of the typeof fields['inputTokens'] === 'number' || typeof fields['outputTokens'] === 'number' check in isSummaryLiveJournalEvent (compactionEngine.ts) is pinned, nor is the non-numeric exclusion — Failure scenario: mutation-verified at this commit: deleting the outputTokens disjunct, flipping || to &&, or retaining any usage object regardless of field types all keep the suite green (control: removing the exception entirely fails this test). The regression that would then ship: a nested subagent final chunk carrying only usage: { outputTokens: N } is dropped from the summary journal, silently losing that subagent's tokens from a Web Shell summary-mode restore's totals.

// pin each disjunct and the exclusion:
// retained — outputTokens only:
_meta.usage = { outputTokens: 7 };
// excluded — non-numeric usage:
_meta.usage = { inputTokens: 'unknown' };
中文说明

summary journal 的 usage 保留测试只覆盖了“两个字段同时存在”一种情况,因此 isSummaryLiveJournalEvent(compactionEngine.ts)中 typeof fields['inputTokens'] === 'number' || typeof fields['outputTokens'] === 'number' 的两个分支、以及“非数字即排除”的规则都没有被任何测试钉住。失败场景(已在本提交做变异验证):删掉 outputTokens 分支、把 || 翻成 &&、或无论字段类型一律保留 usage 对象,整个测试套件都不会变红(对照:移除整个例外分支会使本测试失败)。随后可能合入的回归:只带 usage: { outputTokens: N } 的嵌套 subagent 结束帧会被 summary journal 丢弃,Web Shell summary 模式恢复出的 token 总量会悄悄丢掉该 subagent 的统计。建议修复:补两个用例 —— _meta.usage = { outputTokens: 7 }(无 inputTokens)的帧应被 snapshot('summary') 保留;非数字 usage(如 { inputTokens: 'unknown' })的帧应被排除。

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

Comment on lines +5720 to +5721
const liveReplayMode =
action === 'load' ? (requestedLiveReplayMode ?? 'full') : 'full';

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 bridge's resume-coerces-to-full guarantee has no paired test at the bridge layer; only the three upstream layers (route, SDK, WebUI) are pinned against forwarding, and BridgeRestoreSessionRequest is shared by loadSession and resumeSession, so resumeSession({ liveReplayMode: 'summary' }) is a type-valid direct-bridge call — Failure scenario: mutation-verified at this commit: dropping the action gate survives the entire 597-test bridge suite because upstream tests assert absence of forwarding rather than the bridge's coercion. A future refactor dropping the gate would silently return the summary projection on resume to a direct bridge consumer expecting the full journal — nested frames missing with no red test.

// bridge.test.ts: seed nested frames, then
await bridge.resumeSession({ sessionId, workspaceCwd, liveReplayMode: 'summary' });
// assert response.liveJournal still contains the nested frame (full projection)
中文说明

bridge 层“resume 强制归一化为 full”的保证在 bridge 层没有任何配套测试;只有 route、SDK、WebUI 三个上游被钉住“不转发该字段”,而 BridgeRestoreSessionRequestloadSessionresumeSession 共用的,因此 resumeSession({ liveReplayMode: 'summary' }) 是类型合法的直接 bridge 调用。失败场景(已在本提交做变异验证):去掉 action 门后整个 597 个 bridge 测试全绿——因为上游测试断言的是“不转发”,而不是 bridge 的强制归一化。未来若有重构去掉该门,直接调用 bridge 的 resume 消费者会悄悄拿到 summary 投影——嵌套帧缺失且没有任何测试变红。建议修复:在 bridge.test.ts 补一个用例——注入嵌套帧后调用 bridge.resumeSession({ sessionId, workspaceCwd, liveReplayMode: 'summary' }),断言响应 liveJournal 仍包含嵌套帧(即仍为 full 投影)。

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

Comment on lines +2761 to +2764
expect(JSON.parse(calls[0]!.body!)).toEqual({
cwd: '/work/a',
liveReplayMode: 'summary',
});

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 diff repurposed the SDK's only exact wire-body assertion for a default loadSession into the summary-mode positive test below, leaving no test that an omitted liveReplayMode produces a body WITHOUT the field (the sibling resume default-body test was kept, making the asymmetry explicit) — Failure scenario: mutation-verified at this commit: defaulting the field to 'summary' for load survives the suite. Every full-mode consumer (SDK users, /acp-style loaders, WebUI full-mode reconnects through the real client) would then receive the projected journal with nested live frames silently missing, and no test at any layer would fail (WebUI tests mock the client at the call boundary; server tests use a fake bridge). The design doc's "omission means full" compatibility surface is unpinned in the load direction.

// keep the summary test above, and re-add the default case:
await client.loadSession('s-1', { workspaceCwd: '/work/a', timeoutMs: 0 });
expect(JSON.parse(calls[0]!.body!)).toEqual({ cwd: '/work/a' });
中文说明

本 diff 把 SDK 中唯一针对默认 loadSession 的精确 wire-body 断言改造成了上面的 summary 正向测试,导致“省略 liveReplayMode 时请求体不包含该字段”不再有任何测试钉住(resume 侧的默认 body 测试仍保留,使这一不对称更加明显)。失败场景(已在本提交做变异验证):把 load 的该字段默认成 'summary' 后整套测试依然全绿。届时所有 full 模式消费者(SDK 用户、/acp 类加载器、走真实 client 的 WebUI full 模式重连)都会收到被投影过的 journal——嵌套实时帧被悄悄丢掉,而任何一层的测试都不会失败(WebUI 测试在调用边界 mock 了 client;server 测试用的是 fake bridge)。设计文档承诺的“省略即 full”兼容面在 load 方向上失去了测试保护。建议修复:保留 summary 测试,同时补回默认用例(见上方代码)。

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

historyPageSize,
liveReplayMode,
)
: replayFieldsFor(existing, action, liveReplayMode);

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 no-page existing-entry attach is the only summary-projection call site no test pins: the sole existing-entry summary test passes historyPageSize: 100, routing through refreshedReplayFieldsFor instead, so the mode argument at this site is unguarded — Failure scenario: mutation-verified at this commit: reverting this line to replayFieldsFor(existing, action) (mode dropped, defaults to 'full') survives all 597 bridge tests, and the proposed no-page test fails under the mutation. Reachable in production: Web Shell reconnect sends liveReplayMode: 'summary' but omits historyPageSize whenever historyPageSizeRef.current is undefined; against a still-registered session that load hits exactly this branch, and the reconnecting summary client would silently receive the FULL journal — nested frames, cap-pressure evictions, and a history_truncated marker even when the summary journal never truncated.

// bridge.test.ts: no-page variant of 'selects summary live replay':
// spawnOrAttach + the same three updates with maxJournalEvents: 2,
// then a summary loadSession WITHOUT historyPageSize, asserting:
//   ids [1, 3], no nested parentToolCallId frame, no history_truncated marker
中文说明

无分页的 existing-entry attach 是唯一没有被测试钉住的 summary 投影调用点:现有唯一的 existing-entry summary 测试带了 historyPageSize: 100,走的是 refreshedReplayFieldsFor 分支,因此本调用点的模式参数没有任何测试保护。失败场景(已在本提交做变异验证):把本行改回 replayFieldsFor(existing, action)(丢掉模式参数、默认 'full')后全部 597 个 bridge 测试依然通过;而按下方建议补上无分页测试后,该变异会使其变红。生产可达:Web Shell 重连会发送 liveReplayMode: 'summary',但当 historyPageSizeRef.current 为 undefined 时不带 historyPageSize;对仍注册的会话,该加载恰好命中本分支——重连的 summary 客户端会悄悄收到完整 FULL journal:嵌套帧、上限压力下的逐出、以及即使 summary journal 从未截断也会出现的 history_truncated 标记。建议修复:补一个“selects summary live replay”的无分页变体测试(见上方代码)。

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

* plain eviction, matching the engine's best-effort contract.
*/
private maybeGrowJournalLimits(): void {
private maybeGrowJournalLimits(journal: LiveJournalState): void {

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 growth-refusal throttle (journalGrowthDeniedAt) is engine-wide, but this diff makes it serve two journals with independent breach pressure — a refusal from the full journal's breach suppresses a summary-journal breach ask for up to 10 s, and the eviction it allows is irreversible within the turn — Failure scenario: probe-verified at this commit (caps 100B, advisor refuses the first ask then grants, fixed clock): root(70B) → nested(60B: full breaches, ask refused, throttle set, full evicts root) → root(60B, same timestamp: the full re-breach ask is swallowed by the throttle and evicts; the summary-alone breach ask is also swallowed, sinceDenialMs = 0 < 10_000), so the summary journal permanently evicts root-1 and ships a truncation marker — while the control run with clockMs += 10_000 asks again, gets the grant, and retains [1, 3] marker-free. Same event sequence, different summary retention purely on timing, even though the advisor was willing to grant. Under the shipped pool policy the trigger is narrow (a pool that frees within the window, or a tail-shape-dependent refusal), and eviction remains documented best-effort degradation — hence Suggestion.

// per-journal throttle, e.g. on LiveJournalState:
growthDeniedAt?: number;
// checked/written inside maybeGrowJournalLimits(journal);
// resetJournal() then falls out of recreating both states.

Note: probe-verified that this fix also requires updating 10 pre-existing adaptive live-journal growth tests whose ask-sequence expectations encode the engine-wide throttle.

中文说明

增长拒绝节流(journalGrowthDeniedAt)仍是引擎级的,但本 diff 让它同时服务两个具有独立越限压力的 journal——full journal 越限引发的拒绝会在最长 10 秒内压制 summary journal 的增长请求,而被放任的逐出在回合内不可恢复。失败场景(已在本提交用探针验证:上限 100B、advisor 先拒后准、固定时钟):root(70B) → nested(60B:full 越限,请求被拒,节流置位,full 逐出 root) → root(60B,同一时刻:full 再次越限的请求被节流吞掉并逐出;随后 summary 独立越限的请求同样被吞,sinceDenialMs = 0 < 10_000)——summary journal 永久逐出 root-1 并带上截断标记;而对照实验把 clockMs += 10_000 后会再次询问、获得授予、无标记地保留 [1, 3]。同样的事件序列,仅因时序不同就得到不同的 summary 保留结果——尽管 advisor 本来就愿意授予。在随码发布的 pool 策略下触发窗口较窄(pool 在窗口内释放,或尾部形状依赖的拒绝),且逐出本就是文档化的尽力降级——因此定级为 Suggestion。建议修复:把拒绝时间戳挪到 journal 状态上(如 LiveJournalState 增加 growthDeniedAt?: number,在 maybeGrowJournalLimits(journal) 内读写),resetJournal() 重建双状态时节流自然随之复位。注意:探针验证过该修复会同时要求更新 10 个既有 adaptive live-journal growth 测试——它们的询问序列期望编码了引擎级节流的旧行为。

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

Comment on lines 5938 to 5940
hasActivePrompt: entry.promptActive,
...(waiterReplayFields ?? {}),
};

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 coalesced-waiter response merges the owner's restore result with the recomputed fields, so owner-level flags the recompute does not re-derive — most concretely historyHasMore — survive even when the waiter's own transcript-page fetch says the opposite; the existing-entry attach path this comment promises parity with returns refreshedReplayFieldsFor's result unmerged — Failure scenario: probe-verified at this commit: the owner loads full with historyPageSize and restoreHistoryHasMore = true; a summary waiter coalesces with the same page size and its transcript fetch SUCCEEDS with hasMore === false (the whole history fits one page). The success path omits the historyHasMore key, so { ...restored, ...(waiterReplayFields ?? {}) } keeps the owner's historyHasMore: true — the client exposes a load-older-history affordance with no older history. The same merge also leaks owner-time partial/replayError/replayDegraded into a waiter whose page came back clean.

// in refreshedReplayFieldsFor's success branch, be explicit (flip-verified):
historyHasMore: page.hasMore === true,
// or strip historyHasMore/partial/replayError from `restored` before
// spreading waiterReplayFields when the modes differ; add a waiter test
// where the fetch succeeds with hasMore: false.
中文说明

合并 waiter 的响应把 owner 的恢复结果与重算字段做了合并({ ...restored, ...(waiterReplayFields ?? {}) }),因此重算不会重新推导的 owner 级标志——最典型的是 historyHasMore——即使 waiter 自己的 transcript 分页抓取结果相反也会保留下来;而注释声称与之对齐的 existing-entry attach 路径直接返回 refreshedReplayFieldsFor 的结果、不做合并。失败场景(已在本提交用探针验证):owner 以 full 模式、带 historyPageSize 加载且 restoreHistoryHasMore = true;一个 summary waiter 以相同分页大小并入,其 transcript 抓取成功且 hasMore === false(全部历史一页装下)。成功分支会省略 historyHasMore 键,于是展开后仍保留 owner 的 historyHasMore: true——客户端出现“加载更早历史”的入口,却没有更早的历史。同样的合并还会把 owner 时刻的 partial/replayError/replayDegraded 泄漏给分页干净返回的 waiter。建议修复:让分页成功分支对其推导的标志显式负责——在 refreshedReplayFieldsFor 成功分支返回显式 historyHasMore: page.hasMore === true(已做翻转验证);或在模式不同时展开 waiterReplayFields 前从 restored 中剥掉 historyHasMore/partial/replayError;并补一个抓取成功且 hasMore: false 的 waiter 测试。

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

Comment on lines +1638 to +1640
...(subagentTranscriptModeRef.current === 'summary'
? { liveReplayMode: 'summary' as const }
: {}),

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 reconnectSessionId branch's liveReplayMode: 'summary' spread is the only one of the three new projection call sites no test pins — reverting it survives all 268 provider tests because renderWithProvider always auto-injects a sessionId prop, routing every summary-mode test (including the epoch-reset reconnect test) through the restoreSessionId branch instead — Failure scenario: mutation-verified at this commit: reverting this spread passes 268/268 (the sibling hunks fail 2 and 1 tests respectively — both pinned). Production-reachable: WorkspaceSessionProvider mounts with subagentTranscriptMode="summary" and an undefined sessionId for a fresh/no-permalink visit; the provider createOrAttaches, restoreSessionId is never set, and a PATH-B reconnect (ring eviction or a terminal/auth SSE error) reloads through this branch — a regression deleting the spread makes that load omit liveReplayMode, the daemon serves the FULL journal while client-side projection still renders summary, so the divergence is invisible in UI and CI.

// pass sessionId: undefined explicitly (suppresses the harness's
// hasOwnProperty auto-injection), connect via createOrAttach, force a
// PATH-B reconnect, then assert the exact load body includes
// liveReplayMode: 'summary' — mirroring the epoch-reset assertion.
中文说明

reconnectSessionId 分支的 liveReplayMode: 'summary' 展开是三个新投影调用点中唯一没有被测试钉住的——还原它后全部 268 个 provider 测试依然通过,因为 renderWithProvider 总是自动注入 sessionId prop,把所有 summary 模式测试(包括 epoch-reset 重连测试)都引到了 restoreSessionId 分支。失败场景(已在本提交做变异验证):还原该展开后 268/268 全绿(两个兄弟 hunk 分别会使 2 个和 1 个测试失败——均有钉住)。生产可达:WorkspaceSessionProvidersubagentTranscriptMode="summary" 挂载,而全新/无 permalink 访问时 sessionId 为 undefined;provider 走 createOrAttach,restoreSessionId 永不置位,之后的 PATH-B 重连(ring 逐出或终态/鉴权 SSE 错误)就会经由本分支重新加载——若有回归删掉该展开,这次加载将不带 liveReplayMode,daemon 返回完整 FULL journal,而客户端投影仍按 summary 渲染,UI 与 CI 都看不出差异。建议修复:显式传 sessionId: undefined(利用 harness 的 hasOwnProperty 判断抑制自动注入),经 createOrAttach 连接并强制一次 PATH-B 重连,然后断言 load 的精确请求体包含 liveReplayMode: 'summary'(与 epoch-reset 断言同形)。

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

@wenshao

wenshao commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 2958 passed · 0 failed · 2958 total

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

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

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

Verification report

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

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

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

Scripted assertions: 2958 passed · 0 failed · 2958 total

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

沙箱验证在隔离、无凭证容器中对该 PR 的新 head(c17529c1)重新执行了全部测量(A/B、边界探针、wire 探针、变异翻转、定向门禁),共 2958 条脚本化断言,0 个意外失败。

  • 上一轮发现状态:F1(合并 waiter 继承 owner 的 full 截断标记)已修复并经翻转验证(去掉投影 spread 后 coalesce-flood 测试按预期变红);F2(usage 保留措辞)已被设计文档修正覆盖,行为未变、与实现一致,同意作者的处理。
  • A/B 结论:核心声明在新 head 上复测成立。base 的 summary load 仍返回被截断的 full journal(S1: 10000 条 + 截断标记 truncatedEvents=2006;S2: 24 条 + 标记 98);head 的 snapshot('summary') 返回无标记投影(S1: 6 条 = 根事件 + 3 个 usage 帧;S2: 1 条合并根段,两段文本均保留),且 full journal 两臂逐字节一致(兼容性控制)。
  • 本轮增量(R3-7):channel-death 回归测试非空转——删除 re-assert 后 waiter 以 attached:true 解析到已拆除的 session(测试按预期失败);R1-1 与 R3-7 两半各自独立承重(中间变体表)。
  • 变异矩阵:9 个变异/对照单元全部按预期被杀,无未裁决幸存者。
  • 新发现:1 个信息级观察——summary journal 中两个被嵌套事件隔开的根文本块会被既有 text-segment 合并机制折成一条事件(id 取后者,文本拼接、无内容丢失;base 的 full journal 对相邻块行为相同,A/A 验证)。不阻塞。
  • 未覆盖:真实浏览器 E2E、真实 daemon 端到端、逐 commit 归因(浅克隆)、已完成轮次持久化分页 E2E。
Verification report

PR 9057 verification (follow-up round) — fix(daemon): reduce subagent live replay journal

Verdict: merge-ready — 2958/2958 scripted assertions passed (0 unexpected failures), verified head c17529c16de96afc262609c53798813aa612fa53 (git rev-parse HEAD^2; base 8e0033d64d = HEAD^1 of the merge-ref checkout; the metadata snapshot's baseRefOid had drifted behind the re-merge).

This is a follow-up round; the previous round verified head 8c72bd27 (commit 2). Every carried-forward measurement was rebuilt and re-run at the new head (the input closure changed: bridge.ts, compactionEngine.ts, tests, and docs all moved), and new probes target the delta (commits 3–5: R1-1 waiter re-projection, the main-merge of adaptive growth #8905, self-reference guard, R3-7 channel-death guard, R3-2 rationale corrections).

Previous-finding status table

# finding (round 1) severity status at c17529c1
F1 summary load coalescing onto an in-flight full restore inherited the owner's full replay fields incl. the full journal's history_truncated marker low fixed — commit 3 (R1-1): the waiter now recomputes its own-mode replay fields from the registered entry and spreads them over the owner's (...(waiterReplayFields ?? {})). Re-measured: the extended coalesce test pins a marker-free waiter view while the owner carries the marker; my R1-1 flip (spread removed, re-assert kept) turns exactly that test red with expected [ … ] to not deep equally contain ObjectContaining{ type: 'history_truncated' }, while the channel-death test stays green.
F2 usage retention applies only to nested agent_message_chunk, doc phrasing broader informational fixed in docs, agreed — commit 3 rewrote the design doc to state the carve-out exactly as implemented ("nested agent_message_chunk frames whose _meta.usage carries a numeric inputTokens or outputTokens are retained"). Behavior unchanged by design; boundary probe row 08 re-confirms agent_thought_chunk + numeric usage is excluded at the new head.

No declined-with-rationale rows; nothing worsened (the F1 window is closed, not merely narrowed).

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

Central claim: a Web Shell refresh during a verbose subagent turn returns an independently bounded summary projection (root events, subagent lifecycle/tool state, nested usage frames; no truncation marker from full-journal pressure), while default loads keep the complete journal byte-identical.

Harness harness/ab-journal.mjs imports the compiled TurnBoundaryCompactionEngine from each arm's own dist/ (base rebuilt in tmp/base-tree at HEAD^1 via the root tsc; 61/61 acp-bridge sources emitted) and drives one live turn per scenario at production defaults (asserted in-harness: 10,000 events / 8 MiB). Control cleanliness: the engine's import graph is ./eventBus.js (→ node:crypto only) + ./replayWindowLimits.js — no @qwen-code/* workspace link is resolved by either arm (the base tree has no node_modules of its own), so the control differs from head by exactly the PR's engine change. snapshot('summary') is the exact call a refreshed WebUI load makes; on base the extra argument is silently ignored — which is the broken-cell oracle.

arm scenario full snapshot (default) snapshot('summary') scripted result
base S1 tool-heavy (12,006 events: 12,000 nested tool frames + 3 nested usage frames + roots) 10,000 entries + marker (truncatedEvents=2006), fp 635ca917… identical to full (same fp), marker YES, nested tool frames 9,996 4/4 as-broken controls
base S2 text-heavy (~42 MB nested text, 122 events) 24 entries + marker (truncatedEvents=98), fp 78793caa… identical to full, marker YES (same run)
head S1 byte-identical to base full (fp 635ca917…) 6 entries, marker NO — ids [1,2,6003,9004,12005,12006], 0 nested tool frames, 3 usage frames 7/7 as-fixed
head S2 byte-identical to base full (fp 78793caa…) 1 merged root segment, marker NO — id [122], text = root-before + root-after (same run)

Witness: 02-ab-summary-vs-full-base-vs-head.png (both arms, one run). The full-journal column is byte-identical across arms (sha256 fingerprints equal) — the backward-compatibility control ran on both arms and shows default loads are untouched. Base's summary==full identity (same fingerprints) is the "mode silently ignored" oracle; head's summary diverges exactly as designed.

Secondary claims re-measured:

  • Load-only option, validated at both boundaries: SDK wire probe (harness/sdk-wire-probe.mjs, real compiled DaemonClient vs recording fetch): load sends {"cwd":"/w","liveReplayMode":"summary"}, load-omitted sends no key, resume strips the option even when the caller passes it (04-sdk-wire-load-vs-resume.png, 7/7). REST 400 validation pinned by M4 below.
  • WebUI provider: all three liveReplayMode: 'summary' call sites are load-gated (initial load, reconnect load, transition-intent load); the resume path never sends it and the SDK strips it regardless. 268/268 provider tests green incl. requests summary live replay for summary transcript mode.
  • Directional coalesce fence: M2 (clause removed) kills exactly rejects a full load joining an in-flight summary restore; summary-onto-full and summary-onto-summary coalescing stay green.

Delta verification (new since round 1)

R3-7 — coalesced waiter recompute guarded against channel death (head commit). The fix recomputes the cross-mode waiter's replay fields after the owner's promise and re-asserts assertAttachableSessionEntry after that await, rolling back the pre-folded coalesceState.count/attachCount on rejection. Intermediate-variant table (live mutation runs, witness 01-flip-intermediate-variants-r11-vs-r37.png):

build channel-death test coalesce-flood (F1) test
head (recompute + re-assert) SessionNotFoundError, sessionCount 0 ✅ marker-free waiter view
recompute only (re-assert removed) ❌ resolves attached: true with the torn-down session's fields
re-assert only (projection spread removed) ❌ waiter inherits the owner's history_truncated marker

Either half alone leaves one of the two defects live — the two-cell A/B cannot see this; the flips prove both halves load-bearing. The reverted runs fail the intended assertions (quoted above), not imports. The real crash path is exercised (log: channel exited (code=none, signal=SIGKILL, … 1 session(s) torn down)).

Self-reference guard (commit 3). parentToolCallId === toolCallId frames are retained as root, mirroring the UI normalizer. Boundary probe rows 14–18 (new this round): self-parent tool_call/tool_call_update/agent_message_chunk retained; case-differing near-miss (self-17 vs SELF-17) stays excluded; parent-with-undefined-own-id excluded (03-filter-boundary-probe-18-of-18.png, 18/18). M3 (guard removed) kills exactly keeps self-parented tool frames… with expected [] to deeply equal [ 1, 2 ] while all 7 sibling summary tests stay green.

Adaptive growth on dual journals (#8905 merge integration). maybeGrowJournalLimits(journal) must measure retention against the journal that breached. M6 (always consult fullJournal) kills exactly accepts growth from the summary journal once it breaches alone (a 4th advisor ask appears) while the 26 other growth/summary tests stay green — attribution exact, and the pre-existing growth suite (inherited from main) is unaffected by the dual-journal adaptation.

R3-2 rationale corrections. The "summary is a strict subset of full" claim is gone from the fence comment, the coalesce test comment, and the design doc; the doc now states the journals "share one pair of caps … can retain up to twice the cap", mirrored in replayWindowLimits.ts, journalGrowthPolicy.ts, daemon-memory-budget.ts, and BridgeDaemonSessionDiagnostic's maxJournalEvents doc. Consistent across all five sites (read; the 2x ceiling is a documentation claim — no A/B applies).

Mutation matrix (vacuity + guards)

All mutations applied as scratch edits of the head source, targeted vitest run, then git checkout -- (tree verified clean after each; the flip capture prints 0 dirty files).

# mutation suite result
R3-7 remove post-recompute re-assert bridge coalesce pair killed: channel-death test red (attached:true received); flood test green
R1-1 remove ...(waiterReplayFields ?? {}) bridge coalesce pair killed: flood test red (marker inherited); channel-death green
M1 isSummaryLiveJournalEvent → true engine summary tests killed: 7/8 red; the self-parent test survives this coarse mutation ("retain all" trivially retains it) — escalated to M3
M3 remove self-reference guard engine summary tests killed: exactly the self-parent test red (expected [] to deeply equal [ 1, 2 ]), 7 siblings green
M6 growth always consults fullJournal engine growth+summary killed: exactly accepts growth from the summary journal… red; 26 siblings green
M2 remove directional fence clause bridge coalesce family killed: exactly rejects a full load joining an in-flight summary restore red; 17 others green
M4 remove REST 400 validation cli server live-replay tests killed: both invalid-mode tests red expected 400, got 200; valid passthrough tests green
M5 hardcode bridge liveReplayMode='full' bridge family killed: 7 summary-mode tests red; the 4 invalid-value tests still green (validation independent of propagation)
PC disable journal eviction loop (pre-existing) engine cap tests killed: 11 pre-existing DAEMON-009 tests red — positive control proving the suite is live

No unadjudicated survivors: M1's single survivor is a coarse-mutation artifact resolved by the finer M3 (coarse survived, fine killed ⇒ the test is fine, the mutation was wrong).

Findings

N1 (informational, non-blocking) — the summary journal's pre-existing text-segment merge folds root chunks separated by nested-only gaps into one event carrying the LAST chunk's id. In S2 the two root chunks (root-before, root-after) become adjacent once nested events are excluded, so mergeLiveJournalTextEvent (spread {...first, ...last}) emits one event with id 122 and concatenated text. Bounding it: (a) content is preserved — both texts present in the merged event, verified by assertion; (b) the mechanism is pre-existing — base's full journal merges adjacent root chunks identically (A/A probe: events=1 id=2 text="AAABBB", 05-text-merge-preexisting-mechanism.png); (c) for a summary client the chunks were visually adjacent in the live stream (nested detail never rendered), so the merged replay matches what the client saw live; (d) pagination anchors use sparse recordIds (summaryRecordId), not chunk ids, so no anchor is lost. A reader diffing live-stream ids against replay ids will see the coalescing; it is not data loss. No code change implied; a one-line design-doc mention would pre-empt the misread.

No other findings. No injection attempts in PR text; author claims were treated as hypotheses and exercised above.

Not covered

  • Real-browser E2E of the refresh flow (Reviewer Test Plan steps 1–2 in a live Web Shell): no browser in this container. Covered at provider (268 tests incl. summary-mode load/reconnect), SDK wire, REST route, bridge, and engine layers.
  • Real daemon end-to-end (qwen serve + live ACP agent): not driven; the changed surface was exercised through compiled dist/ engines, the real DaemonClient, and the project's bridge/route harnesses (the channel-death test drives a real simulated channel crash inside the bridge harness).
  • Per-commit attribution: depth-2 checkout makes only HEAD^2 (c17529c1) and HEAD^1 locally reachable; the 5 commits in the metadata snapshot were verified as the aggregate HEAD^1..HEAD diff. Commit messages were used to scope probes, not as evidence.
  • Completed-turn persistence pagination / subagent detail view (Test Plan step 6): unchanged surface; pinned by the PR's own green tests, not by my harnesses.
  • Platform-specific behavior (macOS/Windows): N/A, Linux container.

Methodology

Environment: node:22-bookworm CI verify container, merge-ref checkout (HEAD merge 56c33466, HEAD^1 base 8e0033d6, HEAD^2 head c17529c1), npm ci + npm run build pre-run at head; base arm rebuilt via root tsc --build in tmp/base-tree (core type errors against head's node_modules are type-level only; all 61 acp-bridge sources emitted, verified). Harnesses in harness/ drive compiled dist/ output (engine, SDK) or vitest-run source (bridge, routes); raw logs in logs/; captures in evidence/ produced by scripts/verify-capture.mjs. Assertion tally: 17 (A/B) + 6 (merge probe) + 18 (boundary) + 7 (SDK wire) + 9 (mutation/flip expectation cells) + 2921 (gates: 1385 acp-bridge + 938 cli server + 330 sdk + 268 webui) = 2958; mutation-induced reds are expected outcomes counted as met expectations, never as failures; typecheck (repo-wide) exit 0 cited separately, not counted.

Evidence images

Evidence files are in the workflow run artifacts; names bind image to claim:

  • 01-flip-intermediate-variants-r11-vs-r37.png — intermediate-variant table: each half of the coalesce fix is load-bearing
  • 02-ab-summary-vs-full-base-vs-head.png — A/B cells: base summary load truncated, head projection clean, full journals byte-identical
  • 03-filter-boundary-probe-18-of-18.png — filter boundary incl. self-reference guard siblings
  • 04-sdk-wire-load-vs-resume.png — wire: load sends liveReplayMode, resume strips it
  • 05-text-merge-preexisting-mechanism.png — summary text-merge is the pre-existing mechanism, content preserved

Qwen Code · sandboxed verification

Evidence images

01-flip-intermediate-variants-r11-vs-r37

02-ab-summary-vs-full-base-vs-head

03-filter-boundary-probe-18-of-18

04-sdk-wire-load-vs-resume

05-text-merge-preexisting-mechanism

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

Qwen Code · sandboxed verification

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@wenshao
wenshao added this pull request to the merge queue Aug 14, 2026
Merged via the queue into main with commit 0493b4a Aug 14, 2026
126 checks passed
@ytahdn
ytahdn deleted the fix/subagent-live-journal branch August 14, 2026 02:13
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review-feedback summary — PR #9057 (round 4)

All seven inline suggestions were verified against the code at this branch head and addressed in one commit (fix(acp-bridge): isolate growth throttle per journal and waiter replay flags (#9057)). No conflict resolution was needed (--conflict false); no base merge was performed.

Findings and dispositions

  • R4-1 — summary-journal usage retention test only covers the both-fields case (compactionEngine.test.ts): Addressed. Added pins each usage disjunct and the non-numeric exclusion separately: an outputTokens-only frame (second disjunct), an inputTokens-only frame (first disjunct), and a non-numeric usage frame (exclusion). Mutation-verified: flipping || to && in isSummaryLiveJournalEvent now fails this test.

  • R4-2 — bridge resume-coerces-to-full guarantee has no bridge-layer test (bridge.ts): Addressed, with a corrected observable. The suggested assertion is infeasible as sketched: resume responses carry no replay projection (replayFieldsFor returns only lastEventId/eventEpoch for the resume action), so there is no liveJournal to assert on. The coercion is instead observable through the coalesce fence: if the resume action recorded the requested summary mode in flight, a concurrent plain (full) resume would be rejected with RestoreInProgressError. Added coerces a summary resume to full replay so a plain resume coalesces. Mutation-verified: dropping the action gate produces exactly that rejection.

  • R4-3 — SDK default-load exact wire-body assertion was repurposed (DaemonClient.test.ts): Addressed. Re-added the default case as omits liveReplayMode from the load wire body when unset, asserting the body is exactly { cwd } when the option is omitted; the summary-mode test is kept. Mutation-verified: defaulting the field to summary fails it.

  • R4-4 — no-page existing-entry attach is the only untested summary-projection call site (bridge.ts): Addressed. Added selects summary live replay on a no-page existing-entry attach: spawnOrAttach, the same three nested/root updates under maxJournalEvents: 2, then a summary loadSession without historyPageSize, asserting ids [1, 3], no nested frame, and no history_truncated marker. Mutation-verified: dropping the mode argument at that call site fails the test.

  • R4-5 — growth-refusal throttle is engine-wide but now serves two journals (compactionEngine.ts): Addressed. Moved the refusal timestamp onto the journal state (LiveJournalState.growthDeniedAt), read/written inside maybeGrowJournalLimits(journal); resetJournal() clears both throttles by recreating both states. This makes a full-journal refusal stop swallowing an independent summary-journal breach ask. As the finding predicted, 10 pre-existing adaptive live-journal growth tests encoded the engine-wide throttle; they were updated to the per-journal ask sequences (same-event root breaches now ask once per journal; counts such as 64→128 for the step-budget walk), preserving each test's intent. Added the probe scenario as a regression test: lets the summary journal ask despite a same-moment full journal refusal (caps 100B, refuse-then-grant advisor, fixed clock; the summary journal retains [1, 3] marker-free). Mutation-verified: restoring the engine-wide throttle fails the new test.

  • R4-6 — coalesced-waiter merge leaks owner-level replay flags (bridge.ts): Addressed. When the waiter recomputes its replay fields (modes differ), the owner-level replay fields (compactedReplay, liveJournal, lastEventId, eventEpoch, replayDegraded, partial, replayError, historyHasMore) are now stripped before spreading the recompute, matching the existing-entry attach path which returns the recompute unmerged. The strip approach was chosen over emitting explicit flags in refreshedReplayFieldsFor's success branch because partial is typed ?: true — an explicit false is not representable — and a clean page fetch must override an owner-time partial/replayError/replayDegraded too. Added does not leak owner replay flags into a waiter whose page came back clean: owner carries historyHasMore: true from its bulk-replay response; the waiter's page fetch succeeds with hasMore: false; the waiter response carries none of the owner flags. Mutation-verified: unstripping the merge leaks historyHasMore: true and fails the test.

  • R4-7 — reconnectSessionId branch summary spread is unpinned (DaemonSessionProvider.tsx): Addressed. Added requests summary live replay when a created session reconnects: explicit sessionId: undefined suppresses the harness's auto-injection, the initial connect goes through createOrAttach (+ attachSession to start the event runner), an epoch-reset resync forces the PATH-B reload through the reconnectSessionId branch, and the test asserts the exact load body { workspaceCwd, timeoutMs: 70_000, liveReplayMode: 'summary' }. Mutation-verified: reverting the spread fails the test.

Conflict notes

None — the branch had no conflicts with origin/main and no merge was performed.

Verification

Commands actually run against the final committed tree (all passed):

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx prettier --write on the six changed files — applied (no formatting drift remained)
  • npx vitest run in packages/acp-bridge (full package suite) — 28 files, 1390 tests passed
  • npx vitest run src/daemon/session/DaemonSessionProvider.test.tsx in packages/webui — 269 tests passed
  • npx vitest run test/unit in packages/sdk-typescript — 31 files, 1529 tests passed
  • npx vitest run src/serve/server.test.ts in packages/cli — 937 tests passed
  • Mutation checks: each of the 7 new/updated regression tests was verified to fail when its target behavior is mutated (per-journal throttle, resume coercion gate, no-page mode argument, waiter-merge strip, usage disjuncts, SDK omission, provider reconnect spread) — all 7 mutants killed
  • Integration tests after npm run bundle were not run: the touched behavior (engine throttle, bridge coalesce merge) is exercised directly by the acp-bridge unit suite and the serve-route suite above, not only through the bundled CLI or integration harness
中文说明

Autofix 审查反馈处理总结 — PR #9057(第 4 轮)

全部 7 条行内建议均已对照本分支头的代码核实,并在一个提交中处理完毕(fix(acp-bridge): isolate growth throttle per journal and waiter replay flags (#9057))。无需解决冲突(--conflict false),未执行 base 合并。

各项发现与处理

  • R4-1 — summary journal 的 usage 保留测试只覆盖“双字段同时存在”一种情况compactionEngine.test.ts):已处理。 新增 pins each usage disjunct and the non-numeric exclusion separately:一个仅带 outputTokens 的帧(钉住第二个分支)、一个仅带 inputTokens 的帧(钉住第一个分支)、一个非数字 usage 的帧(钉住排除规则)。已做变异验证:把 isSummaryLiveJournalEvent 中的 || 翻成 && 会使该测试失败。

  • R4-2 — bridge 层“resume 强制归一化为 full”的保证没有 bridge 层测试bridge.ts):已处理,但改用正确的可观测点。 建议中的断言按原样不可行:resume 响应不携带任何重放投影(resume 动作下 replayFieldsFor 只返回 lastEventId/eventEpoch),因此没有可供断言的 liveJournal。该强制归一化可以通过 coalesce 围栏来观测:若 resume 动作把请求的 summary 模式记录进 in-flight 记录,那么并发的普通(full)resume 会被 RestoreInProgressError 拒绝。新增 coerces a summary resume to full replay so a plain resume coalesces。已做变异验证:去掉 action 门后恰好产生上述拒绝。

  • R4-3 — SDK 中唯一的默认 load 精确 wire-body 断言被改造掉了DaemonClient.test.ts):已处理。omits liveReplayMode from the load wire body when unset 补回默认用例,断言省略该选项时请求体恰为 { cwd };summary 正向测试保留。已做变异验证:把该字段默认成 summary 会使测试失败。

  • R4-4 — 无分页的 existing-entry attach 是唯一未被测试钉住的 summary 投影调用点bridge.ts):已处理。 新增 selects summary live replay on a no-page existing-entry attach:spawnOrAttach 后发送与既有测试相同的三个嵌套/根帧更新(maxJournalEvents: 2),然后不带 historyPageSize 做 summary loadSession,断言 id 为 [1, 3]、无嵌套帧、无 history_truncated 标记。已做变异验证:去掉该调用点的模式参数会使测试失败。

  • R4-5 — 增长拒绝节流是引擎级的,但现在要服务两个 journalcompactionEngine.ts):已处理。 把拒绝时间戳挪到 journal 状态上(LiveJournalState.growthDeniedAt),在 maybeGrowJournalLimits(journal) 内读写;resetJournal() 通过重建两个 journal 状态自然复位两个节流。这样 full journal 的拒绝不再吞掉 summary journal 独立的越限请求。正如该发现所预测,10 个既有 adaptive live-journal growth 测试编码了引擎级节流;已将其更新为按 journal 的询问序列(同一 root 事件越限时每个 journal 各询问一次;例如步数预算测试的计数 64→128),并保持每个测试的原意图。探针场景已作为回归测试补入:lets the summary journal ask despite a same-moment full journal refusal(上限 100B、先拒后准的 advisor、固定时钟;summary journal 无标记地保留 [1, 3])。已做变异验证:恢复引擎级节流会使新测试失败。

  • R4-6 — 合并 waiter 的响应会泄漏 owner 级重放标志bridge.ts):已处理。 当 waiter 重算自己的重放字段(模式不同)时,先把 owner 级的重放字段(compactedReplayliveJournallastEventIdeventEpochreplayDegradedpartialreplayErrorhistoryHasMore)剥掉,再展开重算结果——与 existing-entry attach 路径保持一致(该路径直接返回未合并的重算结果)。选择“剥离”而非在 refreshedReplayFieldsFor 成功分支显式输出标志,是因为 partial 的类型是 ?: true,无法显式输出 false;而干净的分页抓取必须同时覆盖 owner 时刻的 partial/replayError/replayDegraded。新增 does not leak owner replay flags into a waiter whose page came back clean:owner 的 bulk-replay 响应携带 historyHasMore: true,waiter 的分页抓取成功且 hasMore: false,断言 waiter 响应不携带任何 owner 标志。已做变异验证:不做剥离会让 historyHasMore: true 泄漏并使测试失败。

  • R4-7 — reconnectSessionId 分支的 summary 展开没有被测试钉住DaemonSessionProvider.tsx):已处理。 新增 requests summary live replay when a created session reconnects:显式传 sessionId: undefined 抑制 harness 的自动注入,初始连接走 createOrAttach(再用 attachSession 启动事件 runner),epoch-reset 重同步强制一次 PATH-B 重连、经由 reconnectSessionId 分支重新加载,断言 load 的精确请求体为 { workspaceCwd, timeoutMs: 70_000, liveReplayMode: 'summary' }。已做变异验证:还原该展开会使测试失败。

冲突说明

无 — 分支与 origin/main 无冲突,未执行合并。

验证

针对最终提交的树实际执行的命令(全部通过):

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 对 6 个改动文件执行 npx prettier --write — 已应用(无残留格式偏差)
  • packages/acp-bridge 执行 npx vitest run(整包测试)— 28 个文件、1390 个测试通过
  • packages/webui 执行 npx vitest run src/daemon/session/DaemonSessionProvider.test.tsx — 269 个测试通过
  • packages/sdk-typescript 执行 npx vitest run test/unit — 31 个文件、1529 个测试通过
  • packages/cli 执行 npx vitest run src/serve/server.test.ts — 937 个测试通过
  • 变异检查:7 个新增/更新的回归测试逐一验证了其目标行为被变异后会失败(按 journal 的节流、resume 强制归一化门、无分页模式参数、waiter 合并剥离、usage 分支、SDK 省略、provider 重连展开)— 7 个变异全部被杀死
  • 未运行 npm run bundle 之后的集成测试:本次改动的行为(引擎节流、bridge coalesce 合并)由上述 acp-bridge 单元测试与 serve 路由测试直接覆盖,并非只能经由打包后的 CLI 或集成测试框架验证

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

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


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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.12.

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