feat(web-shell): compact agent activity summaries - #9657
Conversation
|
Re-run on the current head, after the autofix rounds that followed the round-5 review. Template looks good ✓ Problem: real and observable — in compact mode, parallel-agent progress and completed thinking render as separate top-level rows, and the pre-existing tests encoded exactly that behavior. This PR intentionally reworks the folding hierarchy. Not a theoretical concern; the PR has also been through sandboxed A/B verification and an independent real-Chromium pass on earlier heads. Direction: aligned. Compact mode is an existing web-shell feature and this tightens its presentation rather than adding a parallel system. claude-code CHANGELOG has no direct counterpart (its "compact" entries are about context compression, not display), but transcript presentation is clearly product-relevant. Size: no core paths touched — everything lives under Approach: scope feels right. It reuses the existing compact-merge pass, Risk: no elevated risk signals (no high-risk paths matched). Moving on to code review. 🔍 中文说明在第 5 轮审查之后的自动修复轮次之上,对当前 head 重新运行。 模板完整 ✓ 问题:真实且可观察——紧凑模式下,并行智能体进度和已完成的思考会作为独立的顶层行渲染,既有测试恰好编码了该行为。本 PR 有意重构折叠层级。不是理论性问题;此 PR 在较早的 head 上已经过沙箱 A/B 验证和独立的真实 Chromium 验证。 方向:对齐。紧凑模式是 web-shell 已有功能,本 PR 收紧其展示而非新增并行系统。claude-code CHANGELOG 没有直接对应项(其 "compact" 条目均关于上下文压缩而非展示),但转录展示显然属于产品相关领域。 规模:未触及核心路径——全部改动位于 方案:范围合理。复用现有紧凑合并流程、 风险:无升级风险信号(未命中高风险路径)。 进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewIndependent proposal first: stop special-casing TodoWrite/AskUserQuestion/agent groups in the compact merge, keep lone thoughts/tools and agent-only runs standalone via a run-level guard, nest consecutive agents inside summaries by reusing What I verified on this head, specifically:
Nothing blocking found. Two non-blocking nits carried from the last round: the Files changed (16)
CI test evidenceAll PR CI checks on the reviewed head are green — the ubuntu suite (which carries this PR's adapter/DOM/component tests), the web-shell E2E smoke, and the visual capture all passed. macOS/Windows matrix entries and the CLI integration lane are skipped by configuration for this branch; the finalize job keeps the table current.
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 Sandboxed verification is already in flight for this head (triggered with the last Not verified: pixel-level rendering on Windows/Linux (author marked N/A); live behavior was not exercised in this unattended run — the in-flight verify run is the lane for that. 中文说明代码审查先给出独立方案:在紧凑合并中不再对 TodoWrite/AskUserQuestion/智能体组做特殊处理,用运行级守卫让单独的思考/工具和仅智能体运行保持独立,连续智能体通过复用 本 head 上重点核实:
未发现阻塞问题。两个非阻断小项沿自上一轮: CI 测试证据被审查 head 上的 PR CI 检查全部为绿——ubuntu 套件(包含本 PR 的 adapter/DOM/组件测试)、web-shell E2E 冒烟和视觉采集均通过。macOS/Windows 矩阵项与 CLI 集成通道在该分支上按配置跳过;finalize 任务会持续更新表格。 沙箱验证已在本 head 上进行中(随最近一次 未验证:Windows/Linux 上的像素级渲染(作者标记 N/A);本次无人值守运行未执行实际行为——进行中的 verify 即为该路径。 — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — clean review on the current head; the last point is withheld for the in-flight verify run on this exact commit and two non-blocking nits. Stepping back: this PR went through a long loop — the round-5 Critical (translation-popover clicks toggling the folded thought), the hit-area regression, the later-agent thought gap — and the current head addresses every one of them rather than papering over them. The popover guard is the exact The standing maintainer change-request from round 5 is, as far as the diff and tests show, fully addressed by this head — each finding has a corresponding fix and regression test. The remaining nits are non-blocking: the unrelated formatting reflow in the cua-driver script test, and the missing App-side test for the context provider wrap (consumption is integration-tested through a mock). Approving as the gate's vote, pinned to the reviewed commit; final sign-off rests with the maintainer whose review is still open. 中文说明置信度:4/5 —— 当前 head 审查干净;最后一点保留给本提交上仍在进行的 verify 运行和两个非阻断小项。 整体来看:这个 PR 经历了较长的循环——第 5 轮的 Critical(翻译弹窗点击会切换折叠的思考)、点击热区回归、后续智能体思考缺口——而当前 head 逐一正面解决了这些问题,而非敷衍绕过。弹窗守卫正是审查所建议的 就 diff 与测试所见,第 5 轮遗留的维护者修改请求已被当前 head 完全解决——每项发现都有对应的修复和回归测试。剩余小项均非阻断:cua-driver 脚本测试中无关的格式化重排,以及 context provider 包裹缺少的 App 侧测试(消费端已通过 mock 的集成测试覆盖)。 以门禁身份批准,固定在被审查的提交上;最终签核仍由审查未关闭的维护者决定。 — Qwen Code · qwen3.8-max Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterFull-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
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. |
chiga0
left a comment
There was a problem hiding this comment.
No blocking findings.
Checked:
isAgentOnlyToolGroup/isBackgroundAgentOnlyToolGroupboth excludesummary-prefixed IDs — prevents compact summary messages from being re-consumed by the parallel-agent grouping path. Correct.isMergedToolGroupsimplification:isStandaloneToolGroupremoval meansAskUserQuestionandTodoWritecan now merge;isForceExpandGroup(pending-approval guard) is still inisMergedToolGroup, so live approval tools remain force-expanded. No regression.run.length <= 1condition: single-item runs stay standalone, matching the updated test assertions (msg-g3visible,msg-summary-g3absent). Correct.parallelAgentsByFirstCallIdgrouping loop insidecompactSummary: consecutive runs of ≥2 agents correctly identified; non-consecutive agents handled per-run;groupedAgentCallIdsskip set prevents double-render. Correct.ThoughtLinerefactor (outerdiv[role=button]→ inner<button>): click bubbles from inner button to outerdiv.onClickcorrectly;~sibling CSS selector for chevron opacity (button.chatSummaryThoughtSummary:focus-visible ~ span.chevron) valid because chevron span is a subsequent sibling inside.chatSummaryThoughtHeader. Correct.todos.tstimestamp fix: per-toolendTime ?? startTime ?? message.timestampmore granular than message-level timestamp for merged groups; ordering withincomputeTodoDetailsis unaffected since iteration is still over messages in order. Correct.CompactModeContext.Providerwrapping bothArtifactPanelinstances inApp.tsx; integration test confirmsdata-compact-mode="true"propagates to the subagent transcript. Correct.formatCompletedToolSummarysummarizeAgentsflag: only set whencompactSummary=true; default path unchanged; EN + ZH strings added. Correct.
Ran (CI, ubuntu-latest, Node 22.x):
Test✅ ·web-shell E2E Smoke✅ ·Capture web-shell visuals✅- SKIPPED:
Test (windows-latest),Test (macos-latest),Integration Tests (CLI)— all review-automation matrix skips, no web-shell test coverage loss.
Reviewed with AI assistance.
|
@qwen-code /verify |
|
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: 50 passed · 0 failed · 50 total Flakiness gate: ✅ 5 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:50 通过 · 0 失败 · 50 总计 抖动门:✅ 5 changed test file(s) x 5 identical rounds, no divergence Verification reportPR 9657 — feat(web-shell): compact agent activity summariesVerdict: 中文摘要
Central claim + A/BCentral claim: in compact mode, adjacent thinking, tool activity, and parallel agents fold into one activity summary whose expansion shows a nested The identical harness files (
Witnesses: Bundled-fix separation (commit 1 vs commit 2): with head's tree but base's
Sibling probes
Mutation matrixWitness:
Findings (non-blocking)
Not covered
MethodologyEnvironment: Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
chiga0
left a comment
There was a problem hiding this comment.
Re-reviewing new commits vs prior approved head 9f62da57. No new blockers.
9dde892b fix: preserve merged todo timing
todos.ts:todoDetailSignaturenow includes TodoWrite tool spans (removed the!isTodoWriteToolNameexclusion) and uses per-snapshottimestampinstead ofmessage.timestamp. Correct —computeTodoDetailsreads both, so the memo key must cover both.- New test confirms the signature changes when a todo tool gains an
endTime. ✅
00a009cc fix: address compact summary review
ToolGroup.tsx:opensSubagentDetailsandopensMonitorDetailsnow guard on!compactSummary. In compact-summary mode the outer button toggles expand/collapse first; subagent/monitor details are only opened when not in compact mode. TheonClickhandler has the matching guard. ✅- New test confirms clicking the outer compact-summary button expands (aria-expanded="true") without triggering
onOpen. ✅ MessageList.dom.test.tsx: new test verifies a pending-approval agent is kept outside the parallel-agents compact summary. ✅MessageItem.dom.test.tsx: new test verifies onlysummary-*prefixed groups receivecompactSummary=true. ✅
CI (00a009cc): Test ubuntu ✅ · E2E Smoke ✅ · Capture web-shell visuals ✅
Reviewed with AI assistance.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/components/MessageList.tsx:293 — [review] The synthetic compact-summary invariant is a raw…packages/web-shell/client/components/messages/ToolGroup.tsx:1669 — [probe] The >= 2 threshold keeping a single agent on the normal…packages/web-shell/client/components/messages/ToolGroup.tsx:1764 — [probe] The skip that keeps grouped non-first agents from…packages/web-shell/client/components/messages/ToolGroup.tsx:1794 — [review] The thoughts→ThoughtLine mapping block is duplicated…packages/web-shell/client/components/messages/ToolGroup.tsx:1794 — [probe] Thoughts bound to grouped (non-first) agents have no test…
中文说明
已审查——无阻断问题。 建议见行内评论。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.21.15)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Deferred under the convergence posture (round 3, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/App.tsx:13127 — [probe] no test pins the CompactModeContext providers around the ArtifactPanel mountspackages/web-shell/client/components/messages/tools/ToolChrome.module.css:69 — [review] the new thinking-summary button suppresses its focus outline
中文说明
收敛姿态下延后(第 3 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.21.15)
|
@qwen-code /verify |
|
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: 59 passed · 0 failed · 59 total Flakiness gate: ✅ 7 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:59 通过 · 0 失败 · 59 总计 抖动门:✅ 7 changed test file(s) x 5 identical rounds, no divergence Verification reportPR 9657 — feat(web-shell): compact agent activity summaries (follow-up round)Verdict: 中文摘要
Previous-finding status (follow-up round)The previous round verified head
Central claim + A/BCentral claim: in compact mode, adjacent thinking, tool activity, and parallel agents fold into one activity summary; first expansion shows a nested The identical harness files (
Witnesses: Two base-arm expectations were corrected after first observation and are recorded here for auditability: base renders agent panels as Delta since the previous round (commits
|
| Mutant | Suite | Result | Killing test / classification |
|---|---|---|---|
M1 drop summary- guards |
MessageList.dom (134) | killed | keeps a folded single-agent summary separate from an approving agent — changed from survived at the old head; finding 2 fixed |
| M2 drop agent-only-run exception | MessageList.dom | killed | keeps a parallel-agent-only run on its direct path |
| M3 drop lone-item exception | MessageList.dom | killed | merges tool groups separated by completed thinking (trailing lone tool) |
| M4 disable consecutive-agent nesting | ToolGroup.test (75) | killed | nests parallel-agent details behind the compact summary |
| M5 disable agent-aware summary | ToolGroup.test | killed | same nesting test (render path; the direct formatToolGroupSummary unit test stays green because M5 mutates the call site, not the function) |
| M6 adapter: TodoWrite standalone again | transcriptToMessages.test (135) | killed ×2 | both renamed merge tests |
M7 drop !compactSummary (subagent) |
ToolGroup.test | killed | expands a single-agent compact summary before opening agent details (new) |
M8 drop !compactSummary (monitor) |
ToolGroup.test | killed | expands a single-monitor compact summary before opening monitor details (new) |
| M9 drop App.tsx ArtifactPanel providers | SubagentDetail.integration + MessageItem.dom (13) | survived (13/13 green) | coverage gap — finding 1, stands |
M10 compactSummary={false} in MessageItem |
MessageItem.dom (11) | killed | marks only synthetic groups as compact summaries (new) |
INT revert utils/todos.ts to base |
WebShellTranscript.dom + todos.test (91) | killed ×3 | see intermediate build |
Intermediate build (commit-1 vs commit-2 separation)
Reverting utils/todos.ts to its HEAD^1 version (byte-identical by construction of git checkout HEAD^1 --) at the head tree reproduces the pre-commit-2 state. Witness: 04-intermediate-todo-timing.png.
| build | merged-group todo timing | suites |
|---|---|---|
| base | n/a (groups never merged) | green |
intermediate (base todos.ts at head) |
collapses to the group timestamp; empty tool-time window | red ×3: pre-existing derives task detail from todo_write transcript snapshots, plus the two new tests uses todo tool timestamps inside a merged tool group and changes when a todo tool end time arrives |
| head (both commits) | per-tool boundaries | green |
The timing fix is now pinned by three tests instead of one; commit 2 remains load-bearing.
Findings (non-blocking)
- The App-level compact-mode wiring for the artifact panel is still unpinned by any test (carried over, re-measured as M9). The wiring is correct at this head; the gap is that deleting all four provider lines changes no test outcome, so a future regression would make subagent transcripts in the artifact panel silently render non-compact. Suggested shape of a pin (unchanged from the previous round, not applied here — advisory only): render through
App's panel slot, or assert against the realCompactModeContextexport rather than a test-provided one, using thedata-compact-modeseam the integration test already exposes. Completeness reporting, not a merge condition. - Behavior changes not named in the description (carried over + one addition, all measured on both arms): background agents with launch narration fold into the compact summary instead of the direct background row (D1); an active AskUserQuestion row folds into the summary (D4 — the answer UI is the dedicated prompt, nothing interactive is lost); and the approving-agent seam now keeps the approving agent out of any parallel grouping (E3 — base rendered it inside the direct parallel row; approval UI was visible in both arms). All three are design-consistent and two are pinned by the PR's own tests.
- Investigated and re-disproved — thinking-row focus indicator (carried over):
outline: noneon the new native button matches the pre-existing.chatSummary:focus-visiblehouse pattern in the same stylesheet; the chevron-on-focus cue survives. Not a regression.
Not covered
- Pixel-level visual verification of the nested rows (no browser in this container); Playwright e2e/visual suites not run. The PR declares the same gap for Linux/Windows.
- Per-commit attribution: the checkout is depth-2 and shallow —
git rev-list HEAD^1..HEAD^2returns 1 commit while the metadata lists 5;00a009cande7115034are not individually reachable. The aggregateHEAD^1..HEADdiff is what was verified; the delta section above is inferred from that aggregate diff plus the test names, not from per-commit exercise. - Full base suite not re-run (the harness measured base behavior directly; the head suite is green 4063/4063, so no pre-existing-failure attribution was needed).
- A dedicated harness cell for "the merged group's expansion renders the Todo checklist" (Reviewer Test Plan step 7): group membership is proven by A6/C1; the checklist rendering itself is pinned only by the repo's own suite (WebShellTranscript/ToolGroup tests in the green gate).
- The flakiness gate is owned by the workflow (
steps.flake), not re-run here.
Methodology
Environment: node:22-bookworm CI container, merge-ref checkout (HEAD=625494e, base 7a4566c, verified head a87c4dc). Harnesses are vitest+jsdom test files kept in harness/ and copied into each tree at run time (removed afterwards; git status --porcelain verified empty of tracked changes after every mutation restore). The base worktree reused the root node_modules (PR leaves package.json/package-lock.json untouched — empty diff) plus a symlink of web-shell's nested node_modules (third-party only, PR-untouched); realpath checks confirmed the internal @qwen-code/sdk/webui links resolve into head-tree packages that git diff HEAD^1..HEAD --stat shows unchanged, so no changed code crossed the workspace boundary in the control arm. Mutations were applied by harness/mutate.mjs (exact-count string replacement, fail-loud) or git checkout HEAD^1 -- <file> and restored via git checkout HEAD --. Gates at head: full packages/web-shell suite 4063/4063, tsc -p tsconfig.json --noEmit clean, with a planted type error proving the typecheck gate live. Evidence captures via scripts/verify-capture.mjs. Raw logs in logs/, per-cell JSON in logs/head-arm.json / logs/base-arm.json, harness sources in harness/.
Flakiness gate log
rounds=5 files=7 skipped=0
file packages/web-shell/client/adapters/transcriptToMessages.test.ts: (cd packages/web-shell) npx --no-install vitest run ./client/adapters/transcriptToMessages.test.ts
file packages/web-shell/client/components/MessageItem.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/MessageItem.dom.test.tsx
file packages/web-shell/client/components/MessageList.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/MessageList.dom.test.tsx
file packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/WebShellTranscript.dom.test.tsx
file packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/artifacts/SubagentDetail.integration.test.tsx
file packages/web-shell/client/components/messages/ToolGroup.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/messages/ToolGroup.test.tsx
file packages/web-shell/client/utils/todos.test.ts: (cd packages/web-shell) npx --no-install vitest run ./client/utils/todos.test.ts
per-file results (P=pass F=fail I=infra-exit, one letter per run):
packages/web-shell/client/adapters/transcriptToMessages.test.ts: PPPPP
packages/web-shell/client/components/MessageItem.dom.test.tsx: PPPPP
packages/web-shell/client/components/MessageList.dom.test.tsx: PPPPP
packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: PPPPP
packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: PPPPP
packages/web-shell/client/components/messages/ToolGroup.test.tsx: PPPPP
packages/web-shell/client/utils/todos.test.ts: PPPPP
verdict: pass
summary: 7 changed test file(s) x 5 identical rounds, no divergence
--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 1 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 2 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 2 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 3 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 3 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 4 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 4 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 5 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 5 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
Evidence images
Harness scripts and raw logs are in the workflow run artifacts (7-day retention).
— Qwen Code · sandboxed verification
…web-shell-compact-thinking # Conflicts: # packages/web-shell/client/components/MessageList.dom.test.tsx # packages/web-shell/client/components/messages/ToolGroup.tsx
…hinking' into worktree-fix-web-shell-compact-thinking
doudouOUC
left a comment
There was a problem hiding this comment.
Reviewed PR #9657 — feat(web-shell): compact agent activity summaries.
What this PR does
Compact mode now folds adjacent thinking, tool activity, and parallel agents into one activity summary. Expanding the summary shows parallel agents as a nested progress row. Todo updates now join adjacent tool calls instead of forcing separate tool groups. CompactModeContext propagates to subagent transcripts in the artifact panel.
Previous rounds
Round 1 (chiga0): DISMISSED — no blockers.
Round 2 (chiga0): DISMISSED — no new blockers.
Round 2 (CI bot): COMMENTED — no blockers, 5 deferred suggestions.
Round 3 (CI bot): COMMENTED — no blockers, 2 deferred suggestions (CI: Dependency CVE audit).
Round 2 Criticals — both fixed
- Compact summary + single agent + thought: Verified fixed in 00a009c — opensSubagentDetails and opensMonitorDetails now guard on !compactSummary, and the outer summary button expands first before opening the subagent/monitor panel. Regression test added.
- todoDetailSignature cache key: Verified fixed in 00a009c — removed the !isTodoWriteToolName exclusion from the span loop, so TodoWrite tool times are now hashed. Regression test added.
Round 4 findings
No new Criticals or Suggestions. The 5 deferred suggestions from round 2 and 2 from round 3 remain standing under the convergence posture.
Verified
- Two Criticals from round 1 confirmed fixed by reading the code and tests at HEAD 57ceecf
- No head drift — live SHA matches the fetched commit
- ToolGroup.tsx: parallel agents grouping logic, compact summary rendering, thought line refactor — all correct
- todos.ts: todoDetailSignature and computeTodoDetails now handle per-tool timestamps correctly
- transcriptToMessages.ts: TodoWrite now merges like any other tool — correct
- CSS: focus-visible outline on the new thinking-summary button — correct
— reviewed inline
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/components/MessageList.tsx:371 — [probe] lone streaming thought loses the O(1) streaming-tail fast pathpackages/web-shell/client/components/messages/ToolGroup.tsx:1830 — [probe] thoughts bound to grouped (non-first) parallel agents render path untestedpackages/web-shell/client/components/MessageList.dom.test.tsx:548 — [probe] streaming-summary fast-path rerender coverage removedpackages/web-shell/client/components/MessageList.tsx:339 — [probe] pending AskUserQuestion group can merge into a folded compact summarypackages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx:229 — [probe] App.tsx CompactModeContext provider wrappers have no test coverage
中文说明
已审查——无阻断问题。 建议见行内评论。
收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.21.15)
| <button | ||
| type="button" | ||
| className={styles.chatSummaryThoughtSummary} |
There was a problem hiding this comment.
[Suggestion] The thought header row still advertises itself as fully clickable, but the toggle now lives only on this content-width inner button. The refactor replaced the row-wide role="button" div with a native <button> (flex: 0 1 auto, no grow), while .chatSummaryThoughtHeader keeps cursor: pointer and the :hover primary color across the whole row, and the chevron still reveals on the header hover — the chevron span and the expanded-content clip are siblings outside the button, so nothing outside it catches the click. Hovering the space to the right of the "Done thinking" label (including the chevron) shows a pointer cursor and switches the row to the primary hover color, but clicking there does nothing, where before this change the whole row toggled — a user aiming at the chevron to expand the thought gets no response despite the clickable affordance. Give the button the remaining row width (flex: 1 1 auto on .chatSummaryThoughtSummary, with the chevron/translate button after it) or move the chevron inside it; if the narrow target is intentional instead, drop cursor: pointer from .chatSummaryThoughtHeader and scope the hover color to .chatSummaryThoughtSummary:hover so the row stops promising a click.
中文说明
思考(thought)行的头部仍然表现得整行可点击,但开关实际只存在于这个内容宽度的内层按钮上。本次重构把整行的 role="button" div 换成了原生 <button>(flex: 0 1 auto,不伸展),而 .chatSummaryThoughtHeader 仍保留整行的 cursor: pointer 与 :hover 主色,chevron 也仍随整行 hover 显示——chevron span 与展开内容裁剪区都在按钮外部(兄弟节点),因此按钮之外的点击没有任何元素承接。悬停在 "Done thinking" 标签右侧区域(含 chevron)会显示指针光标并把整行变为主色,但点击没有反应;改动之前整行都可以切换展开——用户对着 chevron 点击展开思考时,尽管有可点击的视觉提示,却得不到任何响应。建议让按钮占据整行剩余宽度(.chatSummaryThoughtSummary 设为 flex: 1 1 auto,chevron/翻译按钮排在其后),或把 chevron 移入按钮内;如果窄点击区是有意为之,则去掉 .chatSummaryThoughtHeader 的 cursor: pointer,并把 hover 主色限定到 .chatSummaryThoughtSummary:hover,让整行不再暗示可点击。
— qwen3.8-max via Qwen Code /review (v0.21.15)
There was a problem hiding this comment.
Independent real-Chromium verification confirms this non-blocking UX issue at exact head 57ceecfdd5a6433744f7d97d02f6a1ffb1c86924. The completed-thinking header was more than 20 px wider than the actual button; clicking 4 px from the header's right edge in the pointer-styled/chevron area left aria-expanded=false, while clicking the label expanded it. The compact-agent behavior itself passed the production browser scenario. Please let the button fill the remaining row (for example flex: 1 1 auto), move the chevron inside it, or scope pointer/hover affordance to the real button hit target.
中文独立复验
真实 Chromium 独立验证确认这个非阻断 UX 问题。完成后的 Thinking Header 比实际按钮宽 20px 以上;点击 Header 右边缘内侧 4px 的 pointer/箭头区域后 aria-expanded 仍为 false,只有点击标签按钮才会展开。Compact Agent 核心行为本身已通过生产浏览器场景。建议让按钮填满剩余行(例如 flex: 1 1 auto)、把箭头移入按钮,或仅在真实按钮点击区域展示 pointer/hover 反馈。
|
@qwen-code /verify |
|
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: 58 passed · 0 failed · 58 total Flakiness gate: ✅ 7 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:58 通过 · 0 失败 · 58 总计 抖动门:✅ 7 changed test file(s) x 5 identical rounds, no divergence Verification reportSandboxed verification: ✅ passed — merge-ready (agent verdict) Scripted assertions: 58 passed · 0 failed · 58 total. Verified head: 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:58 通过 · 0 失败 · 58 总计。验证头:
Verification reportPR 9657 — feat(web-shell): compact agent activity summaries (follow-up round 2)Verdict: 中文摘要
Previous-finding status (follow-up round)The previous round verified head
Delta since the previous round (commits
|
| Cell | Scenario (compact unless noted) | base (control, #9672) | head | Flip |
|---|---|---|---|---|
| A1 | [user, agent, agent, thinking, asst] |
direct Parallel row + standalone thought | one summary-agent-1 folding both agents + thought |
✅ central |
| A2 | agent-only run | direct Parallel row | direct Parallel row, no summary | control |
| A3 | lone completed thinking | standalone | standalone | control |
| A4 | lone tool group | folded summary-g1 |
standalone row | ✅ |
| A5 | lone streaming thinking | summary-t1 |
in-place msg-t1 |
✅ |
| A6 | Read + TodoWrite adjacent | summary-g1 [g1] + standalone todo |
merged summary-g1 [g1, todo] |
✅ |
| A7 | non-compact A1 scenario | parallel row + separate thought | same | control |
| D1 | background agents + launch narration | direct background Parallel row (narration absorbed, hidden) | one summary folding both agents + narration (thought visible inside) | ✅ |
| D3 | single agent amid two tools | summary-g1 + msg-agent-1 + summary-g2 |
one summary [g1, agent, g2], no nested row | ✅ |
| D4 | active AskUserQuestion beside thinking | both standalone | folded into summary-t1 |
✅ |
| D6 | TodoWrite across completed thinking | summary-g1 + standalone special |
merged summary-g1 [g1, special] |
✅ |
| D6b | AskUserQuestion across completed thinking | summary-g1 + standalone special |
merged summary-g1 [g1, special] |
✅ |
| E3 | approving agent beside folded summary | both agents inside direct parallel row | folded summary keeps agent-1; approving agent standalone | ✅ |
| B1 | two agents + thought, real ToolGroup, expand twice | Called 2 other tools, two individual Agent (Explore) rows |
Ran 2 agents → Parallel agents · 2/2 done → 2 [data-agent-status] |
✅ central |
| B2 | two agents without compactSummary | no nesting | no nesting | control |
| B4 | formatToolGroupSummary agent counting |
flag ignored: Read 1 files Called 2 other tools |
Ran 2 agents · Ran 1 tool |
✅ |
| E1 | single agent + thought, subagent-details provider, click | opens details (onOpen called) |
expands summary; thought opens on second click | ✅ |
| E2 | single monitor + thought, monitor-details provider, click | opens details | expands summary | ✅ |
| D5 | thought bound to grouped non-first agent | visible after expand (role="button" header) | visible beside nested row | control |
| C1 | adapter [read, todo, read] |
3 groups | 1 group [tc1, todo-call-1, tc2] | ✅ |
| C2 | merged-group todo timing | startTs=endTs=50, no tool-time window |
startTs=1100, endTs=2000, toolTimeMs=500 |
✅ |
| C3 | todoDetailSignature vs todo endTime |
unchanged | changes | ✅ |
Methodology note on the control arm: the base worktree reused the root node_modules (the PR leaves package.json/package-lock.json untouched — git diff HEAD^1..HEAD --stat -- '*.json' is empty) plus a symlink of web-shell's nested third-party node_modules. The only @qwen-code/* imports in the harness graph are import type (erased at runtime), and the packages they name are unchanged by the PR, so no changed code crossed the workspace boundary in the control arm; realpath checks confirmed the links resolve into head-tree packages absent from the diff.
Mutation matrix (new head)
Baseline before mutating: the seven changed suites green, 450/450. Every revert produced a behavioral expected-vs-actual failure naming the intended test. Witness: 03-mutation-matrix.png (top two rows also in logs/mutation-matrix.log).
| Mutant | Suite | Result | Killing test / classification |
|---|---|---|---|
M1 drop summary- guards |
MessageList.dom (136) | killed | keeps a folded single-agent summary separate from an approving agent — finding 2 fix holds at this head |
| M2 drop agent-only-run exception | MessageList.dom | killed | keeps a parallel-agent-only run on its direct path |
| M3 drop lone-item exception | MessageList.dom | killed | merges tool groups separated by completed thinking |
| M4 disable consecutive-agent nesting | ToolGroup.test (75) | killed | nests parallel-agent details behind the compact summary |
| M5 disable agent-aware summary | ToolGroup.test | killed | same nesting test (Ran 2 agents assertion) |
| M6 adapter: TodoWrite standalone again | transcriptToMessages.test (135) | killed ×2 | both renamed merge tests |
M7 drop !compactSummary (subagent) |
ToolGroup.test | killed | expands a single-agent compact summary before opening agent details |
M8 drop !compactSummary (monitor) |
ToolGroup.test | killed | expands a single-monitor compact summary before opening monitor details |
| M9 drop App.tsx ArtifactPanel providers | SubagentDetail.integration + MessageItem.dom (13) | survived (13/13 green) | coverage gap — finding 1, stands |
M10 compactSummary={false} in MessageItem |
MessageItem.dom (11) | killed | marks only synthetic groups as compact summaries |
Same-file positive controls: M2/M3 kill inside the suite whose M1/M2/M3 siblings they share; M10 kills inside the suite M9 leaves green.
Intermediate build (commit-2 separation)
Reverting utils/todos.ts to its HEAD^1 version at the head tree. Witness: 04-intermediate-todo-timing.png.
| build | merged-group todo timing | suites |
|---|---|---|
| base | n/a (groups never merged) | green |
intermediate (base todos.ts at head) |
collapses to group timestamp; empty tool-time window | red ×3: pre-existing derives task detail from todo_write transcript snapshots + uses todo tool timestamps inside a merged tool group + changes when a todo tool end time arrives |
| head (both commits) | per-tool boundaries | green |
The timing fix remains load-bearing, pinned by three tests.
Findings (non-blocking)
- The App-level compact-mode wiring for the artifact panel is still unpinned by any test (carried over, re-measured as M9). The wiring is correct at this head; deleting all four provider lines changes no test outcome, so a future regression would make subagent transcripts in the artifact panel silently render non-compact. Suggested shape of a pin (unchanged from the previous round, advisory only): render through
App's panel slot or assert against the realCompactModeContextexport rather than a test-provided one. Completeness reporting, not a merge condition. - Behavior changes not named in the description (carried over, re-measured on both arms): background agents with launch narration fold into the compact summary instead of the direct background row (D1 — on base the narration is absorbed and hidden by the direct row; on head it survives as a folded thought inside the summary); an active AskUserQuestion folds into the summary (D4); the approving agent is kept out of any parallel grouping (E3). All three are design-consistent and two are pinned by the PR's own tests.
- Investigated and re-disproved — thinking-row focus indicator (carried over):
outline: noneon the native button matches the pre-existing.chatSummary:focus-visiblehouse pattern; the chevron-on-focus cue survives via the~sibling selector. Not a regression.
Not covered
- Pixel-level visual verification of the nested rows (no browser in this container); Playwright e2e/visual suites not run. The PR declares the same gap for Linux/Windows.
- Per-commit attribution: the checkout is depth-2 and shallow;
97d1628and57ceecfare not individually reachable, so the conflict-resolution audit above is aggregate-diff based (deletion inventory + byte-comparison ofgroupParallelAgents+ full-suite green), not per-commit exercise. - Full base suite not re-run (the harness measured base behavior directly; the head suite is green 4089/4089, so no pre-existing-failure attribution was needed).
- The flakiness gate is owned by the workflow (
steps.flake), not re-run here. - The matrix capture (
03-mutation-matrix.png) trims its top two rows at--rows 20; the complete matrix is inlogs/mutation-matrix.log.
Methodology
Environment: node:22-bookworm CI container, merge-ref checkout (HEAD=cce9c5f, base 6bbb273, verified head 57ceecf). Harnesses are vitest+jsdom test files kept in harness/ and copied into client/__verify__/ of each tree at run time (removed afterwards; git status --porcelain verified clean after every mutation restore and at the end). The base worktree reused the root node_modules plus a symlink of web-shell's nested third-party node_modules; the harness graph's only cross-workspace imports are import type, so the control arm never loaded changed code. Mutations applied by harness/mutant-driver.mjs (exact-count string replacement, fail-loud, restore verified) or git checkout HEAD^1 -- utils/todos.ts. Gates at head: full packages/web-shell suite 4089/4089 (195 files), tsc -p tsconfig.json --noEmit clean with a planted TS2322 proving the gate live. Evidence captures via scripts/verify-capture.mjs. Raw logs in logs/ (head/base arm logs, mutation matrix, full suite), harness sources in harness/.
Flakiness gate log
rounds=5 files=7 skipped=0
file packages/web-shell/client/adapters/transcriptToMessages.test.ts: (cd packages/web-shell) npx --no-install vitest run ./client/adapters/transcriptToMessages.test.ts
file packages/web-shell/client/components/MessageItem.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/MessageItem.dom.test.tsx
file packages/web-shell/client/components/MessageList.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/MessageList.dom.test.tsx
file packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/WebShellTranscript.dom.test.tsx
file packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/artifacts/SubagentDetail.integration.test.tsx
file packages/web-shell/client/components/messages/ToolGroup.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/messages/ToolGroup.test.tsx
file packages/web-shell/client/utils/todos.test.ts: (cd packages/web-shell) npx --no-install vitest run ./client/utils/todos.test.ts
per-file results (P=pass F=fail I=infra-exit, one letter per run):
packages/web-shell/client/adapters/transcriptToMessages.test.ts: PPPPP
packages/web-shell/client/components/MessageItem.dom.test.tsx: PPPPP
packages/web-shell/client/components/MessageList.dom.test.tsx: PPPPP
packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: PPPPP
packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: PPPPP
packages/web-shell/client/components/messages/ToolGroup.test.tsx: PPPPP
packages/web-shell/client/utils/todos.test.ts: PPPPP
verdict: pass
summary: 7 changed test file(s) x 5 identical rounds, no divergence
--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 1 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 2 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 2 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 3 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 3 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 4 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 4 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
round 5 · packages/web-shell/client/adapters/transcriptToMessages.test.ts: P (exit 0)
round 5 · packages/web-shell/client/components/MessageItem.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/MessageList.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/WebShellTranscript.dom.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/artifacts/SubagentDetail.integration.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/messages/ToolGroup.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/utils/todos.test.ts: P (exit 0)
Evidence images
Harness scripts and raw logs are in the workflow run artifacts (7-day retention).
— Qwen Code · sandboxed verification
|
@qwen-code /resolve |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
…l-compact-thinking # Conflicts: # packages/web-shell/client/components/MessageList.tsx
|
🤖 Addressed the latest review feedback (round 9/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 9/100 轮)。改动内容与我反驳保留之处如下: Autofix round summary — PR #9657Feedback triageThis round carried no actionable feedback: the Reviews, Inline comments, ChangesMerged
Audit of the auto-merge (all other files merged textually clean):
No feedback findings were implemented, declined, deferred, or escalated this Verification
Integration tests were not run: the touched behavior is covered by the 中文说明Autofix 轮次总结 — PR #9657反馈分类本轮没有可处理的反馈:Reviews、Inline comments、Issue-level comments、 改动将
自动合并的审查(其余所有文件均无文本冲突):
本轮没有实施、拒绝、延后或升级任何反馈发现,因此省略 验证
未运行集成测试:被改动的行为由该包的 unit/dom/integration 风格 Vitest 套件 🧭 Gate advisory — this round modified areas outside the PR footprint (machine-measured, not agent-authored):
Deferred non-Critical feedbackCritical-only mode is active: the round counter reached 5 (this window was seeded at round 5 by 中文说明已进入仅处理 Critical 的模式:轮次计数已达 5(本窗口由 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/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: reverse audit — stopped at the 5-round cap without convergence: chunk 2 reported D8-4 in round 4 and its dry round-5 re-audit holds no paired certificate; chunk 3 receipts failed certification in rounds 2-4.
Deferred under the convergence posture (round 8, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/App.tsx:13341 — [probe] CompactModeContext providers around ArtifactPanel mounts have no App-side testpackages/web-shell/client/components/MessageList.dom.test.tsx:548 — [probe] updateCompactStreamingThinkingTail success path no longer exercised by any testpackages/web-shell/client/components/MessageList.tsx:373 — [probe] lone streaming thought loses the O(1) streaming-tail fast path (per-delta full remerge)packages/web-shell/client/components/MessageList.tsx:372 — [probe] background-agent launch narration runs lose the live Parallel agents box in compact mode
中文说明
未审查:reverse audit — stopped at the 5-round cap without convergence: chunk 2 reported D8-4 in round 4 and its dry round-5 re-audit holds no paired certificate; chunk 3 receipts failed certification in rounds 2-4。
收敛姿态下延后(第 8 轮,非阻断)——已记录,本轮不要求修改:共 4 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.
Deferred under the convergence posture (round 9, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/App.tsx:13355 — [probe] CompactModeContext providers around ArtifactPanel mounts have no App-side testpackages/web-shell/client/components/messages/ToolGroup.tsx:1719 — [probe] parallel-agent grouping loop has no mixed agent/tool-array testpackages/web-shell/client/components/MessageList.dom.test.tsx:548 — [probe] folded-summary thoughts payload has no MessageList-level test
中文说明
未审查:反向审计——在 5 轮的反审轮数上限内未收敛。
收敛姿态下延后(第 9 轮,非阻断)——已记录,本轮不要求修改:共 3 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
🤖 Could not produce a passing fix for this feedback (round 10/100). This item now needs a human; the loop stays engaged and still picks up new feedback and base conflicts, but will not retry this item on its own. What I found before stopping: Red
|
|
🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run. 中文说明🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.
Deferred under the convergence posture (round 10, not a blocker) — recorded, not requested in this round:
packages/web-shell/client/App.tsx:13355 — [probe] CompactModeContext providers around the ArtifactPanel mounts have no App-side testscripts/tests/cua-driver-release-workflow.test.js:52 — [test] Unrelated formatting-only reflow of an out-of-workspace script test rides in a web-shell feature PR
中文说明
仅完成部分审查,审查缺口已披露。
未审查:反向审计——在 5 轮的反审轮数上限内未收敛。
收敛姿态下延后(第 10 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.0)
|
@qwen-code /takeover stop |
|
👋 Takeover released: the autofix loop will no longer engage this PR (an in-flight round, if any, completes its bounded work). Re-apply 中文说明👋 已释放:autofix 循环不再介入此 PR(在飞的一轮如有,将完成其有界工作)。重新打上 |
|
@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: 144 passed · 0 failed · 144 total Flakiness gate: ✅ 8 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:144 通过 · 0 失败 · 144 总计 抖动门:✅ 8 changed test file(s) x 5 identical rounds, no divergence Verification reportPR 9657 — feat(web-shell): compact agent activity summaries (follow-up round 3)Verdict: 中文摘要
Previous-finding status (follow-up round)The previous round verified head
Central claim + A/BCentral claim: in compact mode, adjacent thinking, tool activity, and parallel agents fold into one activity summary; first expansion shows a nested The identical harness files (
Two base expectations were re-derived by measurement rather than carried from round 2 (the base moved): D6/D6b — the current base already folds a completed thought into the preceding summary, so the flip is the tool joining the group, not the thought's placement; T2 — the translate trigger Delta audit (commits since the previous round)
Mutation matrix (new head)Baseline before mutating: the five pinned suites green (MessageList.dom 136, ToolGroup 82, transcriptToMessages 135, MessageItem.dom 11, SubagentDetail.integration + MessageItem.dom 13). Every revert produced a behavioral expected-vs-actual failure naming the intended test (messages quoted in
Same-file positive controls: M11/M12 kill inside the very suite whose M4/M5/M7/M8 siblings they share, and M10 kills inside MessageItem.dom, which M9 leaves green — the runner demonstrably collects the mutated files. 12/12 rows as expected. Intermediate build (todo-timing separation)Reverting
Identical to the previous round: the timing fix remains load-bearing, pinned by three tests (one pre-existing, two from this PR). Findings
Not covered
MethodologyEnvironment: Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
chiga0
left a comment
There was a problem hiding this comment.
Re-review of new commits since my last review at 9dde892b (round 2).
New commits reviewed:
00a009ccfix: address compact summary reviewe7115034test: cover compact review edge casesf23a3b8afix: make folded thought header row fully clickable2b4e7d0dfix: guard folded thought toggle against popover clicks6e6ebfd2test: cover thinking header hit area and parallel-agent thoughts8f1ce19e/8cee640b/eb445503merges from main (no functional delta in web-shell)
Prior critical findings — all resolved at current head
Critical 1 (MessageList.tsx) — single-agent + thought → thought unreachable.
Fixed in 00a009cc / 2b4e7d0d. The opensSubagentDetails / opensMonitorDetails derivations now gate on !compactSummary, so a compact summary with a folded thought plus a single agent/monitor tool expands the summary row instead of jumping straight to the panel. Confirmed in the diff at ToolGroup.tsx and in the new test 'expands a single-agent compact summary before opening agent details'.
Critical 2 (todos.ts) — todoDetailSignature stale cache.
Fixed in 9dde892b (already covered in round 2): the !isTodoWriteToolName exclusion is removed from the span loop, and the snapshot entry now hashes tool.endTime ?? tool.startTime ?? message.timestamp instead of the group-level message.timestamp. New test 'changes when a todo tool end time arrives' pins the span-loop path; 'uses todo tool timestamps inside a merged tool group' pins the per-snapshot path.
Critical 3 (ToolGroup.tsx) — unguarded onClick on the folded-thought header row.
Fixed in 2b4e7d0d. The ThoughtLineHeader div carries onClick={(e) => { if (e.currentTarget.contains(e.target as Node)) onToggle(); }}. For clicks on DOM children the check is always true (toggle fires), but for Radix PopoverContent rendered through a portal, e.target sits outside the div's DOM subtree so contains returns false and the toggle does not fire. New test 'does not toggle the folded thought on clicks inside the translation popover' verifies both the translation-content case and the retranslate button case.
What I checked in this round
Static:
opensSubagentDetails/opensMonitorDetailsgating: both derive!compactSummary && ...;onClickblock updated to use the derived bool rather than re-checkingsingleSubagent && subagentDetailsraw.ThoughtLineHeaderrefactor: outer div handles all DOM-child clicks viacontains; inner native<button>carriesaria-expandedand activates keyboard toggle via synthetic click → bubble. The outer div has noroleortabIndex(correct — focus stays on the native element).todoDetailSignaturespan loop:!isTodoWriteToolNameguard removed; hashes all tool spans including TodoWrite. Snapshot timestamp usestool.endTime ?? tool.startTime ?? message.timestamp— changes when a todo tool'sendTimearrives.- Merge commits from main: confirmed no web-shell source changes.
CI at this head:
Test (ubuntu-latest, Node 22.x)✅ (27 min)web-shell E2E Smoke✅ ·Capture web-shell visuals✅ ·Desktop Shell (win/ubuntu)✅Test (macos, windows)SKIP — fork PR security restriction, expected, no platform-specific logic in this diff.Dependency CVE audit✅ ·Secret scan✅
Not covered (exclusions):
- Platform-specific rendering on macOS/Windows (no host; unit tests skip for fork PRs).
- Pixel-level visual diff (out of scope per PR's own risk statement).
Open suggestions (not blocking — deferred per round-escalating floor)
From prior review rounds, still open but minor:
- No integration test pins the full wiring chain MessageItem→ToolGroup
compactSummarywith real components (mutatingcompactSummary={false}survives the suite). summary-exclusion inisAgentOnlyToolGroup/isBackgroundAgentOnlyToolGroupnot exercised by any assertion.- Ordering-contract comment ("the group renders in the original order") is technically stale for thoughts bound to non-first agents in a parallel-agent run, which intentionally appear after the
ParallelAgentsGroupbox.
Reviewed with AI assistance.
Dismissing per maintainer instruction: the blocking Critical (translation Popover click bubbling into the thought-row onClick, ToolGroup.tsx) is fixed at the latest head 6e6ebfd — the currentTarget.contains(event.target) guard is in place, exactly the suggested remediation.
Local verification report — real Chromium, PR head vs merge-baseVerified as a maintainer on a local build. Head Instead of relying on the jsdom suites alone ( Verdict: the behaviour in the description is real and works. One trade-off is worth an explicit decision before merge (see §3); everything else is nits.
1. Compact mode folds thinking + parallel agents + tools into one summary ✅Confirmed in the browser, all on the real components:
Guard rails held (all verified in-browser, screenshot below): an agent-only run keeps the direct parallel-agent row with no summary wrapper; consecutive thinking with no tools stays standalone; non-compact mode is unchanged. I also probed three shapes the description does not mention — all render sanely with no console/page errors:
2. TodoWrite now merges with adjacent tools ✅One group; expanding it yields both the tool row and the Todo checklist ( Also checked the obvious hazard: a live 3.
|
| 检查项 | 结果 |
|---|---|
| PR 头的真实浏览器断言 | 36 / 36 通过 |
| merge-base 臂(源码回退,harness 不变) | 18 / 30 通过 —— 12 条失败恰好是本 PR 新增的行为 |
| 7 个改动测试文件 @ PR 头 | 457 / 457 通过 |
| 回退 8 个源文件、保留 PR 的测试 | 24 条失败 → 测试确实编码了新行为,不是同义反复 |
@qwen-code/web-shell 全量套件 |
4205 / 4206(唯一 1 条失败是我本地 packages/webui/dist 过期,与本 PR 无关,见 §5) |
tsc --noEmit,PR vs merge-base |
两臂错误集完全一致(91 行),comm -3 为空 → 未引入新类型错误 |
eslint packages/web-shell |
干净 |
prettier --check |
5 条既有告警,没有一条在本 PR 改动的文件里 |
1. 紧凑模式把思考 + 并行智能体 + 工具折叠为一条摘要 ✅
浏览器里在真实组件上确认:
- 折叠行显示
Ran 2 agents · Ran 1 tool(中文已运行 2 个智能体 · 调用了 1 个工具) - 第一次展开 → 折叠思考行 + 嵌套的
并行智能体 · 2/2 完成+ 同级工具行;此时单个智能体尚未进入 DOM - 第二次展开 → 原有的单个智能体详情,未改变
- 折叠思考可展开出内容;整行都是点击热区(点在标签右侧 40px 处同样生效);聚焦摘要按钮后按
Enter也能切换
护栏均成立:仅含并行智能体的运行保持直接展示、无摘要外壳;无工具的连续思考保持独立行;非紧凑模式完全未变。
另外补测了描述未提及的三种形态,全部渲染正常、无任何控制台/页面错误:绑定到后一个智能体的思考会渲染在聚合行下方(与代码注释一致);单个智能体 + 思考 + 工具会显示 Ran 1 agent · Ran 1 tool、不产生嵌套行;非连续智能体(agent, tool, agent)表头计数为 2 但不聚合,各自保留独立行。
2. TodoWrite 与相邻工具合并 ✅
合并为一个组;展开后同时包含工具行与 Todo 清单(● / ◐ / ○,已完成项带删除线 —— 这是真实 CSS,jsdom 看不到)。
同时排查了最明显的风险:进行中的 AskUserQuestion 不会被埋掉,因为它以 pendingApproval 形式到达,isForceExpandGroup 会把它排除在合并之外,只有已完成的才会折叠。
3. ⚠️ 唯一需要拍板的点:运行中的并行智能体进度多了 2 次点击
场景:两个前台智能体处于 in_progress,且相邻有一条已完成思考 —— 这是非常常见的实时状态(模型先思考,再并行展开)。
- merge-base:智能体组保持独立,
ParallelAgentsGroup在顶层渲染并带autoManageExpansion,运行期间自动展开 → 0 次点击即可看到每个智能体的实时行。 - 本 PR:该运行被合并,面板变为嵌套。嵌套的
ParallelAgentsGroup只传了agents+pendingApproval,没有autoManageExpansion/expandActiveWhenLive;外层摘要在有前台工具运行时也不会自动展开。于是运行期间要看到单个智能体进度需要 2 次点击。
客观地说:标题层面并没有丢信息 —— 折叠行显示 Running 2 tools: Agent Map the auth middleware call graph · Agent Inventory session-store call sites,两个运行中的智能体仍被点名,且该行有动效。所以这是紧凑模式下有意的取舍,不是 bug。
如果希望紧凑模式下实时进度仍是 0 次点击,有两个低成本方案:把 autoManageExpansion / expandActiveWhenLive 透传给嵌套的 ParallelAgentsGroup;或在 hasRunningTool && hasForegroundActiveTool(即已经算好的 animateSummary)时自动展开紧凑摘要。无论选哪种,建议在 PR 描述里补一句 —— 紧凑模式虽然是可选项,但这恰恰是用户盯得最多的状态。
4. 附带收获:本 PR 修掉了 main 上一个真实存在的 bug ✅
ThoughtLineHeader 的重写不只是外观改动。merge-base 上表头挂的是裸 onClick={onToggle};中文翻译弹层是 Radix portal,DOM 上在表头之外、但 React 树上仍在其内部,React 会沿 React 树重新派发点击,于是折叠思考会在弹层背后被展开。
在两臂上用同一脚本、在 main 今天就存在的摘要形态(工具 → 思考 → 工具,紧凑模式,中文)复现:
[base] 点击 portal 弹层内部后,思考被展开? true <-- bug
[pr] 点击 portal 弹层内部后,思考被展开? false <-- 已修复
event.currentTarget.contains(event.target) 这个守卫形状正好对症:对真实子节点恒为真,对 portal 内容为假。点击触发按钮本身另有 stopPropagation 覆盖,两条路径都已验证。
5. 看起来红、但不是本 PR 的问题
- web-shell visuals 机器人的
⚠️ No preview与本 PR 无关。在同一次运行(32674055155)中,base 臂失败的是完全相同的两个场景:screenshots.spec.ts:786 › workspace sidebar(dark 与 light),报strict mode violation: getByRole('complementary').getByText('Run auth migration') resolved to 2 elements。头臂2 failed / 35 passed,base 臂2 failed / 30 passed。这是既有的重名会话定位问题,值得单独开 issue。 - 我本地全量跑出的那条红(
constants/sessions.test.ts,DAEMON_SESSION_DEFAULT_MAX_BLOCKS为undefined)是我工作树里packages/webui/dist过期所致(该导出在 fix(web-shell): bound daemon transcript retention to stop renderer OOM crashes #9303 落地,我的 dist 早于它)。上游Test (ubuntu-latest, Node 22.x)是绿的。
6. Nit(不阻塞)
- 新增的
SubagentDetail.integration.test.tsx用例并没有测到它命名的那个改动。 它vi.mock了../../App并自带一个CompactModeContext,因此在 merge-base 上原样通过 —— 我回退源码后单独跑过,是绿的。它作为SubagentDetail的护栏有价值,但真正的改动(在App.tsx两处渲染点用CompactModeContext.Provider包住ArtifactPanel)没有任何覆盖。我改为静态核对了链路:两处新 Provider 都位于既有 Provider(App.tsx:12514/12610)之外,且MessageList.tsx:2780/MessageItem.tsx:77会读取该 context —— 接线是对的,只是没有测试兜底。 - 摘要行的分隔符不一致。 新的智能体分支用
' · '拼接,既有的种类分支用' '拼接,于是 todo 合并后会出现Read 1 file Updated task list(无分隔符)与Ran 2 agents · Ran 1 tool并存。空格拼接是既有实现,但 TodoWrite 进入这条路径是新的 —— 在 §2 的截图里可见。 scripts/tests/cua-driver-release-workflow.test.js是无关的格式化漂移。已验证:PR 里的内容与prettier(base 内容)逐字节一致。无害,只是超出了本 PR 的范围。- 一处轻微 CSS 回退:表头的
:focus-within规则被改为.chatSummaryThoughtSummary:focus-visible ~ …,因此聚焦翻译按钮时不再显出箭头,:focus-visible也不再通过继承给箭头/标签着色。纯外观问题。
仅作为审阅者的参考证据,不构成 approve。
|
Released in v0.22.2. |
























What this PR does
Compact mode now folds adjacent thinking, tool activity, and parallel agents into one activity summary. Expanding the summary shows parallel agents as a nested progress row, and expanding that row reveals the existing per-agent details. Agent-only runs keep their direct parallel-agent presentation, while lone thoughts and tools remain standalone. Todo updates now join adjacent tool calls instead of forcing separate tool groups.
The same compact-mode behavior is propagated to subagent transcripts opened in the artifact panel. The nested rows reuse the spacing, translation placement, running-state priority, and interaction patterns of existing tool and thinking rows.
Why it's needed
Compact conversations could still show parallel-agent progress and completed thinking as separate top-level rows, producing unnecessary visual noise and an inconsistent expansion hierarchy. The new presentation keeps the collapsed timeline concise while preserving all progress and detail on demand.
Reviewer Test Plan
How to verify
Enable compact mode and run two parallel agents with adjacent thinking or another tool. Confirm that the collapsed row reports agent and tool counts, the first expansion shows a
Parallel agents · x/x donerow plus the other activity, and the second expansion shows the individual agents. Confirm that a run containing only parallel agents still uses the direct parallel-agent row, consecutive thinking without tools stays standalone, and non-compact mode keeps agents and thinking separate. Run a normal tool adjacent to a TodoWrite update and confirm they share one group whose expansion contains both tool rows and the Todo checklist.Evidence (Before & After)
Before: compact mode displayed parallel-agent completion and completed thinking as separate top-level rows. After: they share one compact summary with nested parallel-agent progress and unchanged per-agent details.
Tested on
Environment (optional)
Web Shell unit and DOM tests, TypeScript typecheck, and production/library builds.
Risk & Scope
Linked Issues
N/A
中文说明
本 PR 的改动
紧凑模式现在会将相邻的思考、工具活动和并行智能体折叠到一条活动摘要中。展开摘要后,并行智能体会作为嵌套的进度行展示;再次展开该行后,会显示现有的单个智能体详情。仅包含智能体的运行仍保持直接的并行智能体展示,单独的思考和工具也仍独立展示。Todo 更新现在会与相邻工具调用合并,不再强制创建单独的工具组。
在产物面板中打开的子智能体转录也会获得相同的紧凑模式行为。嵌套行复用了现有工具和思考行的间距、翻译位置、运行状态优先级和交互模式。
为什么需要
紧凑对话中,并行智能体进度和已完成思考仍可能作为独立的顶层行展示,带来不必要的视觉噪声和不一致的展开层级。新展示在保持所有进度和详情可按需查看的同时,让折叠后的时间线更简洁。
审查者测试计划
验证方法
启用紧凑模式,运行两个并行智能体,并使其与思考或另一个工具相邻。确认折叠行报告智能体和工具数量,第一次展开显示“并行智能体 · x/x 完成”行及其他活动,第二次展开显示各个智能体。确认仅包含并行智能体的运行仍使用直接的并行智能体行,没有工具的连续思考仍独立展示,并且非紧凑模式仍将智能体和思考分开。运行一个与 TodoWrite 更新相邻的普通工具,确认它们共用一个工具组,展开后同时包含工具行和 Todo 清单。
证据(修改前后)
修改前:紧凑模式将并行智能体完成状态和已完成思考显示为独立的顶层行。修改后:它们共用一条紧凑摘要,其中包含嵌套的并行智能体进度,并保留原有的单个智能体详情。
测试平台
环境(可选)
Web Shell 单元和 DOM 测试、TypeScript 类型检查,以及生产和库构建。
风险与范围
关联问题
N/A