fix(cli): make the Agent Team teammate tab transcript scrollable in VP mode - #9531
fix(cli): make the Agent Team teammate tab transcript scrollable in VP mode#9531yiliang114 wants to merge 13 commits into
Conversation
…P mode In Virtualized History mode (ui.useTerminalBuffer, on by default) the app owns the whole screen, so there is no terminal-native scrollback. The main conversation view renders its transcript in a ScrollableList virtual viewport, but AgentChatContent rendered the teammate tab transcript through ink's <Static> unconditionally — content that scrolled off screen could not be reached by Page Up, Page Down, arrow keys, or the mouse wheel (#9507). Route the teammate transcript through the same ScrollableList viewport in VP mode: header + committed + live items + spinner live in one viewport pinned to the tail, with Page Up/Page Down, Shift+arrows, Ctrl+Home/End and wheel/scrollbar support. The committed/live split is preserved (items from an executing/confirming tool group onward stay on the interactive render path so approval dialogs keep receiving input). The legacy <Static> path for useTerminalBuffer: false is unchanged — native terminal scrollback already works there.
|
Re-run gate pass on the updated head — still clean, and the new commits land where the review asked.
Moving on to code review. 🔍 中文说明针对更新后的 head 重新执行准入门检查——依然干净,且新提交正是按评审意见落地的。
进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code review (re-run on
|
| Check | Conclusion |
|---|---|
Post Coverage Comment (ubuntu-latest, 22.x) |
❌ failure (downstream artifact miss) |
Test (ubuntu-latest, Node 22.x) |
|
web-shell E2E Smoke (ubuntu-latest, Node 22.x) |
|
Classify PR |
✅ success |
Dependency CVE audit |
✅ success |
Desktop Shell (ubuntu-22.04) |
✅ success |
Desktop Shell (windows-2022) |
✅ success |
Integration Tests (no-AK, No Sandbox) |
✅ success |
Remind on force-push |
✅ success |
Secret scan (TruffleHog) |
✅ success |
One row per check name (latest run); skipped checks omitted (Test macOS/Windows, Integration Tests CLI); failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。
The author's component-level evidence (real viewport machinery + real keypress pipeline, red-before/green-after) pins the contract, but no live multi-teammate VP session has been exercised — the author states this explicitly. Sandboxed verification would settle that remaining claim: @qwen-code /tmux — that Page Up genuinely recovers a teammate's earlier output in a real VP-mode session, and that a pending approval dialog still receives input inside the viewport.
中文说明
代码审查(在 1576cfd 上重跑)
先给独立方案(同前):让队友转录走主视图既有的 ScrollableList 视口,保留已提交/进行中拆分,固定尾部,legacy <Static> 路径不动——对于第 2 轮评审指出的页脚高度过期问题,从 composer 同步一个 layout key 进入控件高度测量 effect,与 liveAgentPanelLayoutKey 对 LiveAgentPanel 的做法完全一致。PR 两点都与方案吻合,没有遗漏更简路径。
本轮对照基线代码重新核实:
- 核心视口路径——契约与首轮完整审查一致:只挂载激活标签页内容(不会两个视口同时监听 Page Up)、所有 hook 在 VP 提前返回之前执行、额外的
!embeddedShellFocused焦点门控正确、key 稳定性成立(h-${item.id}刻意不编码 pending 状态)。VP/legacy 属性一致性逐行复核:已提交、进行中、spinner、header 条目接收的属性与 legacy 路径完全一致。 - 页脚重测量(第 2 轮 critical)——
getAgentComposerLayoutKey覆盖页脚渲染的每一个行数因子(加载行、状态行、排队消息、输入换行),同步进AgentViewContext,并接入 AppContainer 测量 effect 依赖与 provider 两个 memo 依赖数组,每一处都有源码级守卫测试钉住。机制复用getLiveAgentPanelLayoutKey(Scroll-back broken and screen flickers during multi-agent runs in non-VP mode #5798)的既有模式,而非新造。 - 新测量测试在最小组件上用真实 ink 渲染复现了根因形态:无该依赖时页脚增长后可用高度保持过期偏高;有该依赖时预留空间恰好收缩增长量。红/绿纪律良好。
- 选择复制接线与 MainContent 的
TextSelectionController用法一致,包括带安全回退的 ref 视口访问器。未把页脚纳入可选区域是比 MainContent 更窄的契约,不构成回归。
非阻塞项,/review 流程已记录并延后(此处不再重复要求):注释承诺的头尾往返断言(R1-3)、spinner 路径覆盖(D2-1)、依赖守卫测试中两条注释准确性小问题(R4-1/R4-2)。该评审第 4 轮在此 head 上无新发现,仅因下方 CI 状态从批准降级为评论。
测试
CI 证据——引自被审提交上 PR 自身的检查(经 API 获取;按规则本审查为静态审查,不运行 PR 代码)。本 head 上所有运行均已完成——无进行中项——但有 3 项为红,且每一项都可归因于 runner 资源池而非本 diff:
Test (ubuntu-latest, Node 22.x)(第 7 次尝试,job 99231288884):08:32:09 → 09:32:48Z,恰好跑满上限,被 GitHub 生成的注解 "The job has exceeded the maximum execution time of 1h0m0s" 终止。日志显示被杀时套件仍在通过,全程无任何失败测试。是基础设施超时,不是测试失败。Post Coverage Comment (ubuntu-latest, 22.x):因Artifact not found for name: coverage-reports-22.x-ubuntu-latest失败——纯粹是 Test 任务在上传产物前被杀的下游客。web-shell E2E Smoke:在page.waitForFunction超时中撞上工作流timeout-minutes: 20上限;本 PR 未触碰任何 web-shell 代码,且 main 的 E2E 项在同一时间窗口同样为红。- 背景:main 分支 CI 在同一时间窗口同样红/被取消(8 月 30 日 08:49Z 失败及一批取消),不相关 PR 也出现相同超时形态——与本 PR 下维护者归因评论所述的自托管 runner 资源池退化一致。
需要直说的后果:Linux 单测套件在本 head 上从未跑完。最近一次完整绿跑是 0b4f683c(8 月 20 日),早于 layout key 各提交;其后的增量是 23 行 layout key 机制加测试,沿用的是仓库中已验证为绿既有模式。重跑失败任务是转绿的途径;红色各项均不指向本 diff。
(CI 明细见上方英文表格。)
作者的组件级证据(真实视口机制 + 真实按键管线,修复前红/修复后绿)钉住了契约,但没有跑过真实多队友 VP 会话——作者已明确说明。沙箱验证可以补齐这一剩余声明:@qwen-code /tmux——在真实 VP 模式会话中确认 Page Up 确实能找回队友更早的输出,且待审批对话框在视口内仍能接收输入。
— Qwen Code · qwen3.8-max
Reviewed at 1576cfda32889f411135086f50082f43efc1e17f · re-run with @qwen-code /triage
|
Confidence: 4/5 — the code is ready and every stage is clean; the two honest gaps are the never-completed unit-suite run on this head (runner pool, not the diff) and the live-session check nobody has driven yet. Stepping back: the core fix was already a good one on the first pass — observed bug, minimal solution, the main view's own viewport reused rather than a parallel scroller. Everything added since answers review feedback rather than expanding scope: the round-2 critical about the viewport sizing from a stale CI status at post time: all 中文说明置信度:4/5 —— 代码已就绪、各阶段干净;两个如实陈述的缺口是本 head 上从未跑完的单测套件(runner 资源池问题,与 diff 无关)和尚未有人驱动过的真实会话验证。 退一步看:核心修复在首轮就是好的——已观测的 bug、最小方案、复用主视图自己的视口而非新造滚动器。此后所有增量都在回应评审意见而非扩大范围:第 2 轮关于视口使用过期 发布时 CI 状态:本 head 上所有 — Qwen Code · qwen3.8-max Reviewed at |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
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.
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
— qwen3.8-max via Qwen Code /review (v0.21.14)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
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.
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory; 68 tests pass — this review observed 22032 passed.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:271 — [review] D2-1 the VP spinner path is untested — deleting the spinner spread survives the whole new suite (mutant verified); deferred by the code-age rule: anchored on code…packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:263 — [review] R1-1 still stands — item-identity rebuild defeats memo(HistoryItemDisplay); author declined in round 1 as a separate rendering-performance changepackages/cli/src/ui/components/agent-view/AgentChatContent.test.tsx:346 — [review] R1-3 still stands — the third test does not pin the head-to-tail round trip its comment promises; author declined in round 1 as test-matrix expansionpackages/cli/src/ui/components/agent-view/AgentChatContent.tsx:60 — [review] R1-4 still stands — the key-must-not-encode-pending-ness invariant has no test driving a pending-to-committed transition; author declined in round 1packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:342 — [review] R1-5 still stands — the hasFocus/isActive gate is only tested in its all-false default; author declined in round 1 as a separate test-matrix expansionpackages/cli/src/ui/components/agent-view/AgentChatContent.test.tsx:97 — [review] R1-6 still stands — createUIState factory is a near-verbatim copy of MainContent.test.tsx's; author declined in round 1 as unrelated test-infrastructure refac…
中文说明
仅完成部分审查,审查缺口已披露。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory; 68 tests pass — this review observed 22032 passed。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 6 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.3)
Bring in the typecheck:integration and check:tui-dep-direction scripts added on main so the CI gate steps stop failing with "Missing script". Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
AppContainer's controls-height measure effect tracked only main-conversation state, so on the agent tab the Completed/Failed status row, queued messages and input growth never triggered a re-measure: controlsHeight stayed stale-high and the transcript viewport pushed the composer and tab bar past the terminal bottom. AgentComposer now derives a layout key from its height-shifting state (streaming state, status row, queued messages, input text) and syncs it to AgentViewContext; the measure effect depends on that key, mirroring liveAgentPanelLayoutKey from #5798. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Main renamed GeminiRespondingSpinner to RespondingSpinner; the merge kept the old name at the viewport's spinner item and broke typecheck. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Main renamed GeminiRespondingSpinner to RespondingSpinner; update the teammate-tab spinner usage and its test mock so the merged tree compiles. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
CI attribution —
Triggering a failed-jobs rerun; leaving the infra attribution to maintainers. |
|
CI triage (run 33249328264, head 4da1dae): re-running failed jobs. The web-shell E2E Smoke failures are collapsed-groups-persist and split-persist — this PR touches only packages/cli agent-view/AppContainer (0 web-shell files), and the same run lists 6 flaky specs on the shared runner. Test ubuntu failure attribution (7 suites outside the diff, 60m cap) is in the previous comment; Post Coverage Comment failed in 14s (infrastructure). Triggering --failed rerun. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed. Suggestions are inline.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-6 createUIState test-factory duplication (round 3 refiled it with gemini→memory key-drift evidence) — already reported (comment 3818835361), author declined in round 1 as unrelated test-infrastructure refactoring
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
Deferred under the convergence posture (round 3, not a blocker) — recorded, not requested in this round:
packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:348 — [probe] D3-1 agent VP path omits measureAtFullHeight — probe shows one clipped confirmation frame that self-heals next frame; deferred by the code-age rule (anchor unchang…packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:354 — [probe] D3-2 ScrollableList/TextSelectionController wiring duplicated near-verbatim from MainContent and already drifted; deferred by the code-age rule (anchor unchanged s…packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:271 — [review] D3-3 (re-deferral of D2-1) VP spinner branch untested — deleting the spinner spread survives the suite; deferred by the code-age rule
Convergence: round 3 posted 1 inline comment(s), 1 of them reported for the first time; the previous round posted 1 (1 new). The rate of new findings is not falling. Batching the remaining fixes and verifying them before the next push, or dropping this PR's reviews to --severity-floor critical, keeps the loop from re-deriving the same set. (Observation only — nothing was withheld from this review because of this observation.)
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
收敛姿态下延后(第 3 轮,非阻断)——已记录,本轮不要求修改:共 3 条(原文未翻译,列表见上方英文部分)。
收敛情况:第 3 轮发布了 1 条行内评论,其中 1 条是首次提出;上一轮发布了 1 条(其中 1 条首次提出)。新发现的产出速度没有下降。把剩余修复攒成一批、验证后再推送,或将本 PR 的评审降到 --severity-floor critical,可以避免循环反复推导同一组发现。(仅为观察——本轮评审未因此扣留任何内容。)
— qwen3.8-max via Qwen Code /review (v0.22.3)
) R3-1: the provider link of the #9507 layout-key chain was the only link without a source guard. Pin agentComposerLayoutKey in the state memo deps and setAgentComposerLayoutKey in the actions memo deps of AgentViewContext.tsx by extending app-container-controls-dep.test.ts in the PR's established guard style. Mutation-verified: dropping either entry from its deps array (while the object literal keeps it) turns exactly the matching new test red, and every pre-existing test stays green. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
2 Suggestion(s) were drafted inline past the resolved critical posting floor — the floor engaged early: the first-time-finding rate has not fallen for 2 consecutive round(s); the CLI moved them into the deferral list below (floor enforcement).
Deferred under the convergence posture (round 4, not a blocker) — the floor engaged early: the first-time-finding rate has not fallen for 2 consecutive round(s) — recorded, not requested in this round:
packages/cli/src/ui/app-container-controls-dep.test.ts:110 — [review] R4-2: This guard comment states the staleness direction backwards. If the dep above is dropped and the agent footer grows (status row appears, messages queue, input wraps…packages/cli/src/ui/app-container-controls-dep.test.ts:152 — [review] R4-1: This comment describes a failure mechanism the code cannot have. setAgentComposerLayoutKey is a raw useState setter (AgentViewContext.tsx:165, passed unmodified…
中文说明
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
2 条 Suggestion 在已解析的 critical 发布下限之外被起草为行内评论——发布下限因首次发现速率连续 2 轮未下降而提前生效;CLI 已将其移入下方延后清单(下限强制执行)。
收敛姿态下延后(第 4 轮,非阻断)——发布下限因首次发现速率连续 2 轮未下降而提前生效——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
CI attribution — Shape: job-level 1h timeout kill. Every suite that completed before the kill passed:
The runner-health probe also reported its positive control inconclusive ("the injected always-failing test did not turn the run red — a dead runner, a collector that skipped it, or a reporter that dropped the failure"), i.e. the runner itself was sick. Same sick-runner/timeout signature seen repo-wide this window (#10159, #10394, #9260 prior attempts).
Triggering a failed-jobs rerun. |
|
CI attribution — run 33255831712 latest attempts (head
|
|
@qwen-code /triage |
|
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: 117 passed · 0 failed · 117 total Flakiness gate: ✅ 4 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:117 通过 · 0 失败 · 117 总计 抖动门:✅ 4 changed test file(s) x 5 identical rounds, no divergence Verification reportPR #9531 verification — fix(cli): make the Agent Team teammate tab transcript scrollable in VP modeVerdict: 中文摘要
Central claim and A/B proofCentral claim: with The PR's own harness (
Flip: 1/3 → 3/3; the single flip is exactly the central-claim test. Witness: Independent boundary harness (
Head 5/5, base 2/5 — the flips are precisely the viewport-specific probes. Witness: Mutation matrix (on head, one hunk reverted at a time, restored after)
M3 classification — redundant defence, not a defect. FindingsNo blocking findings.
Not covered
MethodologyEnvironment: CI merge-ref checkout (depth 2), Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
|
@qwen-code /triage |
|
Sandboxed verification: ❌ not passed — non-deterministic tests (flakiness gate); job cancelled before the report - workflow run Flakiness gate: ❌ 1 of 4 changed test file(s) returned different results across identical re-runs (1 full round(s)) The job was cancelled before producing a report, but the deterministic flakiness gate had already observed run-to-run divergence — the per-round matrix is in the gate step output of the workflow run log. 中文 — 判定:❌ 不通过 · 测试结果不确定(抖动门);作业在报告前被取消抖动门:❌ 1 of 4 changed test file(s) returned different results across identical re-runs (1 full round(s)) 作业在生成报告前被取消,但确定性抖动门已观测到轮间分歧——各轮矩阵见工作流运行日志中 gate step 的输出。 — Qwen Code · sandboxed verification |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅ Code-only approval: the red CI legs on this head are runner-pool casualties (see the Stage 3 comment) — merge stays gated on a green run.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
5 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R5-1 agent VP viewport measureAtFullHeight parity gap (this round's probe re-confirmed the transient one-frame clip) — already recorded (round-3 deferral D3-1)
- R5-2 round-trip test gap in the third AgentChatContent test — already reported (round-1 R1-3, thread 3818835345), author declined
- R5-3 duplicated VP selection-bridge wiring with MainContent — already recorded (round-3 deferral D3-2)
- R5-4 VP spinner path untested — already recorded (round-2 deferral D2-1, round-3 deferral D3-3)
- R5-5 item-identity rebuild defeating memo(HistoryItemDisplay) — already reported (round-1 R1-1, thread 3818835325), author declined
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally; the packages/cli unit suite timed out under shared-host contention (the PR's own 4 test files pass 30/30 in separate runs) and the test-efficacy probe was inconclusive (harness control never ran green).
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
Deferred under the convergence posture (round 5, not a blocker) — the floor engaged early: the first-time-finding rate has not fallen for 2 consecutive round(s) — recorded, not requested in this round:
packages/cli/src/ui/components/agent-view/AgentComposer.tsx:299 — [review] D5-1 rationale comments at 3 sites invert the staleness direction (controlsHeight stale-low, viewport stale-high) — overlaps round-4 R4-2
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 5 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally; the packages/cli unit suite timed out under shared-host contention (the PR's own 4 test files pass 30/30 in separate runs) and the test-efficacy probe was inconclusive (harness control never ran green)。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
收敛姿态下延后(第 5 轮,非阻断)——发布下限因首次发现速率连续 2 轮未下降而提前生效——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.3)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
4 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R6-1 round-trip test missing the back-to-tail leg — already reported (round-1 R1-3, thread 3818835345), author declined
- R6-2 agent VP wiring omits measureAtFullHeight and getAdditionalSelectableRects — already recorded (round-3 deferrals D3-1 and D3-2; round-5 R5-1 and R5-3)
- R6-3 viewport focus-gate inputs untested — already reported (round-1 R1-5, thread 3818835358), author declined
- R6-4 VP spinner path untested — already recorded (round-2 deferral D2-1, round-3 deferral D3-3, round-5 R5-4)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 4 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
8 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- measureAtFullHeight omitted from the agent VP ScrollableList — already recorded (round-3 deferral D3-1, round-5 R5-1, round-6 R6-2)
- ScrollableList/TextSelectionController wiring duplicated from MainContent, incl. the omitted getAdditionalSelectableRects — already recorded (round-3 deferral D3-2, round-5 R5-3, round-6 R6-2)
- item-identity rebuild defeats memo(HistoryItemDisplay) — already reported (round-1 R1-1, comment 3818835325), author declined
- the third AgentChatContent test does not pin the head-to-tail round trip — already reported (round-1 R1-3, comment 3818835345), author declined
- the key-must-not-encode-pending-ness invariant has no transition test — already reported (round-1 R1-4), author declined
- viewport focus-gate inputs untested and the confirmation case never rendered — already reported (round-1 R1-5, comment 3818835358), author declined
- VP spinner path untested — already recorded (round-2 deferral D2-1, round-3 D3-3, round-5 R5-4, round-6 R6-4)
- createUIState test-factory duplication and its gemini-to-memory phantom keys — already reported (round-1 R1-6, comment 3818835361), author declined
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally; the test-efficacy probe was also inconclusive (harnessValidated: null — the probe runner hit this repo's vitest prerequisite guard and collected nothing), so there is no mutant, revert or hunk evidence either way.
Not explored to full depth (tool budget reached): "agent 1d": none — I used roughly 20 of the ~52 allotted calls and finished the walk.; "agent reverse-audit (round 7)": I did not execute the proposed real- AppContainer measurement arm, so its feasibility rests on reading AppContainer.test.tsx:5660-5730 and ink's updateConta….
Test Plan (not a blocker): src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory.
Deferred under the convergence posture (round 7, not a blocker) — recorded, not requested in this round:
packages/cli/src/ui/components/agent-view/AgentComposer.tsx:305 — [probe] D7-1 getAgentComposerLayoutKey omits the AgentFooter row's width-shifting inputs, so the footer grows a row at widths 40-53 without re-measuring controlsHeightpackages/cli/src/ui/components/agent-view/AgentChatContent.tsx:342 — [probe] D7-2 the new viewport's dialogsVisible focus gate can only disable navigation, because no dialog is ever rendered on an agent tabpackages/cli/src/ui/AppContainer.tsx:3765 — [probe] D7-3 ExitWarning is a second row-growing child of the measured box with no measure dep, so the rigid viewport is sized stale-high (25-row frame in a 24-row terminal)packages/cli/src/ui/components/agent-view/AgentChatContent.tsx:337 — [probe] D7-4 the VP early return removes historyRemountKey's last VP-mode consumer, falsifying four comments in untouched files and leaving an inert VP-only bumppackages/cli/src/ui/app-container-controls-dep.test.ts:123 — [probe] D7-5 the guard suite never pins that AgentComposer renders inside the mainControlsRef box; relocating it leaves 32 + 2 + 178 tests greenpackages/cli/src/ui/app-container-controls-dep.test.ts:114 — [probe] D7-6 the new guard's closed order-sensitive regex reddens on the D7-1 fix and on a cosmetic reorder that yields a byte-identical key
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 8 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally; the test-efficacy probe was also inconclusive (harnessValidated: null — the probe runner hit this repo's vitest prerequisite guard and collected nothing), so there is no mutant, revert or hunk evidence either way。
未探索到全部深度(达到工具调用预算):"agent 1d":none — I used roughly 20 of the ~52 allotted calls and finished the walk.;"agent reverse-audit (round 7)":I did not execute the proposed real- AppContainer measurement arm, so its feasibility rests on reading AppContainer.test.tsx:5660-5730 and ink's updateConta…。
Test Plan(非阻断):src/ui/components/agent-view/AgentChatContent.test.tsx — no such file or directory; src/ui/components/shared/ScrollableList.test.tsx — no such file or directory。
收敛姿态下延后(第 7 轮,非阻断)——已记录,本轮不要求修改:共 6 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max-2026-09-02 via Qwen Code /review (v0.22.3)



What this PR does
When Virtualized History mode is on (
ui.useTerminalBuffer, the default), the teammate tab transcript is now rendered through the sameScrollableListvirtual viewport the main conversation view uses: header, committed items, live items, and the running spinner all live in one viewport pinned to the tail, so Page Up / Page Down, Shift+arrows, Ctrl+Home/End, and the mouse wheel can reach earlier output. The committed/live split is preserved — items from an executing/confirming tool group onward stay on the interactive render path, so teammate approval dialogs keep receiving input inside the viewport. WithuseTerminalBuffer: falsenothing changes: the transcript keeps flowing through<Static>into the terminal's native scrollback, which already worked there.Why it's needed
In VP mode the interactive UI takes over the whole terminal screen, so there is no terminal-native scrollback to fall back on.
AgentChatContentrendered the teammate tab transcript with ink's<Static>unconditionally, so once a teammate's output scrolled past the visible area it could not be retrieved by any means — Up arrow, Page Up/Page Down, and the mouse wheel all had no effect (#9507). The main conversation view does not have this problem because its transcript already renders in a scrollable virtual viewport; this brings the teammate tab to parity.Reviewer Test Plan
How to verify
Component-level reproduction and fix verification use the real
ScrollableList/VirtualizedListviewport machinery plus the real keypress pipeline (no viewport mocks):npx vitest run src/ui/components/agent-view/AgentChatContent.test.tsxinpackages/cli. Before this PR, the VP-mode test fails because the renderer emits all 40 transcript lines at once and Page Up is a no-op; after this PR, the viewport starts pinned to the tail, Page Up reveals earlier output, the tail leaves the visible window, and the legacy (useTerminalBuffer: false) path still emits everything unchanged. Full agent-view regression:npx vitest run src/ui/components/agent-view/ src/ui/components/shared/ScrollableList.test.tsx— 68 tests pass.tsc --noEmitandeslintreport nothing new for the changed files (the remaining repo-wide tsc errors are pre-existing on pristinemainin this environment:acpAgent.ts,daemon-status.ts,workspace-extensions-controller.ts,native-audio-recorder.ts). Manual check: enable Agent Team (QWEN_CODE_ENABLE_AGENT_TEAM=1), create a team, have a teammate produce more output than fits on one screen, switch to its tab, and scroll back with Page Up.Evidence (Before & After)
Component-level frames from the reproduction test (VP mode, 40 transcript lines, viewport height 8):
Before (old always-
<Static>renderer — every line emitted, Page Up does nothing):After (viewport pinned to the tail on open):
After Page Up × N (earlier output is back in view, tail left the window):
Tested on
Linux ✅ is component-level verification (real viewport + keypress pipeline driven through ink-testing-library, red-before/green-after); a live multi-teammate terminal session was not exercised on this machine.
Environment (optional)
Node v24,
npx vitest runinpackages/clion Linux; no sandbox.Risk & Scope
<Static>— scroll behavior matches the main view, but any viewport-specific rendering quirks (height estimation, scrollbar) now apply to teammate transcripts too; the executing/confirming split keeps approval dialogs on the interactive path.useTerminalBuffer: falserendering is byte-for-byte the previous code path.Linked Issues
Fixes #9507
中文说明
这个 PR 做了什么
当 Virtualized History 模式开启(
ui.useTerminalBuffer,默认开启)时,队友标签页的转录现在通过与主对话视图相同的ScrollableList虚拟视口渲染:头部信息、已提交条目、进行中条目和运行中的 spinner 都位于同一个固定在尾部的视口内,因此 Page Up / Page Down、Shift+方向键、Ctrl+Home/End 以及鼠标滚轮都可以回看更早的输出。已提交/进行中的拆分逻辑被保留——从正在执行/等待确认的工具组开始的条目仍走可交互渲染路径,保证队友的审批对话框在视口内仍能接收输入。useTerminalBuffer: false时完全不变:转录继续通过<Static>流入终端原生回滚缓冲区,那条路径本来就没有问题。为什么需要
VP 模式下交互式界面接管整个终端屏幕,没有终端原生回滚可以兜底。
AgentChatContent无条件用 ink 的<Static>渲染队友标签页转录,所以一旦队友的输出滚出可见区域就无法通过任何方式找回——向上箭头、Page Up/Page Down、鼠标滚轮全部无效(#9507)。主对话视图没有这个问题,因为其转录本来就渲染在可滚动的虚拟视口里;本 PR 让队友标签页对齐这一行为。评审测试计划
如何验证
组件级复现与修复验证使用真实的
ScrollableList/VirtualizedList视口机制和真实按键管线(不 mock 视口):在packages/cli下运行npx vitest run src/ui/components/agent-view/AgentChatContent.test.tsx。修复前 VP 模式测试失败,因为渲染器一次性输出全部 40 行转录且 Page Up 无效;修复后视口初始固定在尾部,Page Up 可以回看更早输出、尾部离开可见窗口,且 legacy(useTerminalBuffer: false)路径仍原样输出全部内容。完整 agent-view 回归:npx vitest run src/ui/components/agent-view/ src/ui/components/shared/ScrollableList.test.tsx,68 条测试全部通过。tsc --noEmit和eslint对改动文件无新增报错(本环境下仓库层面剩余的 tsc 错误在纯净main上同样存在:acpAgent.ts、daemon-status.ts、workspace-extensions-controller.ts、native-audio-recorder.ts)。手动验证方式:启用 Agent Team(QWEN_CODE_ENABLE_AGENT_TEAM=1),创建团队,让队友产生超过一屏的输出,切换到它的标签页,用 Page Up 回滚。证据(修复前后)
来自复现测试的组件级帧(VP 模式,40 行转录,视口高度 8):
修复前(旧的纯
<Static>渲染——所有行一次性输出,Page Up 无效):帧内同时包含AGENT_HEADER、user-msg-0到user-msg-39全部行,没有任何滚动能力。修复后(打开时视口固定在尾部):帧内为
user-msg-32到user-msg-39。按若干次 Page Up 后(更早的输出回到视口,尾部离开窗口):帧内为
user-msg-0到user-msg-7。测试平台
Linux ✅ 为组件级验证(真实视口 + 按键管线经 ink-testing-library 驱动,修复前红、修复后绿);本机未跑真实的多队友终端会话。macOS / Windows⚠️ 未测试。
环境
Node v24,Linux 下
packages/cli内npx vitest run;无沙箱。风险与范围
<Static>——滚动行为与主视图对齐,但视口特有的渲染特性(高度估算、滚动条)也会作用于队友转录;执行中/确认中的拆分保证审批对话框仍在可交互路径上。useTerminalBuffer: false的渲染与原代码路径完全一致。关联 Issue
Fixes #9507