Skip to content

feat(web-shell): group scheduled task run sessions - #10611

Merged
qqqys merged 11 commits into
QwenLM:mainfrom
qqqys:feat/web-shell-scheduled-task-session-groups
Sep 2, 2026
Merged

feat(web-shell): group scheduled task run sessions#10611
qqqys merged 11 commits into
QwenLM:mainfrom
qqqys:feat/web-shell-scheduled-task-session-groups

Conversation

@qqqys

@qqqys qqqys commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Automatically groups Web Shell sessions created by repeated runs of the same scheduled task. The virtual group is keyed by the stable scheduled-task source identity, uses the scheduled task title as its label, and displays the scheduled-task clock icon instead of a color marker. Existing manual color and named groups keep precedence, and the same behavior applies to primary and secondary workspaces without requiring session-organization support.

Why it's needed

Per-run scheduled tasks create a fresh session each time. Those sessions currently accumulate as a flat list, making the sidebar noisy and making runs from the same automation harder to scan.

Reviewer Test Plan

How to verify

Open Web Shell with at least two sessions created by separate runs of the same scheduled task. Confirm that both sessions appear under one expanded group named after the scheduled task, that the group header uses the scheduled-task clock icon, and that an ordinary session remains under Ungrouped. Collapse and re-expand the automatic group to confirm the existing collapsed-section behavior still works.

Evidence (Before & After)

Before: every scheduled-task run appeared as a separate top-level session. After: runs sharing a scheduled-task identity appear under one task-title group. The rendered validation screenshot is attached in the first PR comment.

Tested on

Platform Tested
macOS
Windows
Linux

Environment (optional)

Node.js 22.17.0; Web Shell Vite development build; Chrome driven by Playwright with the repository mock daemon.

Risk & Scope

  • Main risk or tradeoff: The display label removes the generated · MM-DD HH:mm run suffix; if that daemon naming convention changes, grouping remains stable by task identity but the label may retain the new suffix.
  • Not validated / out of scope: Windows and Linux visual rendering; changing daemon persistence or existing manual session groups.
  • Breaking changes / migration notes: None.

Linked Issues

None.

中文说明

这个 PR 做了什么

自动归组 Web Shell 中由同一个定时任务多次运行创建的会话。虚拟分组使用稳定的定时任务来源标识,标题取定时任务标题,并用定时任务时钟图标替代颜色标记。已有的手动颜色分组和命名分组优先级更高;主工作区和次工作区都会生效,也不依赖会话组织能力。

为什么需要

按次运行的定时任务每次都会创建一个新会话。当前这些会话会平铺累积,侧边栏容易变得拥挤,也不方便快速查看同一个自动任务的多次运行。

Reviewer Test Plan

如何验证

在 Web Shell 中准备至少两个由同一个定时任务不同运行创建的会话。确认它们位于同一个默认展开的分组中,分组标题是定时任务标题,分组头使用定时任务时钟图标,普通会话仍位于“未分组”。折叠并重新展开自动分组,确认现有的折叠状态行为仍然正常。

证据(改动前后)

改动前:每次定时任务运行都作为顶层会话平铺。改动后:共享同一定时任务标识的运行会话位于同一个任务标题分组下。实际渲染的验证截图附在 PR 首条评论中。

测试平台

平台 已测试
macOS
Windows
Linux

环境(可选)

Node.js 22.17.0;Web Shell Vite 开发构建;Chrome 由 Playwright 驱动,并使用仓库内的 mock daemon。

风险与范围

  • 主要风险或取舍:展示标题会移除自动生成的 · MM-DD HH:mm 运行时间后缀;如果 daemon 的命名约定发生变化,仍会按任务标识稳定分组,但标题可能保留新的后缀。
  • 未验证 / 不在范围内:Windows 和 Linux 的视觉渲染;修改 daemon 持久化或已有手动会话分组。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

无。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

⚠️ Deferred approval withheld — 1 PR CI workflow run(s) on 8686830 did not finish green; see the updated table in the Stage 2 comment. Re-run @qwen-code /triage after fixes. finalize run

⚠️ 延迟审批已搁置 —— 8686830 有 1 个 PR CI workflow 未以绿色完成,详见 Stage 2 评论中已更新的表格。修复后可重新运行 @qwen-code /triage查看 finalize 运行

@qqqys

qqqys commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

E2E verification

Rendered the Web Shell against the repository mock daemon with two per-run sessions sharing the same scheduled-task identity and one ordinary session.

  • Both runs appear in one expanded group named after the scheduled task.
  • The group header and scheduled-run rows use the scheduled-task clock icon instead of a color marker.
  • The ordinary session remains under Ungrouped.
  • The screenshot uses the real Web Shell Vite build in Chrome at a 540 px sidebar width.
Web Shell scheduled-task session grouping verification

Additional verification:

  • Focused Web Shell unit tests: 155 passed across 4 files.
  • Web Shell TypeScript typecheck: passed.
  • Pre-commit Prettier and ESLint checks: passed.
  • Workspace build during dependency preparation: passed.
中文验证说明

使用仓库 mock daemon 构造了两个共享同一定时任务标识的按次运行会话,以及一个普通会话,并通过真实 Web Shell Vite 页面在 Chrome 中完成渲染验证。

  • 两次运行位于同一个默认展开、以定时任务标题命名的分组中。
  • 分组头和运行会话行都使用定时任务时钟图标,不显示颜色标记。
  • 普通会话仍位于“未分组”。
  • 额外验证包括 4 个文件共 155 个聚焦单测、Web Shell 类型检查、提交前 Prettier/ESLint 检查以及工作区构建,均已通过。

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Re-run at the current head — this PR went through five autofix rounds and a maintainer live validation since the first review, so restating the gate verdict for the diff as it stands now.

  • Template: looks good ✓
  • Problem: observed, not theoretical — per-run scheduled tasks create a fresh session each time, and those runs stack flat in the sidebar. Beyond the author's before/after account and rendered screenshot, a maintainer has since reproduced the whole flow end-to-end against a real qwen serve daemon, verifying every claim in the PR body.
  • Direction: aligned. Sidebar session organization and scheduled tasks are both active product areas, and grouping repeated runs of one automation is a natural extension of the existing manual groups.
  • Size: not applicable — no core paths; everything stays inside packages/web-shell/client/components/. For reference: 12 files, +747/−54 ≈ ~280 production lines (incl. 20 lines of CSS) + ~520 test lines.
  • Approach: scope still feels right. The growth since the first review is all review-driven: first-sync latch re-arms for session_organization landing mid-session (including via the Channels tab), a label-preference rule plus tests pinning its documented limit, deflake timeout bumps, and a one-line readOnly trust gate. That last one also fixes a pre-existing UX bug (untrusted secondary workspaces with a manual group rendered clickable session rows that 403'd) — maintainer-verified, and worth one sentence in "Risk & Scope", but a description-hygiene note rather than a blocker.
  • Risk: no elevated risk signals — none of the changed files match the revert-correlated high-risk paths.

Moving on to code review. 🔍

中文说明

在当前 head 上重跑——本 PR 自初审后经历了五轮 autofix 与维护者真机验证,此处按当前 diff 重述门禁结论。

  • 模板:完整 ✓
  • 问题:真实存在而非理论问题——按次运行的定时任务每次都会创建新会话,这些运行在侧边栏平铺累积。除作者的改动前后说明与渲染截图外,维护者已在真实 qwen serve daemon 上端到端复现整个流程,逐项验证了 PR 声明。
  • 方向:对齐。侧边栏会话组织与定时任务都是活跃产品方向,把同一自动任务的多次运行归组是现有手动分组的自然延伸。
  • 规模:不适用——未触及核心路径,全部改动都在 packages/web-shell/client/components/ 内。参考:12 个文件,+747/−54 ≈ 约 280 行生产代码(含 20 行 CSS)+ 约 520 行测试。
  • 方案:范围仍然合理。初审后的增量全部来自评审反馈:session_organization 中途到达(含经由 Channels 标签页)时的首同步 latch 重置、标题优先规则及钉住其文档化局限的测试、deflake 超时上调,以及一行 readOnly 信任门。最后一项顺带修复了一个既有 UX 缺陷(未受信任的次级工作区存在手动分组时会话行可点击但返回 403)——已经维护者实测确认,值得在 "Risk & Scope" 补一句,但属描述层面的卫生问题,不构成阻塞。
  • 风险:无升级风险信号——改动文件均未命中与回滚相关的高风险路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

My independent proposal is unchanged from the first review: key the group by the task id behind the scheduled_task_run: source-id prefix, derive the label by stripping the daemon-generated run-time suffix, render through the existing group-section component with an icon instead of the color dot, keep manual color/group precedence, and cover both the primary and the per-workspace render path. The PR does exactly that — I found no simpler path. The one structural alternative (the daemon carrying the task title alongside the session summary instead of the label being recovered from the display name) crosses the daemon/API surface and is correctly deferred, with the limit documented in the helper.

Things I verified against the code at this head:

  • The suffix regex and truncation behavior mirror the producer exactly (scheduledTaskRunSessionName in cli/src/runtime/scheduled-task-run.ts: zero-padded · MM-DD HH:mm, 60-char ceiling with a trailing ), and the helper's sourceType === 'default' guard matches SCHEDULED_TASK_RUN_SOURCE_TYPE.
  • Label preference is now pinned by tests: a generated-shape name outranks a rename regardless of collection order, and the documented shape-based limit (a rename ending in the same shape is treated as generated) has its own pinning test.
  • The two latch paths added since the first review each have a witness test reproducing the exact failing sequence: registers manual groups as initial when organization lands after a scheduled-task settle and … while the channel source is selected.
  • The readOnly guard in WorkspaceSection.groupedSessions keeps untrusted secondary workspaces on the flat, trust-gated branch even when a manual group exists — pinned by keeps scheduled-task runs read-only in an untrusted workspace. This is also the pre-existing UX fix the maintainer called out: at merge-base, an untrusted workspace with any manual group rendered clickable rows that fired a request and 403'd.
  • The three }, 15000) timeout bumps are deflake-only for ~0.9 s tests that crossed the default 5 s budget under loaded CI runners; the maintainer measured the affected suite at essentially identical runtime on merge-base vs head (3.52 s vs 3.55 s) and green locally with the bumps removed.
  • The ChatEditor.test.tsx hunk removes a duplicate language binding that upstream already fixed in fix(web-shell): remove duplicate language declaration in ChatEditor.test.tsx #10729 — harmless; it drops out on rebase.

Non-blocking, noted for follow-up:

  • WebShellSidebar bucketing order (color > manual group > scheduled) still has no test pinning it — the maintainer's mutants M7/M11 survive — a gap the approver accepted. A follow-up test with a colored run and a grouped run asserting they stay out of the auto group would close it.
  • The PR description's "Risk & Scope" still doesn't mention the trust-gate fix; one sentence is enough.

Testing evidence

The PR's own CI on the reviewed commit, fetched via API (I do not run PR code). The two red checks below are infrastructure, not this PR:

  • Test (ubuntu-latest, Node 22.x) was cancelled at the 120-minute ECS-runner cap on both attempts. Its log shows the main suite completed fully green before the kill — 981 files, 27,693 passed | 90 skipped, 0 failures — and the only red line logged is one timing-sensitive test in packages/core/src/hooks/hook-runner.process.test.ts, a package this diff does not touch.
  • web-shell E2E Smoke is marked failed on attempt 2, but the log ends with The runner has received a shutdown signal — and the same suite passed on attempt 1 of this exact head.
  • Main-branch CI shows a run of cancellations/failures on the same ECS fleet across the same window (recovering ~22:11 UTC), consistent with a runner-fleet outage rather than a regression here. The maintainer independently ran both suites green at this head and reached the same infrastructure conclusion in his validation comment.
  • No rerun was in flight, so I queued one for the two red jobs (attempt 3); the table below is updated by the finalize job once CI settles.

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

Check Conclusion
web-shell E2E Smoke (ubuntu-latest, Node 22.x) 🚫 cancelled
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success
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
Secret scan (TruffleHog) ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

Sandboxed verification is already in flight: this triage run carries a verify job (maintainer-triggered), and its A/B report will post in this thread. The claim it settles — that grouped sections materialize from a real daemon session catalog rather than a mocked client — is already shown by the maintainer's live validation; the run makes it reproducible. Windows/Linux rendering still rests on the visual capture and the author's word.

中文说明

代码评审:我的独立方案与初审一致——以 scheduled_task_run: 前缀后的任务 id 作分组键,去掉运行时间后缀得到标题,复用现有分组组件并以图标替代颜色点,保持手动分组优先,覆盖主目录与按工作区两条渲染路径。PR 与之一致,没有更简路径;唯一的结构性替代(daemon 随会话摘要直接携带任务标题)跨越 daemon/API 边界,已正确推迟并在 helper 中记录局限。

在该 head 上核实:后缀正则与截断行为与生产端 scheduledTaskRunSessionName 完全一致;标题优先规则已有测试钉住(含"同形状重命名按生成名处理"的文档化局限);初审后新增的两条 latch 路径各有复现精确失败序列的见证测试;readOnly 门控让未受信任的次级工作区即使存在手动分组也保持走带信任门的平铺分支(这正是维护者指出的既有 403 UX 缺陷的修复,已有测试钉住);三处 15000 超时上调纯属 deflake(维护者实测 merge-base 与 head 的套件耗时基本一致,移除后本地仍全绿);ChatEditor.test.tsx 的 hunk 与上游 #10729 的修复重复,无害,rebase 后消失。

非阻塞跟进:WebShellSidebar 的分桶顺序仍无测试钉住(维护者的变异体 M7/M11 存活),批准者已接受该缺口;PR 描述的 "Risk & Scope" 仍未提及信任门修复,补一句即可。

测试证据:来自 PR 自身 CI(我不运行 PR 代码)。两个红色检查均为基础设施问题:Test (ubuntu-latest) 两次都在 ECS 运行器 120 分钟上限处被取消,日志显示主套件在被杀前已全绿(981 个文件、27,693 通过、0 失败),日志中唯一的红项位于本 diff 完全未触及的 packages/core 钩子时序测试;web-shell E2E Smoke attempt 2 因"runner 收到关机信号"失败,而同一 head 的 attempt 1 该套件通过;main 分支在同一时间窗于同批 ECS 运行器上连续取消/失败(约 22:11 UTC 恢复),支持运行集群故障而非本 PR 回归的判断。维护者已在该 head 本地将两套用例跑绿且结论一致。因无在途重跑,我已将两个红色任务重新排队(attempt 3),表格由 finalize 任务在 CI 结束后更新。沙箱 verify 任务已随本次 /triage 运行在途(维护者触发),A/B 报告将跟贴在本线程;Windows/Linux 渲染仍依赖视觉截图与作者说明。

Qwen Code · qwen3.8-max

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

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

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

Screenshots · before / after

terminal-turn-error-copy-narrow-dark before/after

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

Qwen Code · web-shell visuals

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — consistent with the maintainer's own verdict after live validation: every claim in the PR reproduces end-to-end against a real daemon, and what remains is non-blocking (a test gap the approver accepted, and a one-line description note).

Going back to my independent proposal: the PR matches it, and after five review rounds I found nothing I would have done differently — one small single-purpose helper plus wiring into the existing section components, no parallel machinery. The diff grew since the first review, but every addition answers a named finding: the latch re-arms, the label-preference rule and its pinning tests, the deflake timeouts. No scope creep. The single out-of-scope item is the readOnly trust-gate line, which is a real, maintainer-verified UX fix (untrusted workspaces with a manual group used to render clickable rows that 403'd) rather than drive-by churn.

Reservations, none blocking: WebShellSidebar bucketing order still isn't pinned by a test (mutants M7/M11 survive); the approver accepted that gap, and the suggested follow-up test is small. Windows/Linux rendering rests on the visual capture and the author's word — the maintainer's live Linux validation against a real daemon covers the behavioral claim, and the in-flight verify job adds reproducible A/B proof.

CI on this head landed red but clearly from infrastructure (runner shutdown signal, 120-minute ECS timeout with the suite green before the kill, main red in the same window — evidence in Stage 2). I queued a rerun of the two red jobs, so approval is deferred until CI lands green on 868683029afb8a6050daf845b4d5390f55b00db3.

中文说明

Confidence: 4/5 —— 与维护者真机验证后的结论一致:PR 的每项声明都能在真实 daemon 上端到端复现,剩余事项均不阻塞(批准者已接受的测试缺口,以及一行描述补充)。

对照我的独立方案:PR 与之一致,五轮评审后仍没有想换的做法——一个小的单一职责 helper 加上对现有分组组件的接线,没有平行机制。初审后 diff 有增长,但每处增量都对应具体评审发现:latch 重置、标题优先规则及其钉住测试、deflake 超时,无范围蔓延。唯一超出声明范围的是 readOnly 信任门一行,属于维护者已前后验证的真实 UX 修复(未受信任工作区存在手动分组时会话行可点击但 403),不是顺手改动。

非阻塞保留意见:WebShellSidebar 的分桶顺序仍无测试钉住(变异体 M7/M11 存活),批准者已接受该缺口,建议的补充测试很小。Windows/Linux 渲染依赖视觉截图与作者说明——维护者的 Linux 真机验证覆盖了行为声明,在途的 verify 任务会补充可复现的 A/B 证据。

该 head 的 CI 红色为基础设施问题(runner 关机信号、120 分钟 ECS 超时且套件被杀前全绿、main 同窗口同样红——证据见 Stage 2)。两个红色任务的重跑已排队,待 CI 在受审提交上变绿后批准。

Qwen Code · qwen3.8-max

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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

Comment thread packages/web-shell/client/components/sidebar/WebShellSidebar.tsx
Comment thread packages/web-shell/client/components/sidebar/WorkspaceSection.tsx Outdated
Comment thread packages/web-shell/client/components/sidebar/WorkspaceSection.tsx
Comment thread packages/web-shell/client/components/sidebar/WorkspaceSection.tsx Outdated
@qqqys

qqqys commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

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

Copy link
Copy Markdown
Collaborator

🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 autofix/takeover 标签(或评论 @qwen-code /takeover stop)即可释放。

@qwen-code-dev-bot

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

Copy link
Copy Markdown
Collaborator

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

中文说明

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round (same-run verification repair) — PR #10611

The previous commit (17e6808e15, addressing all eight round-1 findings) was
rejected by deterministic verification because two tests in
packages/web-shell timed out in the gate's full changed-file run:

  • WebShellSidebar.workspace-removal.test.tsx > gives a locked trusted secondary active row normal actions through its workspace
  • WebShellSidebar.workspace-removal.test.tsx > routes locked secondary delete, archive, color, and pinned mutations only to its client

Per the same-run repair rule, the rejected commit is preserved and this round
adds one follow-up commit (503bcd2d05) fixing that rejection. No base
conflict (--conflict false); no merge performed.

Diagnosis

Evidence, not guesswork:

  1. The two tests pass locally in isolation and under the exact gate
    command
    — but they are the two slowest tests in the file: ~888 ms and
    ~867 ms measured at current HEAD (third place is 577 ms).
  2. Baseline probe on origin/main (origin/main test file + component
    temporarily placed in the tree, measured, then restored): the same two
    tests take ~851 ms and ~893 ms — identical to HEAD. The PR's changes do
    not slow these tests; the PR's test-file edits start at line 4349 and run
    after both failing tests, so test-order contamination is also excluded.
  3. The gate runner was substantially more loaded than this environment:
    its run reports collect 120 s vs ~58–71 s locally and aggregate test time
    239 s vs 151–186 s locally. A ~900 ms test under several-fold worker
    contention crosses vitest's default 5000 ms test timeout.

Conclusion: pre-existing slow tests (heavy locked-secondary interaction
scenarios) that exceeded the default 5 s budget under parallel CI load. Not a
product defect and not caused by this PR.

Fix

Gave exactly those two tests an explicit 15000 ms timeout via the it(...)
third argument — the established repository convention
(packages/cli uses }, 10000); / }, 15000); / }, 20000); for its slow
tests; no such timeouts existed in web-shell yet because no test there had
approached the cap). All assertions are untouched; a genuinely hung test still
fails, just at 15 s. 15 s is ~16× the isolated runtime (~0.9 s), absorbing a
far larger load factor than the one observed at the gate.

No mutation probe applies to this change: it adds no guard or branch to
product code, only a timeout argument. The evidence above is the witness —
baseline timings prove why 5 s failed and why 15 s holds; the two tests
themselves are the coverage.

Round-1 ledger findings (re-listed in this round's feedback)

The rejected commit already addressed these; they were re-verified at the
current HEAD by the gate-command run below (14 files, 935 tests, 0
failures
, including every witness test):

Finding Severity Disposition
R1-1 first-sync latch consumed during org-disabled phase (rc:3892948337) Critical Resolved in preserved commit; witness test registers manual groups as initial when organization lands after a scheduled-task settle green at HEAD
R1-2 duplicated get-or-create accumulation (rc:3892948347) Suggestion Resolved in preserved commit; both call-site witness tests green
R1-3 label recovered from a lossily truncated display name (rc:3892948357) Suggestion Partial — truncation documented in preserved commit; structural sourceTitle part deferred to the follow-up queue (out of web-shell footprint), thread left open with a reply
R1-4 time-suffix regex mirror undocumented (rc:3892948363) Suggestion Resolved in preserved commit (comment-only)
R1-5 grouped branch lacks the readOnly trust gate (rc:3892948371) Suggestion Resolved in preserved commit; witness test keeps scheduled-task runs read-only in an untrusted workspace green
R1-6 manual-group-over-scheduled-task precedence untested (rc:3892948374) Suggestion Resolved in preserved commit; witness test keeps a manually grouped scheduled-task run under its manual group green
R1-7 run exclusivity from Ungrouped/Recent unpinned (rc:3892948381) Suggestion Resolved in preserved commit; strengthened assertions green
R1-8 label || taskId fallback untested (rc:3892948389) Suggestion Resolved in preserved commit; fallback cases (falls back to the task id…) green

Issue-level comments

  • ic:5474754722 (maintainer E2E verification): informational, consistent with
    the green test run; no action needed.
  • ic:5474862562 (web-shell visual preview): not addressed. Adding a
    screenshots.spec.ts scenario is a nice-to-have beyond this repair round's
    scope, and this runner has no Playwright browsers to verify one. Recorded
    as a follow-up candidate in the previous round.

Changed files

  • packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx
    (two lines: });}, 15000); on the two slow tests)

Verification

All commands actually run this round, with results:

  • Baseline timing probe — swapped origin/main versions of the test file and
    WebShellSidebar.tsx into the tree, ran the two tests (851 ms / 893 ms,
    both passed), restored HEAD versions, confirmed git status clean — proves
    the slowness predates this PR
  • npx vitest run --config vitest.config.ts client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx
    (from packages/web-shell) — 1 file, 104 tests passed
  • Gate command npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests
    (from packages/web-shell) — 14 files, 935 tests passed, 0 failures (junit
    confirms all round-1 witness tests present and green)
  • npm run build — exit 0
  • npm run typecheck — exit 0
  • npm run lint — exit 0
  • npx prettier --check on the changed test file — passed
  • Pre-commit hook at commit time (Prettier/ESLint on staged files) — passed
中文说明

Autofix 评审轮次(同轮验证修复)— PR #10611

上一个提交(17e6808e15,已处理第 1 轮全部八项发现)被确定性验证拒绝,原因是
packages/web-shell 中两个测试在门禁的变更文件全量运行中超时:

  • WebShellSidebar.workspace-removal.test.tsx > gives a locked trusted secondary active row normal actions through its workspace
  • WebShellSidebar.workspace-removal.test.tsx > routes locked secondary delete, archive, color, and pinned mutations only to its client

按同轮修复规则,被拒提交予以保留,本轮追加一个修复该拒绝的后续提交
503bcd2d05)。无基线冲突(--conflict false),未做任何合并。

诊断

基于证据而非猜测:

  1. 这两个测试在本地单独运行和门禁同款命令下都能通过——但它们是文件中
    最慢的两个测试:当前 HEAD 实测约 888 毫秒与 867 毫秒(第三名仅 577 毫秒)。
  2. origin/main 上做基线探针(将 origin/main 的测试文件与组件临时换入
    树中测量后恢复):同样两个测试耗时约 851 毫秒与 893 毫秒——与 HEAD 完全一致。
    本 PR 的改动没有拖慢这两个测试;PR 对测试文件的编辑从 4349 行开始,位于两个
    失败测试之后,也排除了测试顺序污染。
  3. 门禁运行器的负载明显高于本环境:其运行记录显示 collect 120 秒,本地约
    58–71 秒;测试总耗时 239 秒,本地约 151–186 秒。约 900 毫秒的测试在数倍于
    常态的 worker 争用下会越过 vitest 默认 5000 毫秒的测试超时。

结论:既有的慢测试(重量级的锁定次工作区交互场景)在并行 CI 负载下超出默认
5 秒预算。不是产品缺陷,也非本 PR 引入。

修复

恰好给这两个测试通过 it(...) 第三参数加上显式 15000 毫秒超时——这是仓库既有
惯例(packages/cli 的慢测试使用 }, 10000); / }, 15000); / }, 20000);
web-shell 此前没有测试接近上限,故无先例)。所有断言原样保留;真正挂死的测试
依旧会失败,只是在 15 秒时失败。15 秒约为单独运行耗时(约 0.9 秒)的 16 倍,
足以吸收远大于门禁实际观测到的负载倍数。

本轮改动不适用变异探针:未向产品代码添加任何守卫或分支,只是超时参数。上文证据
即为见证——基线计时证明了 5 秒为何失败、15 秒为何成立;两个测试本身即为覆盖。

第 1 轮清单发现(在本轮反馈中重新列出)

被拒提交已处理这些发现;本轮在现有 HEAD 上通过门禁命令运行重新验证(14 个文件、
935 个测试、0 失败,含全部见证测试):

发现 严重度 处置
R1-1 组织关闭阶段消耗首次同步锁存器(rc:3892948337) Critical 已在保留提交中解决;见证测试 registers manual groups as initial when organization lands after a scheduled-task settle 在 HEAD 为绿
R1-2 重复的 get-or-create 累积循环(rc:3892948347) Suggestion 已在保留提交中解决;两个调用点见证测试为绿
R1-3 分组标签从有损截断的显示名还原(rc:3892948357) Suggestion 部分处理——截断说明已随保留提交落地;结构化 sourceTitle 部分延后至跟进队列(超出 web-shell 足迹),线程保持打开并已回复
R1-4 时间后缀正则镜像未注明(rc:3892948363) Suggestion 已在保留提交中解决(纯注释)
R1-5 分组分支缺少 readOnly 信任门(rc:3892948371) Suggestion 已在保留提交中解决;见证测试 keeps scheduled-task runs read-only in an untrusted workspace 为绿
R1-6 手动分组优先于定时任务的优先级无测试(rc:3892948374) Suggestion 已在保留提交中解决;见证测试 keeps a manually grouped scheduled-task run under its manual group 为绿
R1-7 运行会话相对 Ungrouped/Recent 的排他性未钉住(rc:3892948381) Suggestion 已在保留提交中解决;加强后的断言为绿
R1-8 label || taskId 回退无测试(rc:3892948389) Suggestion 已在保留提交中解决;回退用例(falls back to the task id…)为绿

议题级评论

  • ic:5474754722(维护者 E2E 验证):信息性,与绿色测试运行一致,无需处理。
  • ic:5474862562(web-shell 视觉预览):不处理。新增 screenshots.spec.ts
    场景属于超出本修复轮范围的锦上添花,且本运行器没有 Playwright 浏览器、
    无法验证此类场景。已在上一轮记录为后续跟进候选。

变更文件

  • packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx
    (两行:两个慢测试的 });}, 15000);

验证

本轮实际运行的全部命令及结果:

  • 基线计时探针——将 origin/main 版本的测试文件与 WebShellSidebar.tsx 换入树中,
    运行两个测试(851 毫秒 / 893 毫秒,均通过),恢复 HEAD 版本并确认
    git status 干净——证明慢速早于本 PR 存在
  • npx vitest run --config vitest.config.ts client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx
    (在 packages/web-shell 下)— 1 个文件、104 个测试通过
  • 门禁命令 npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests
    (在 packages/web-shell 下)— 14 个文件、935 个测试通过、0 失败(junit 确认
    第 1 轮全部见证测试在列且为绿)
  • npm run build — 退出码 0
  • npm run typecheck — 退出码 0
  • npm run lint — 退出码 0
  • 对变更测试文件执行 npx prettier --check — 通过
  • 提交时 pre-commit 钩子(对暂存文件的 Prettier/ESLint)— 通过

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

🧵 Resolved all 7 selected review thread(s). · 已关闭全部选中的 7 条评审线程。

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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/sidebar/WebShellSidebar.tsx:3875 — [probe] D2-1 settle-gate rewrite is inert in the tests (revert mutant leaves 156/156 green) — code unchanged since the round-1 reviewed head
  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:2052 — [probe] D2-2 in-flight reloadGroups clobbers the org-revoke clear; PR's early-return removals make the stale state visible — race code unchanged since the round-1 revie…
中文说明

已审查——无阻断问题。 建议见行内评论。

收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。

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

Comment thread packages/web-shell/client/components/sidebar/WebShellSidebar.tsx Outdated
Comment thread packages/web-shell/client/components/sidebar/WebShellSidebar.tsx
@qqqys

qqqys commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover from 2

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔄 Takeover re-armed: the round counter starts a fresh window (earlier rounds count toward the cap only via this seed); management continues. This window's round counter restarts at 2 (rounds already spent on this PR), so the Critical-only brake engages after 3 more change-producing round(s) instead of a full fresh 5.

中文说明

🔄 已重新武装:轮次计数开启新窗口(此前轮次仅通过该种子计入上限),托管继续。本窗口轮次计数从 2 重启(即本 PR 已消耗的轮次),因此再经过 3 个产生改动的轮次即进入 Critical-only,而非重新计满 5 轮。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix address-review summary — PR #10611 (round 4, same-run verification repair)

New commit: ffd8266486 test(web-shell): deflake session overview and boot tests under CI load (#10611) on feat/web-shell-scheduled-task-session-groups, on top of the preserved (previously rejected) commit 2ca4557fcd. No base conflict (--conflict false); origin/main was not merged.

Same-run verification repair — deterministic rejection fixed

The previous round was rejected because packages/web-shell tests failed: SessionOverviewPanel > selects every session across pages like the old overview died with Error: Test timed out in 5000ms under CI load.

Reproduced locally before changing anything: running the gate's exact command (npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests from packages/web-shell, this same self-hosted runner) reproduced the timeout class — junit recorded the failing test at 8.06s wall with Error: Test timed out in 5000ms, and main-boot.test.tsx > clears the boot fallback when the app mounts after the grace period at 5.28s with the same error.

Root cause: both are fully-mocked tests whose wall time is dominated by jsdom rendering (the overview test renders 50 table rows plus a select-all re-render; it already takes ~1s unloaded, the slowest in its file) and by the cold import('./main') of the app dependency graph (the boot test; the failing run's transform phase took ~50s). Under the saturated suite (939 tests, ~380s cumulative test time), both exceed vitest's default 5000ms budget. Neither is a product regression from this PR — the PR does not touch SessionOverviewPanel.tsx or main.tsx; the tests enter the --changed set only through the WebShellSidebar.module.css import chain.

Fix (allowed deflake class: raise the per-test timeout budget; every assertion and input preserved verbatim): a 15000ms third argument on the two affected it(...) calls, matching this branch's own precedent (503bcd2d05, which deflaked two locked-secondary sidebar tests the same way). The post-fix gate run proves the budget was load-bearing: the two tests took 5.68s and 6.56s there — both would have failed under the old 5000ms budget; the suite finished 939/939 green.

Feedback points and dispositions

  • [rc:3895671411] R1-1 (latch restore only re-arms the selected source) — Resolved in code by the preserved commit 2ca4557fcd; re-verified this round: the Tasks-latch re-arm (WebShellSidebar.tsx:1283), the render-phase groupsCatalogReady gate close on switch back to Tasks, and the sibling-source witness test registers manual groups as initial when organization lands while the channel source is selected are all present and green in the gate run.
  • [rc:3895671427] R2-1 (no test for org-enabled ungrouped scheduled runs) — Resolved in code by the preserved commit; re-verified: the section[aria-label="Hourly review"] assertions after settleGroupsCatalog() and the WorkspaceSection case forms the scheduled-task section while organization is enabled are present and green.
  • [rc:3895671437] R2-2 (group label fixed by first-collected run) — Resolved in code by the preserved commit; re-verified: the generated-name precedence rule in collectScheduledTaskSession and its two precedence unit tests are present and green.
  • D2-1, D2-2 — deferred by the workflow's round-2 convergence posture and explicitly "not requested in this round" — left untouched, per the feedback's own framing.

Mutation probes (witness verification)

Probe Mutation Result
overview timeout third argument 15000 → 500 test red: Error: Test timed out in 500ms; restored → green
boot timeout third argument 15000 → 50 test red: Error: Test timed out in 50ms; restored → green

Changed files

  • packages/web-shell/client/components/SessionOverviewPanel.test.tsx — 15s per-test budget for selects every session across pages like the old overview
  • packages/web-shell/client/main-boot.test.tsx — 15s per-test budget for clears the boot fallback when the app mounts after the grace period

Verification

Commands actually run and their results:

  • npm run buildpassed (exit 0)
  • npm run typecheckpassed (exit 0)
  • npm run lintpassed (exit 0)
  • npx eslint on the two changed files — passed (exit 0)
  • npx prettier --check on the two changed files — passed
  • Gate's exact command cd packages/web-shell && npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests — first (pre-fix) run reproduced the timeout class; final (post-fix) run: 14 files, 939/939 tests passed, exit 0, junit failures="0", with the two deflaked tests finishing at 5.68s and 6.56s (both over the old budget, under the new one)
  • Focused runs: SessionOverviewPanel.test.tsx + main-boot.test.tsx — 98 passed
  • Integration tests: not run — the change is test-only and exercised entirely by the package's Vitest suite
  • npm run generate:settings-schema: not applicable — no settings source changed
中文说明

Autofix address-review 摘要 — PR #10611(第 4 轮,同轮验证修复)

新提交:ffd8266486 test(web-shell): deflake session overview and boot tests under CI load (#10611),位于 feat/web-shell-scheduled-task-session-groups 分支,叠加在保留的(上一轮被拒的)提交 2ca4557fcd 之上。无 base 冲突(--conflict false);未合并 origin/main

同轮验证修复 — 已修复确定性拒绝

上一轮被拒的原因是 packages/web-shell 测试失败:SessionOverviewPanel > selects every session across pages like the old overview 在 CI 负载下以 Error: Test timed out in 5000ms 失败。

改动前已在本地复现:在同一台自托管运行器上执行门禁的原始命令(在 packages/web-shell 下运行 npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests),复现了同类超时——junit 记录该失败测试实际耗时 8.06 秒并报 Error: Test timed out in 5000ms,且 main-boot.test.tsx > clears the boot fallback when the app mounts after the grace period 也以 5.28 秒报出同样错误。

根因:两者都是全 mock 测试,其耗时主要来自 jsdom 渲染(概览测试渲染 50 行表格并触发一次全选重渲染;无负载时已约 1 秒,是该文件中最慢的用例)以及冷 import('./main') 引入整个应用依赖图(boot 测试;失败那次运行的 transform 阶段耗时约 50 秒)。在饱和的套件下(939 个测试、累计测试时长约 380 秒),两者都超过了 vitest 默认的 5000ms 预算。两者都不是本 PR 引入的产品回归——PR 并未改动 SessionOverviewPanel.tsxmain.tsx;这些测试只是因为 WebShellSidebar.module.css 的导入链才进入 --changed 集合。

修复方式(允许的 deflake 类别:提高单测超时预算;所有断言与输入逐字保留):为受影响的两个 it(...) 调用加上 15000ms 第三参数,与本分支自身的先例一致(503bcd2d05 以同样方式为两个 locked-secondary 侧边栏测试 deflake)。修复后的门禁运行证明该预算是承重的:这两个测试在该次运行中分别耗时 5.68 秒和 6.56 秒——在旧的 5000ms 预算下都会失败;套件最终以 939/939 全绿收尾。

反馈点及处置

  • [rc:3895671411] R1-1(锁存器恢复只重新武装被选中的来源) — 已由保留的提交 2ca4557fcd 在代码中解决;本轮重新验证:Tasks 锁存器重新武装(WebShellSidebar.tsx:1283)、切回 Tasks 时渲染阶段关闭 groupsCatalogReady 门、以及兄弟来源见证测试 registers manual groups as initial when organization lands while the channel source is selected 均存在且在门禁运行中为绿色。
  • [rc:3895671427] R2-1(缺少组织启用时未归组定时任务运行的测试) — 已由保留的提交在代码中解决;重新验证:settleGroupsCatalog() 之后的 section[aria-label="Hourly review"] 断言,以及 WorkspaceSection 用例 forms the scheduled-task section while organization is enabled 均存在且为绿色。
  • [rc:3895671437] R2-2(分组标题由最先收集的运行固定) — 已由保留的提交在代码中解决;重新验证:collectScheduledTaskSession 中的生成名优先规则及其两个优先级单元测试均存在且为绿色。
  • D2-1、D2-2 — 由工作流第 2 轮收敛姿态延后,且明确"本轮不要求修改"——按其表述保持不动。

变异探针(见证验证)

探针 变异 结果
overview 超时 第三参数 15000 → 500 测试变红Error: Test timed out in 500ms;还原后变绿
boot 超时 第三参数 15000 → 50 测试变红Error: Test timed out in 50ms;还原后变绿

变更文件

  • packages/web-shell/client/components/SessionOverviewPanel.test.tsx — 为 selects every session across pages like the old overview 设置 15 秒单测预算
  • packages/web-shell/client/main-boot.test.tsx — 为 clears the boot fallback when the app mounts after the grace period 设置 15 秒单测预算

验证

实际执行的命令及结果:

  • npm run build通过(exit 0)
  • npm run typecheck通过(exit 0)
  • npm run lint通过(exit 0)
  • 对两个变更文件运行 npx eslint — 通过(exit 0)
  • 对两个变更文件运行 npx prettier --check — 通过
  • 门禁原始命令 cd packages/web-shell && npx vitest run --config vitest.config.ts --changed origin/main --passWithNoTests — 首次(修复前)运行复现了同类超时;最终(修复后)运行:14 个文件、939/939 测试通过、exit 0,junit failures="0",其中两个被 deflake 的测试分别耗时 5.68 秒和 6.56 秒(均超出旧预算、在新预算之内)
  • 聚焦运行:SessionOverviewPanel.test.tsx + main-boot.test.tsx — 98 个测试通过
  • 集成测试:未运行——本次改动仅涉及测试,且完全由该包的 Vitest 套件覆盖
  • npm run generate:settings-schema:不适用——未改动任何 settings 源

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

🧵 Resolved all 3 selected review thread(s). · 已关闭全部选中的 3 条评审线程。

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed — no blockers. Suggestions are inline.

Convergence: round 3 posted 1 inline comment(s), 1 of them reported for the first time; the previous round posted 3 (3 new). Findings keep coming back to the same files: packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts (findings in round 2; 1 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. No Critical finding is open on this round, so merging and moving the remaining Suggestion threads to a follow-up issue is available as an ending — a merged pull request cannot diverge further. (Observation only — nothing was withheld from this review because of this observation.)

中文说明

已审查——无阻断问题。 建议见行内评论。

收敛情况:第 3 轮发布了 1 条行内评论,其中 1 条是首次提出;上一轮发布了 3 条(其中 3 条首次提出)。发现反复回到同一批文件:packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts(第 2 轮已出过发现,本轮又有 1 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。本轮没有未决的 Critical,因此"合入后把剩余 Suggestion 线程转到后续 issue"是一个可选的结束方式——已合入的 PR 不会继续发散。(仅为观察——本轮评审未因此扣留任何内容。)

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

…QwenLM#10611)

A user rename ending in the generated run-name suffix shape is indistinguishable from a generated name at the rendered-string layer. Document that limit above SCHEDULED_TASK_RUN_TIME_SUFFIX and pin the current classification with a test; the structural fix (persisting the task title alongside the run) is tracked as a follow-up.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Address review summary — PR #10611

One feedback item this round; no failed or still-red checks; --conflict false so no merge was performed.

Feedback points

[rv:5070553093] Review — "no blockers, suggestions inline"

No action required; the single inline suggestion is handled below.

[rc:3897838328] [Suggestion] R2-2 (fix-induced): shape-based label preference cannot tell a user rename from a generated run name

Verification — reproduced on HEAD ffd8266. A scratch vitest probe (deleted after recording) ran the pure function with the finding's scenarios:

  • PROBE-A (rename Investigate flake, then rename Follow-up · 08-31 09:30) → label Follow-up — the suffix-shaped rename outranks the plain rename and its suffix is stripped, exactly as reported.
  • PROBE-B (lone rename Follow-up · 08-31 09:30) → label Follow-up.
  • PROBE-C control (real generated name Hourly review · 08-31 09:30 plus a rename) → label Hourly review — the preference itself works for genuinely generated names.

The finding stands: at the rendered-string layer a rename and a generated name that share the · MM-DD HH:mm shape are informationally identical, so no classifier change at this layer can fix it.

Disposition — addressed in scope now; structural fix deferred to the follow-up queue (deferred-findings.json, thread left open with a reply in comment-replies.json):

  • Documented the known limit above SCHEDULED_TASK_RUN_TIME_SUFFIX in scheduled-task-session-groups.ts (+4 lines), as the finding's fallback option proposes.
  • Added the requested test case treats a rename matching the suffix shape as a generated name in scheduled-task-session-groups.test.ts, pinning the documented behavior (label Follow-up). Mutation probe: temporarily reverting the shape-preference branch to first-wins makes the new test (and the existing preference test) FAIL (2 failed | 4 passed); restoring it returns to 6 passed — so the test is a live witness for the pinned behavior.
  • The structural fix (persisting the task title alongside the run when displayName is written in dispatchTaskToFreshSession, reading it in getScheduledTaskSessionGroup, with a synchronized field on both sides of the DaemonSessionSummary/BridgeSessionSummary wire mirror) spans packages/sdk-typescript, packages/acp-bridge, and packages/cli — areas this web-shell-only PR has never touched and which include core infrastructure. It is recorded as a deferred finding for the follow-up queue instead of expanding this PR's footprint.

Changed files (commit 085b70b310, +18 lines):

  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts (+4, comment only)
  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts (+14, one test)

Verification

  • cd packages/web-shell && npx vitest run client/components/sidebar/scheduled-task-session-groups.test.ts — 6 passed (touched package)
  • Mutation probe (new-test witness): preference branch flipped to first-wins → 2 failed including the new test; restored → 6 passed
  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0)
  • npm run lint — passed (exit 0)
  • Not applicable: npm run generate:settings-schema (no settings source touched); integration tests after npm run bundle (the touched behavior is a pure client-side function covered by the unit tests above)
中文说明

处理评审摘要 — PR #10611

本轮共 1 条反馈;无失败检查项,无遗留未通过的检查项;--conflict false,未执行合并。

反馈点

[rv:5070553093] 评审 —"无阻断问题,建议见行内"

无需处理;唯一的行内建议在下方处理。

[rc:3897838328] [Suggestion] R2-2(修复引发):按格式优先的标签规则无法区分用户重命名与生成的运行名

验证——已在 HEAD ffd8266 上复现。 用一个临时 vitest 探针(记录输出后已删除)对该纯函数执行了发现中的场景:

  • PROBE-A(先重命名 Investigate flake,再重命名 Follow-up · 08-31 09:30)→ 标签为 Follow-up——后缀格式的重命名压过普通重命名且后缀被剥离,与报告完全一致。
  • PROBE-B(仅有重命名 Follow-up · 08-31 09:30)→ 标签为 Follow-up
  • PROBE-C 对照(真实生成名 Hourly review · 08-31 09:30 加一个重命名)→ 标签为 Hourly review——对真正的生成名,优先规则本身工作正常。

该发现成立:在渲染字符串层,共享 · MM-DD HH:mm 格式的重命名与生成名信息上完全相同,因此在任何分类器层面都无法修复。

处置——本轮在范围内处理;结构性修复转入后续跟进队列(记录于 deferred-findings.json,线程保持打开,并在 comment-replies.json 中回复):

  • 按发现提出的备选方案,在 scheduled-task-session-groups.tsSCHEDULED_TASK_RUN_TIME_SUFFIX 上方记录了已知局限(+4 行)。
  • scheduled-task-session-groups.test.ts 中补充了所要求的测试用例 treats a rename matching the suffix shape as a generated name,固定当前已记录的行为(标签为 Follow-up)。变异探针:将格式优先分支临时回退为先到先得后,新测试(及既有优先测试)失败(2 failed | 4 passed);恢复后回到 6 passed——该测试是所固定行为的有效见证。
  • 结构性修复(在 dispatchTaskToFreshSession 写入 displayName 时将任务标题一并持久化、getScheduledTaskSessionGroup 直接读取,并在 DaemonSessionSummary/BridgeSessionSummary 线格式镜像两侧同步添加字段)涉及 packages/sdk-typescriptpackages/acp-bridgepackages/cli——均为本 web-shell PR 从未触及的区域,且包含核心基础设施。因此记录为延后跟进项,而不扩大本 PR 的足迹。

变更文件(提交 085b70b310,+18 行):

  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts(+4,仅注释)
  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts(+14,一个测试)

验证

  • cd packages/web-shell && npx vitest run client/components/sidebar/scheduled-task-session-groups.test.ts — 6 通过(触及的包)
  • 变异探针(新测试见证):将优先分支回退为先到先得 → 2 失败(含新测试);恢复 → 6 通过
  • npm run build — 通过(exit 0)
  • npm run typecheck — 通过(exit 0)
  • npm run lint — 通过(exit 0)
  • 不适用:npm run generate:settings-schema(未触及设置源);npm run bundle 后的集成测试(触及的行为是纯客户端函数,已由上述单元测试覆盖)

🦷 Gate advisory — this round's changed tests all pass on the pre-round tree (machine-measured, not agent-authored). Expected for a refactor or coverage addition; if this round was meant to FIX a defect, that defect did not reproduce. · 本轮改动的测试在轮前树上全部通过(门自动测量,非 agent 文本)。对重构或补充覆盖属正常;若本轮意在修复缺陷,则该缺陷未能复现。

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

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:

  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts:66 — [probe] D4-1 label-retention guard's blocking direction is untested — probe-confirmed mutant removing .some() survives the whole shipped suite
  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:3806 — [review] D4-2 stale manual groups paint one frame after org flips off — sessionSections memo's group branch ungated, unlike WorkspaceSection
  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:3824 — [probe] D4-3 scheduled-task section header flips while searching — label derived from search-filtered membership, probe-reproduced
中文说明

⚠️ 已从批准降级为评论:CI still running。 已审查。

收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 3 条(原文未翻译,列表见上方英文部分)。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔀 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 qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed.

2 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • Round-5 label-recovery altitude finding — already reported (R1-3, comment 3892948357; R2-2 cluster, comments 3895671437 and 3897838328)
  • Round-5 producer-mirror coupling finding — already reported (R1-4, comment 3892948363)

Not explored to full depth (tool budget reached): "agent 6a": none — no check was cut short..

Deferred under the convergence posture (round 5, not a blocker) — recorded, not requested in this round:

  • packages/web-shell/client/components/sidebar/WorkspaceSection.tsx:820 — [probe] all-pinned scheduled sections keep the grouped view via an untested scheduledSections.some(...) clause — mutant survives the whole shipped suite
  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:3824 — [probe] org-disabled grouped path drops the flat path's creation-descending sort for Ungrouped rows — order flips when the first scheduled run appears
中文说明

已审查。

本轮确认的 2 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

未探索到全部深度(达到工具调用预算):"agent 6a"none — no check was cut short.

收敛姿态下延后(第 5 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind main, so it merged current main in via update-branch and will retry on the next scan. A stale base (a dependency or symbol main already changed) can fail the build without being the fix's fault; if it still fails once current, it hands off to a human.

What I found before stopping:
Qwen hit the tool-call loop guard during address-review. A human should take over this feedback batch.

See the Qwen Autofix agent step logs for model/tool output.

中文说明

🤖 AutoFix 更新了一个过期的 base —— 修复未通过验证,但本 PR 落后于 main,因此已通过 update-branch 合入当前 main,并将在下次扫描时重试。过期的 base(main 已改动的依赖或符号)可能让构建失败而并非修复本身的错;若 base 更新后仍然失败,将移交人工处理。

Run log: https://github.com/QwenLM/qwen-code/actions/runs/33463003729


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed.

7 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • Label recovery via reverse-parsing the rendered displayName vs a structured task title — already reported (R1-3, comment 3892948357; R2-2 cluster, comments 3895671437 and 3897838328)
  • First-wins label instability across divergent generated titles in collectScheduledTaskSession — already reported (R2-2, comment 3895671437)
  • Suffix-regex producer/consumer drift coupling and contract-test angle — already reported (R1-4, comment 3892948363; its minimal fix, the consumer-side mirror comment, landed in the current diff)
  • Producer-side back-pointer comment for the suffix mirror — already reported (R1-4, comment 3892948363)
  • Stale manual groups paint one frame after org flips off (sessionSections memo group branch ungated) — already reported (D4-2, round-4 deferred list, review 5072186698)
  • Untested scheduledSections.some(...) clause in the WorkspaceSection empty-label guard — already reported (D5-1, round-5 deferred list, review 5073326594)
  • Org-disabled grouped path drops the flat path's creation-descending sort for Ungrouped rows — already reported (D5-2, round-5 deferred list, review 5073326594)

2 Suggestion(s) were drafted inline past the resolved critical posting floor; the CLI moved them into the deferral list below (floor enforcement).

Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:

  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:1284 — [review] R6-1: The first-sync latch is re-armed only when the session_organization capability flips ON; when it flips OFF mid-session, the newly formed Ungrouped ( re…
  • packages/web-shell/client/components/sidebar/scheduled-task-session-groups.ts:69 — [review] R6-2: collectScheduledTaskSession re-scans the whole section with a regex test on every generated-name run, even though the label decision is perm…
中文说明

已审查。

本轮确认的 7 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

2 条 Suggestion 在已解析的 critical 发布下限之外被起草为行内评论;CLI 已将其移入下方延后清单(下限强制执行)。

收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。

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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review round — no action taken

All feedback newer than the last evaluation (2026-08-31T19:51:32Z) was triaged. Nothing actionable was found this round, so no code changes were made and the branch remains at 93c62ed9.

Feedback triage

  • Automated review rounds 4–6 (rv:5072186698, rv:5073326594, rv:5074548763) each posted 0 fresh findings (fresh: 0, posted: 0).
  • Every finding referenced in this round's feedback is one of:
    • Already reported on this PR in earlier rounds and still open for maintainer consideration — the R1-3 / R2-2 label-recovery cluster and the R1-4 producer/consumer suffix-mirror coupling; or
    • Deferred by the reviewer under the convergence posture, explicitly marked "recorded, not requested in this round" (D4-1, D4-2, D4-3, D5-1, D5-2, R6-1, R6-2). These are audit records, not requested work, so they were intentionally left untouched; they remain recorded in the review's deferred ledger for a maintainer to schedule if desired.
  • Inline comments: none. Issue-level comments: none. Conflicts: none (--conflict false).

Cancelled check: web-shell E2E Smoke (ubuntu-latest, Node 22.x)

Diagnosed from CI metadata (job logs are not available in this environment):

  • The job ran 20m 28s (04:55:27Z → 05:15:55Z) against timeout-minutes: 20 in ci.yml — i.e. it hit the job timeout, so the conclusion is CANCELLED, not a test FAILURE.
  • The job's wall-clock budget is dominated by runner setup on the self-hosted pool (npm ci, npx playwright install chromium), which is unrelated to this PR's code.
  • No evidence of a code-level defect from this PR:
    • This PR changes only packages/web-shell/client/components/sidebar/** and their collocated unit tests; it touches no CI workflow, e2e spec, or Playwright configuration.
    • On this same commit (93c62ed9), the unit-test job Test (ubuntu-latest, Node 22.x) passed, and Capture web-shell visuals — a Playwright rendering of this same web shell including this PR's sidebar changes — also passed. A sidebar rendering hang would have surfaced there.

Conclusion: an environment/timing timeout; the appropriate remedy is a CI re-run of the job, and no code change is warranted.

Changes made

None. No commit was created.

中文说明

Autofix 审查轮次 — 未采取任何操作

已对上次评估(2026-08-31T19:51:32Z)之后的全部反馈进行分类处理。本轮没有任何可操作事项,因此未做任何代码修改,分支仍停留在 93c62ed9

反馈分类

  • 自动审查第 4–6 轮(rv:5072186698、rv:5073326594、rv:5074548763)均未发布新发现fresh: 0posted: 0)。
  • 本轮反馈中提及的每一条发现都属于以下两类之一:
    • 已在此前轮次报告过、仍留待维护者考量——R1-3 / R2-2 标签恢复(label-recovery)问题簇,以及 R1-4 生产者/消费者后缀镜像耦合问题;或
    • 被审查者按收敛姿态(convergence posture)延后、并明确标注"已记录,本轮不要求修改"(D4-1、D4-2、D4-3、D5-1、D5-2、R6-1、R6-2)。这些是审计记录,不是本轮要求处理的工作,因此有意不做改动;它们仍保留在审查的延后清单中,维护者如有需要可自行安排处理。
  • **行内评论:**无。**Issue 级评论:**无。**冲突:**无(--conflict false)。

被取消的检查:web-shell E2E Smoke (ubuntu-latest, Node 22.x)

基于 CI 元数据诊断(本环境无法获取任务日志):

  • 该任务运行了 20 分 28 秒(04:55:27Z → 05:15:55Z),而 ci.yml 中设置了 timeout-minutes: 20 —— 即触发了任务超时,因此结论为 CANCELLED(被取消),而不是测试 FAILURE(失败)。
  • 该任务的耗时主要来自自托管运行器上的安装准备步骤(npm cinpx playwright install chromium),与本 PR 的代码无关。
  • 没有证据表明是本 PR 引入的代码级缺陷:
    • 本 PR 仅修改 packages/web-shell/client/components/sidebar/** 及其同目录单元测试,未触碰任何 CI 工作流、e2e 用例或 Playwright 配置。
    • 在同一提交(93c62ed9)上,单元测试任务 Test (ubuntu-latest, Node 22.x) 已通过,Capture web-shell visuals —— 一个用 Playwright 渲染同一 web shell(含本 PR 侧边栏改动)的任务 —— 也已通过。如果侧边栏渲染存在挂起问题,在那里就会暴露。

结论:属于环境/耗时超时;合适的处理方式是重新运行该 CI 任务,无需修改代码。

所做修改

无。未创建任何提交。

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


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

…led-task-session-groups

# Conflicts:
#	packages/web-shell/client/components/sidebar/WebShellSidebar.tsx
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

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

Autofix review-response summary

No new review feedback arrived this window (no reviews, inline comments, issue-level comments, or failed checks), so this round's work was the requested base-conflict resolution: merging origin/main into the PR branch.

Conflict resolution

origin/main advanced by 8 commits, among them feat(web-shell): Add standalone chats (#10514), which conflicted with this PR in packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:

  • This PR split the channel check into channelManagementEnabled (a pure capability read reused by the Tasks-latch re-arm introduced for scheduled task session groups) plus channelGroupingEnabled (source + capability).
  • Main's standalone-chats work added a projectFeaturesEnabled gate to channelGroupingEnabled so non-workspace contexts never load channel grouping, mirroring the gate it added to organizationEnabled.

Resolution keeps both intents: the PR's split stays, and main's projectFeaturesEnabled gate is applied to the channelGroupingEnabled composite — semantically identical to main's definition. The latch re-arm usage of channelManagementEnabled is already guarded by organizationEnabled, which itself implies projectFeaturesEnabled, so the merge introduces no behavior change there. Everything else merged cleanly, including WebShellSidebar.workspace-removal.test.tsx.

Mutation probe

Per the witness rule, the merged gate was probed: temporarily removing projectFeaturesEnabled && from channelGroupingEnabled left the entire web-shell suite green (5510 tests), i.e. no existing test pinned it — the one nearby assertion only checks the default session source. A focused witness test was added: it activates the Channels source, then hides project features while that source is still active (the exact path the gate protects, since the source tabs disappear but the sessionSource state persists) and asserts useChannels switches from {autoLoad: true, enabled: true} to {autoLoad: false, enabled: false}. Probe results: gate removed → the new test fails (1 failed | 109 passed); gate restored → green (110 passed).

Verification

  • npm install --no-audit --no-fund — ran first to sync workspace links for the newly merged packages/qwen-live; an incidental lockfile churn from the local npm version (stripped libc metadata fields) was discarded, keeping the merged lockfile byte-identical
  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run --config vitest.config.ts in packages/web-shell — 243 files, 5511 tests passed (final tree, includes the new witness test)
  • Mutation probe on the merged projectFeaturesEnabled gate — without the gate the new witness test fails; with it restored, all sidebar tests pass
  • Integration tests after npm run bundle — not applicable: the change is web-shell sidebar UI, not exercised through the bundled CLI
  • npm run generate:settings-schema — not applicable: this round did not change any settings source
中文说明

Autofix 评审响应总结

本轮窗口内没有新的评审反馈(没有评审、行内评论、issue 级评论或失败的检查),因此本轮的工作是按要求解决与基础分支的冲突:将 origin/main 合并进 PR 分支。

冲突解决

origin/main 前进了 8 个提交,其中 feat(web-shell): Add standalone chats (#10514) 与本 PR 在 packages/web-shell/client/components/sidebar/WebShellSidebar.tsx 中发生冲突:

  • 本 PR 将 channel 判断拆分为 channelManagementEnabled(纯能力读取,被定时任务会话组引入的 Tasks 锁存重新激活逻辑复用)和 channelGroupingEnabled(来源 + 能力)。
  • main 的独立会话(standalone chats)工作为 channelGroupingEnabled 增加了 projectFeaturesEnabled 门控,使非工作区上下文不会加载 channel 分组,与其为 organizationEnabled 增加的门控保持一致。

解决方案同时保留双方意图:保留本 PR 的拆分,并将 main 的 projectFeaturesEnabled 门控应用到 channelGroupingEnabled 组合上——语义上与 main 的定义完全一致。锁存重新激活处对 channelManagementEnabled 的使用已由 organizationEnabled 守卫,而后者本身已蕴含 projectFeaturesEnabled,因此合并不会在该处引入行为变化。其余内容全部自动合并成功,包括 WebShellSidebar.workspace-removal.test.tsx

变更探测(Mutation probe)

按照"每个新增守卫必须有测试见证"的规则,对合并进来的门控做了探测:临时移除 channelGroupingEnabled 中的 projectFeaturesEnabled && 后,整个 web-shell 测试套件仍然全绿(5510 个测试),即没有现有测试钉住该行为——附近唯一的断言只检查默认会话来源。因此新增了一个聚焦的见证测试:先激活 Channels 来源,然后在项目功能被隐藏时保持该来源仍处于激活状态(这正是门控保护的路径,因为来源切换标签会消失但 sessionSource 状态会保留),并断言 useChannels{autoLoad: true, enabled: true} 变为 {autoLoad: false, enabled: false}。探测结果:移除门控 → 新测试失败(1 失败 | 109 通过);恢复门控 → 全绿(110 通过)。

验证

  • npm install --no-audit --no-fund — 先行执行,以便为新合并进来的 packages/qwen-live 同步工作区链接;本地 npm 版本产生的锁文件无关变动(剥离 libc 元数据字段)已被丢弃,合并后的锁文件保持逐字节一致
  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • packages/web-shell 中执行 npx vitest run --config vitest.config.ts — 243 个文件、5511 个测试全部通过(最终代码树,包含新的见证测试)
  • 对合并进来的 projectFeaturesEnabled 门控做变更探测 — 移除门控时新见证测试失败;恢复后全部 sidebar 测试通过
  • npm run bundle 后的集成测试 — 不适用:本次改动是 web-shell 侧边栏 UI,不经过打包后的 CLI 执行
  • npm run generate:settings-schema — 不适用:本轮未改动任何设置源

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

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


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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed.

5 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • Primary-catalog group-over-scheduled precedence untested — already reported (R1-6, comment 3892948374)
  • O(k^2) .some() re-scan in collectScheduledTaskSession — already reported (R6-2, round-6 deferred list, review 5074548763)
  • All-pinned scheduled-sections empty-label guard untested — already reported (D5-1, round-5 deferred list, review 5073326594)
  • Divergent generated-title label precedence untested — already reported (R2-2, comment 3895671437)
  • Stale manual groups rendered after org revoke — already reported (D2-2, round-2 deferred list, review 5067998490)

Deferred under the convergence posture (round 7, not a blocker) — recorded, not requested in this round:

  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:3894 — [review] No test pins scheduled-task sections rendering below manual groups; section order survives a push-order swap mutation
中文说明

已审查。

本轮确认的 5 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

收敛姿态下延后(第 7 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。

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

@qqqys

qqqys commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover stop

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

Copy link
Copy Markdown
Collaborator

👋 Takeover released: the autofix loop will no longer engage this PR (an in-flight round, if any, completes its bounded work). Re-apply autofix/takeover (or comment @qwen-code /takeover) to re-engage.

中文说明

👋 已释放:autofix 循环不再介入此 PR(在飞的一轮如有,将完成其有界工作)。重新打上 autofix/takeover 标签(或评论 @qwen-code /takeover)即可再次接管。

# Conflicts:
#	packages/web-shell/client/main-boot.test.tsx

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed.

3 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:

  • Structural task title vs display-name reverse-parse label recovery — already reported (R1-3, comment 3892948357; R2-2 cluster, comments 3895671437 and 3897838328)
  • First-wins label precedence across divergent generated titles / pinned older run pinning a stale task title — already reported (R2-2, comment 3895671437)
  • Org-disabled grouped path drops the flat path's creation-descending sort for Ungrouped rows — already reported (D5-2, round-5 deferred list, review 5073326594)

Deferred under the convergence posture (round 8, not a blocker) — recorded, not requested in this round:

  • packages/web-shell/client/components/sidebar/WorkspaceSection.tsx:977 — [probe] scheduled-task section rows render via bare renderSession — secondary-workspace content-search snippets dropped (probe flips)
  • packages/web-shell/client/components/sidebar/WorkspaceSection.tsx:969 — [review] fourth byte-identical copy of the 7-line collapse-toggle closure (905/931/969/989); extract a local helper
  • packages/web-shell/client/components/sidebar/WebShellSidebar.tsx:3907 — [probe] new organizationEnabled color-bucketing guard untested — delete-mutant survives 175/175 sidebar tests
中文说明

已审查。

本轮确认的 3 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。

收敛姿态下延后(第 8 轮,非阻断)——已记录,本轮不要求修改:共 3 条(原文未翻译,列表见上方英文部分)。

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

中文说明

⚠️ 已从批准降级为评论:CI still running。 已审查。

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

@wenshao

wenshao commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Local validation — real qwen serve daemon + real Web Shell in Chromium

Verified as a maintainer at head 868683029a (merge-base b27deb634d, current main 61697df9b0), Linux, Node 22.22.2.

Verdict: recommend merge. Every claim in the PR body reproduces end to end against a live daemon. I found no functional defect. I do have one test-coverage gap I'd like closed (F2), and the PR silently fixes a pre-existing trust-gate UX bug that deserves a line in the description (F1).

How this was validated (not jsdom)

Two vite build outputs of packages/web-shell — one at the PR head, one with only the six changed source files reverted to the merge-base — swapped into dist/web-shell of the same qwen serve binary, so the daemon is byte-identical across arms. Session data is real: a live daemon created durable sessionMode: "per_run" scheduled tasks and fired them via POST /scheduled-tasks/:id/run, so every scheduled_task_run:<taskId> source id and every <title> · MM-DD HH:mm display name was produced by scheduledTaskRunSessionName, not hand-written. 6 tasks / 11 run sessions / 2 workspaces / 1 untrusted secondary.

Results

# Claim Result
1 Runs of one task group under the task title (primary workspace) ✅ Fig 1 — 3 tasks grouped; before: one flat list capped at 5 rows + "Show all"
2 Same in a secondary workspace (WorkspaceSection) ws2 groups its 2 runs; ordinary chat stays in Ungrouped
3 Works without session_organization ✅ Fig 2 — capability stripped in flight: manual/color sections vanish (proving the gate really flipped), scheduled groups remain
4 Manual color + named groups keep precedence ✅ Fig 3 left — "Green" ·1 and "Release triage" ·2 hold their runs; the auto group drops to ·1
5 Group header uses the clock icon, not a color dot [data-web-shell-scheduled-task-group] present, no sessionGroupDot
6 Collapse/expand + persistence ✅ ids are exactly the documented scheduled-task:839s5f8p and ws:f37e922f499c81d3|group:scheduled-task:8f3362wz; survives reload
7 Label = task title with the run-time suffix removed ✅ incl. producer truncation (Reconcile the nightly artifact manifests acro…) and a title that itself ends in a date (Snapshot · 01-02 03:04)
8 Missing displayName → falls back to the task id ✅ header renders alm3h5hv (matches how unnamed session rows already render)
9 Sidebar search ✅ only matching runs form a section; counts adjust

Repo checks at head: packages/web-shell 5589/5589 unit tests pass, tsc --noEmit clean, eslint clean on all changed files, 47/47 test:e2e:smoke Playwright tests pass locally (incl. web-shell.collapsed-groups-persist.spec.ts). Trial-merging current main is conflict-free; after rebuilding sdk-typescript + web-shell on the merged tree, 5642/5642 pass and typecheck is clean.

On the two red CI checks: both are infrastructure, not this PR. web-shell E2E Smoke ends with The runner has received a shutdown signal … The operation was canceled, and Test (ubuntu-latest) is cancelled at the 2 h cap with its only logged failure in packages/core/src/hooks/hook-runner.process.test.ts — unrelated to web-shell. Both suites pass locally at this head.

Fig 1

Fig 2


F1 — the PR also fixes a pre-existing trust-gate bug; please say so in the description

WorkspaceSection.groupedSessions gains if (channelGroupingEnabled || readOnly) return null;. That is not just defensive: on the merge-base, an untrusted secondary workspace that had any manual session group rendered its sessions through the grouped branch, which has no trust gate — the rows came out as role="button", and clicking one fired POST /session/:id/load403 Workspace is not trusted, leaving a red toast and a dead-end conversation view. With the PR the same rows are back to role="note" / "Trust this workspace to open the session" and issue no request at all (Fig 4).

The daemon always enforced trust, so this is a UX bug rather than data exposure — but it is a user-visible fix outside the PR's stated scope, and the "Risk & Scope" section currently says the change is limited to grouping. Worth one sentence (and a Fixes #… if an issue exists).

Fig 4

F2 — WebShellSidebar precedence over the new auto group is entirely untested (the one thing I'd fix)

WorkspaceSection has keeps a manually grouped scheduled-task run under its manual group. WebShellSidebar has no equivalent, and its bucketing order is what makes precedence work. Two mutants against the PR's own production code:

  • M7 — move collectScheduledTaskSession(...) above the session.groupId && validGroupIds.has(...) branch.
  • M11 — skip the color branch for scheduled runs.

Both leave 174/174 tests green across the four touched suites, yet visibly break the UI: the "Green" color section disappears entirely and "Release triage" drops from 2 members to 1, because the auto group swallows them (Fig 3, right — that panel is a real build of the mutated source driven through the same daemon).

Suggested: one test in WebShellSidebar.workspace-removal.test.tsx with a scheduled run carrying color and another carrying groupId, asserting they render in the color/manual sections and not in section[aria-label="<task title>"].

For the record, 9 of the 12 mutants I ran were killed — M1 sourceType guard, M2 empty-taskId guard, M3 label || taskId, M4 suffix strip, M6 never-collect, M8 the readOnly gate, M9 the removed org-disabled early return, M10 the icon slot, M12 the assigned check. Coverage on the new module itself is good; only the sidebar's precedence ordering is unguarded.

Fig 3

F3 — the "first generated name wins" guard is unpinned, and picks the worse label in a real case (minor)

Deleting !section.sessions.some(hasGeneratedRunName) (mutant M5) also keeps 174/174 green. The documented shape-based limit then bites in a way the tests don't show: I renamed one run of Nightly deploy check to Follow-up · 12-31 23:59 while its sibling still carried the genuine generated name Nightly deploy check · 09-02 06:52, and the whole group header became "Follow-up" — first-wins hands the header to the rename precisely because the rename sorts first after being touched. A "most common generated title wins" rule would have kept Nightly deploy check. Not a blocker; either pin the current rule with a test or consider the majority rule.

F4 — two tasks with the same title render two identical headers (nit)

Two distinct scheduled tasks both named Review PRs produce two adjacent Review PRs · 1 / Review PRs · 3 groups (visible in Fig 1). Grouping is correct — they are different taskIds and collapse independently — but there is nothing on screen to tell them apart.

F5 — ChatEditor.test.tsx duplicates an upstream fix (nit)

868683029a removes the duplicate language binding, which main already fixed in 5282abea22 (#10729). Harmless — the trial merge resolves it cleanly — just expect that hunk to vanish on rebase.

F6 — isScheduledTaskSession narrows for an empty task id (informational)

Base treated sourceId === "scheduled_task_run:" as a scheduled-task session (row clock icon); the new getScheduledTaskSessionGroup rejects it. generateCronTaskId() never returns an empty id, so this is unreachable through the daemon — noting it only because the helper is now the single source of truth for two different questions.

On the }, 15000) timeout bumps

Checked that they are not masking a slowdown introduced here: SessionOverviewPanel.test.tsx runs 3.52 s of test time on merge-base sources and 3.55 s on the PR head (96 tests, same file, same machine), and all three bumped tests pass locally with the bumps removed. They read as pure CI-load insurance.

(Unrelated, for whoever owns it: prettier --check packages/web-shell fails on 5 files that this PR does not touch — 4 .module.css plus client/index.html.)

中文版报告

本地验证 —— 真实 qwen serve daemon + Chromium 中的真实 Web Shell

以维护者身份在 head 868683029a 上验证(merge-base b27deb634d,当前 main61697df9b0),Linux,Node 22.22.2。

结论:建议合并。 PR 描述中的每一条主张都在真实 daemon 上端到端复现,没有发现功能缺陷。但有 一个测试覆盖缺口希望补上(F2),另外这个 PR 顺带修复了一个既有的信任门 UX bug,值得在描述里写一句(F1)。

验证方式(不是 jsdom)

packages/web-shell 做了两份 vite build:一份是 PR head,另一份只把改动的 6 个源文件回退到 merge-base。两份产物分别换入同一个 qwen serve 二进制的 dist/web-shell,因此两个对照组的 daemon 完全一致。会话数据也是真实的:由活跃 daemon 创建 sessionMode: "per_run" 的持久化定时任务,并通过 POST /scheduled-tasks/:id/run 触发,因此每一个 scheduled_task_run:<taskId> 来源标识和每一个 <title> · MM-DD HH:mm 展示名都由 scheduledTaskRunSessionName 真实生成,而非手工构造。共 6 个任务 / 11 个运行会话 / 2 个工作区 / 1 个未受信任的次级工作区。

结果

# 主张 结果
1 同一任务的多次运行按任务标题归组(主工作区) ✅ 图 1 —— 3 个任务成功归组;改动前是一个平铺列表,被 5 行上限 + "Show all" 截断
2 次工作区同样生效(WorkspaceSection ws2 的 2 次运行归为一组,普通会话仍在 Ungrouped
3 不依赖 session_organization 能力 ✅ 图 2 —— 在网络层剥离该能力后,手动分组/颜色分组消失(证明开关确实翻转了),定时任务分组仍在
4 手动颜色与命名分组优先级更高 ✅ 图 3 左 —— "Green" ·1 与 "Release triage" ·2 保住成员,自动分组降到 ·1
5 分组头用时钟图标而非颜色点 ✅ 存在 [data-web-shell-scheduled-task-group],无 sessionGroupDot
6 折叠/展开与持久化 ✅ id 与注释完全一致:scheduled-task:839s5f8pws:f37e922f499c81d3|group:scheduled-task:8f3362wz;刷新后保持
7 标题 = 任务标题去掉运行时间后缀 ✅ 含生产端截断(Reconcile the nightly artifact manifests acro…)以及标题本身以日期结尾的情况(Snapshot · 01-02 03:04
8 缺失 displayName 时回退到任务 id ✅ 分组头显示 alm3h5hv(与无名会话行的既有渲染方式一致)
9 侧边栏搜索 ✅ 只有命中的运行会形成分组,计数同步调整

仓库层面检查(在该 head 上):packages/web-shell 单测 5589/5589 通过,tsc --noEmit 干净,改动文件 eslint 干净,test:e2e:smoke47/47 Playwright 用例本地全过(含 web-shell.collapsed-groups-persist.spec.ts)。与当前 main 试合并无冲突;在合并后的树上重建 sdk-typescriptweb-shell 后,5642/5642 通过且类型检查干净。

关于两个红色 CI: 都是基础设施问题,与本 PR 无关。web-shell E2E Smoke 的日志结尾是 The runner has received a shutdown signal … The operation was canceledTest (ubuntu-latest) 状态是 cancelled(2 小时上限),日志中唯一真实失败是 packages/core/src/hooks/hook-runner.process.test.ts,与 web-shell 无关。两套用例在本地该 head 上都能通过。

F1 —— 本 PR 还修复了一个既有的信任门 bug,建议在描述里说明

WorkspaceSection.groupedSessions 新增了 if (channelGroupingEnabled || readOnly) return null;。这不只是防御性写法:在 merge-base 上,一个未受信任的次级工作区只要存在任意手动会话分组,其会话就会走分组分支,而该分支没有信任门 —— 行渲染为 role="button",点击会发出 POST /session/:id/load 并返回 403 Workspace is not trusted,留下一个红色 toast 和一个走不通的会话视图。应用本 PR 后,同样的行恢复为 role="note" / "Trust this workspace to open the session",并且完全不会发请求(图 4)。

daemon 侧一直是强制校验的,所以这属于 UX 缺陷而非数据泄露;但它是 PR 声明范围之外的用户可见修复,而 "Risk & Scope" 目前写的是改动仅限于归组。建议补一句(如果有对应 issue,也可以加 Fixes #…)。

F2 —— WebShellSidebar 的优先级顺序完全没有测试覆盖(唯一希望补上的点)

WorkspaceSectionkeeps a manually grouped scheduled-task run under its manual group 这条用例;WebShellSidebar 没有对应用例,而它的分桶顺序正是优先级得以成立的原因。我对 PR 自己的生产代码做了两个变异:

  • M7 —— 把 collectScheduledTaskSession(...) 移到 session.groupId && validGroupIds.has(...) 分支之前;
  • M11 —— 让定时任务运行跳过颜色分支。

两者都让四个被改动测试文件的 174/174 全绿,但界面明显坏掉:"Green" 颜色分组整个消失,"Release triage" 从 2 个成员掉到 1 个,成员被自动分组吞掉(图 3 右 —— 那一栏是变异源码的真实构建产物,跑在同一个 daemon 上)。

建议:在 WebShellSidebar.workspace-removal.test.tsx 里加一条用例,构造一个带 color 的运行会话和一个带 groupId 的运行会话,断言它们出现在颜色/手动分组里,而不在 section[aria-label="<任务标题>"] 中。

作为参考,我跑的 12 个变异体中 9 个被杀死:M1 sourceType 守卫、M2 空 taskId 守卫、M3 label || taskIdM4 后缀剥离、M6 永不收集、M8 readOnly 门、M9 恢复 org-disabled 早退、M10 图标插槽、M12 assigned 判断。新模块自身的覆盖是好的,只有侧边栏的优先级顺序没有防护。

F3 —— "首个生成名优先" 的守卫没有测试固定,而且在真实场景下选出了更差的标题(次要)

删掉 !section.sessions.some(hasGeneratedRunName)(变异体 M5)同样保持 174/174 全绿。此时代码里已记录的"按形状判定"限制会以测试看不到的方式发作:我把 Nightly deploy check一次运行重命名为 Follow-up · 12-31 23:59,而它的兄弟运行仍保留真正的生成名 Nightly deploy check · 09-02 06:52,结果整个分组头变成了 "Follow-up" —— 因为重命名会刷新时间戳而排到最前,首个优先就把标题让给了它。若改成"出现最多的生成标题优先",则会保留 Nightly deploy check。这不是阻塞项;要么用一条测试把当前规则钉住,要么考虑改成多数规则。

F4 —— 两个同名任务会渲染出两个一模一样的分组头(吹毛求疵)

两个不同的定时任务都叫 Review PRs 时,会产生相邻的 Review PRs · 1Review PRs · 3 两个分组(图 1 可见)。归组本身是正确的 —— 它们是不同的 taskId,折叠状态也各自独立 —— 但界面上没有任何可区分的信息。

F5 —— ChatEditor.test.tsx 与上游修复重复(吹毛求疵)

868683029a 移除了重复的 language 绑定,而 main 已经在 5282abea22#10729)修过。无害 —— 试合并能干净解决 —— 只是 rebase 后这个 hunk 会消失。

F6 —— isScheduledTaskSession 对空任务 id 的判定收窄了(仅供参考)

改动前 sourceId === "scheduled_task_run:" 会被判定为定时任务会话(行上带时钟图标),新的 getScheduledTaskSessionGroup 则拒绝它。generateCronTaskId() 不会返回空 id,所以通过 daemon 无法触达;提一句只是因为这个 helper 现在同时承担了两个不同问题的判定职责。

关于 }, 15000) 超时上调

已确认这些上调没有掩盖本 PR 引入的变慢:SessionOverviewPanel.test.tsx 在 merge-base 源码下测试耗时 3.52 s,在 PR head 下为 3.55 s(同一文件 96 条用例,同一台机器),并且把三处上调全部移除后本地依然全过。它们读起来就是纯粹的 CI 负载保险。

(与本 PR 无关,供相关同学参考:prettier --check packages/web-shell 在 5 个本 PR 未触及的文件上失败 —— 4 个 .module.cssclient/index.html。)

@wenshao

wenshao commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

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

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

Scripted assertions: 6005 passed · 0 failed · 6005 total

Flakiness gate: ✅ 6 changed test file(s) x 5 identical rounds, no divergence

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

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

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

抖动门:✅ 6 changed test file(s) x 5 identical rounds, no divergence

Verification report

PR #10611 Deep Verification — feat(web-shell): group scheduled task run sessions

Verdict: merge-ready — 6005/6005 scripted assertions passed (0 unexpected failures). Verified head: 868683029afb8a6050daf845b4d5390f55b00db3 (git rev-parse HEAD^2), merged over base tip 24b53add508913ad149392b87def2bd7594b1f08.

中文摘要
  • 结论merge-ready。6005/6005 脚本化断言通过,无意外失败。
  • A/B 结论:核心改动经证实为承载性(load-bearing)。同一场景同一 harness:head 构建把同一调度任务的两次运行归入一个以任务标题命名、带时钟图标的分组(无需 session_organization 能力,主/次工作区均生效);base 构建渲染为平铺列表(见 01-ab-head-grouped.png02-ab-base-flat.png)。手动颜色/命名分组优先级在两侧均保留。
  • 交叉验证:PR 新增测试在 base 源码上按预期变红 3 例(缺失分组/图标,断言为行为性失配);base 既有套件(51 + 110 例)在 head 源码上全部通过,无附带回归。7 个变异矩阵单元全部 KILLED,阳性对照存活验证套件有效。
  • 附加发现:base tip 的 ChatEditor.test.tsx 因重复 language 绑定无法编译(esbuild 报 "The symbol language has already been declared"),本 PR 顺带修复,head 全套 5628 通过。
  • Findings(均不阻塞):N1 后缀-only 显示名的标签回退边缘(外观级);N2 "折叠后重新展开自动分组" 的评审验证步骤无测试钉住(覆盖缺口,Suggestion)。
  • 未覆盖:逐提交归因(shallow 深度 2,本地仅可达 1/11 提交);Windows/Linux 视觉渲染;真实 daemon + Playwright 的端到端截图复现;main 试合并。

Scope selection

Central claim: sessions created by per-run scheduled-task fires (sourceType: 'default', sourceId: 'scheduled_task_run:<taskId>') are automatically grouped into one virtual section keyed by task identity, labeled with the task title (the generated · MM-DD HH:mm suffix stripped), headed by the clock icon — in both the primary sidebar catalog and secondary workspace sections, without requiring the session_organization capability.

Secondary claims (verified):

  1. Manual organization keeps precedence: color buckets and named groups retain their members; the automatic section only collects unassigned runs (and only renders color sections while organization is enabled).
  2. The first-sync latch handling stays correct when the organization capability lands after an org-disabled scheduled-task settle, including while the Channels tab is selected (the two new "registers manual groups as initial" behaviors).

Out of scope (listed under Not covered): visual rendering, per-commit attribution, E2E browser reproduction, trial merge into current main.

A/B: central claim is load-bearing

Environment: head tree = CI merge-ref checkout at 8601b9c5; base tree = scratch worktree at HEAD^1 (24b53add), sharing the root node_modules. Realpath check: readlink -f node_modules/@qwen-code/sdkpackages/sdk-typescript in the head tree — but every @qwen-code/* import in the harness closure is type-only (erased by esbuild), verified per file (WorkspaceSection.tsx, daemon-react-sdk.ts carry no runtime cross-package imports), so the base arm loads only base-tree sources. The vitest RUN line of each arm names its root tree, and the base arm's flat-render assertions would fail if head code leaked in.

Harness harness/zz-verify-ab.test.tsx (run unmodified on both arms, arm selected by VERIFY_ARM): two runs of scheduled_task_run:task-1 (Review PRs · 08-31 09:30, Review PRs · 08-31 08:30) plus one ordinary session, rendered through WorkspaceSection with a fake DaemonClient.

cell build scenario observable oracle result
A-head head org disabled section[aria-label="Review PRs"] exists, carries data-web-shell-scheduled-task-group icon, contains both run titles, no color dot; ordinary session under Ungrouped 2/2 pass
A-base base org disabled no such section, no icon attribute, 3 flat rows 2/2 pass (base is flat, as predicted)
B-head head org enabled, run-1 in manual group My group My group keeps run-1 only; run-2 forms the automatic Review PRs section pass
B-base base same My group keeps run-1; run-2 spills into Ungrouped; no automatic section pass

Witnesses: 01-ab-head-grouped.png, 02-ab-base-flat.png. Logs: logs/ab-head.log, logs/ab-base.log.

Cross-arm oracle sensitivity (the PR's own new tests executed against the other arm's source):

run source under test result
head WorkspaceSection.test.tsx + SessionGroupSection.test.tsx on base source base 3 red, 55 green — exactly the two central grouping tests and the icon test fail, each on the intended assertion (expected null not to be null at the missing section[aria-label="Review PRs"] / icon — quoted in logs/head-tests-on-base.log). The other two new tests (manual-group precedence, untrusted read-only) pass on base too: they pin preserved invariants, not the delta.
head scheduled-task-session-groups.test.ts on base source base collection fails: the module does not exist on base (expected for a new file)
base WorkspaceSection.test.tsx on head source head 51/51 pass — no collateral on the secondary surface (logs/base-tests-on-head.log)
base WebShellSidebar.workspace-removal.test.tsx (110 tests incl. the old flat-icon oracle) on head source head 110/110 pass — all prior primary-surface expectations hold; the old flat-icon test still holds because grouping adds a section around the row without removing the row-level source icon (logs/base-sidebar-tests-on-head.log)

Wire oracle: producer ↔ client label round trip

harness/roundtrip.mts drives the real producer scheduledTaskRunSessionName (packages/cli/src/runtime/scheduled-task-run.ts) as the oracle for the client parser: 11 task titles (unicode, astral-at-cut-boundary, titles containing ·, titles already ending in a suffix shape, truncation-boundary lengths 46/47/100, whitespace-heavy) × 4 trigger dates (single-digit fields, leap day, year end), 3 assertions each: group identity, label recovery against the fixed-length oracle (the producer suffix is a constant 14 chars, so label === name.slice(0, -14)), and separator code points (U+0020 U+00B7 U+0020, matching the client regex byte-for-byte). Plus classification boundaries (channel sourceType, empty task id, colon-laden ids, blank names), label-preference ordering with real producer names, and a 2 k/3 k/5 k/20 k hostile-name ladder.

146/146 pass; ladder timings flat (0.007–0.016 ms per parse, no superlinear growth — the pattern is fixed-length, input is daemon/user-authored, not cross-trust-boundary). Witness: 03-roundtrip-producer-oracle.png, log logs/roundtrip.log.

The client-side mirror constant scheduled_task_run: matches packages/acp-bridge/src/session-source.ts exactly; the producer zero-pads every field, so the \d{2} classes always match producer output.

Mutation matrix (no survivors)

Every guard the PR introduces was reverted/crippled in a scratch edit, the pinned suite run, and the edit reverted (harness/mutation-matrix.sh; witness 04-mutation-matrix.png, log logs/mutation-matrix.log):

mutation guard under test suite result verdict
M1 disable collection in WorkspaceSection secondary-surface grouping 2 red / 6 green KILLED
M2 remove generated-title preference label stability vs renames 2 red / 4 green KILLED
M3 break suffix-regex separator suffix stripping 3 red / 3 green KILLED
M4 restore org-disabled early return in sessionSections primary-surface grouping 2 red KILLED
M5 remove latch re-arm organized settle after org-disabled settle 2 red (both latch tests) KILLED
M6 remove source-switch gate Channels→Tasks settle race 1 red / 1 green (channel test only) KILLED
C1 break source-id prefix (positive control) 5 red / 1 green KILLED (suite live)

M5/M6 separate cleanly: the re-arm is required by both latch scenarios, the source-switch gate only by the channel one — two load-bearing guards, not redundant defence. Every red quoted was the intended behavioral assertion (e.g. missing section[aria-label=…]), never an import/compile break.

Targeted gates (head)

gate result
npm run test@qwen-code/web-shell, 251 files 5628/5628 pass (logs/gate-web-shell-head.log, witness 05-gate-web-shell-head.png)
npm run typecheck pass (logs/gate-typecheck.log)
npm run lint pass (logs/gate-lint.log); liveness proven: a planted unused variable in scheduled-task-session-groups.ts was reported, then reverted

Base-tip note: at HEAD^1, ChatEditor.test.tsx fails to even collect — esbuild: The symbol "language" has already been declared (duplicate destructuring binding). The PR's final commit removes the duplicates; at head the file's tests run green inside the 5628.

Findings

N1 — suffix-only display names keep a · 08-31 09:30 label instead of the taskId fallback (cosmetic, non-blocking). getScheduledTaskSessionGroup trims the display name first, so a name that is exactly the generated suffix ( · 08-31 09:30) loses its leading separator space, the strip regex no longer matches, and the non-empty remainder · 08-31 09:30 becomes the group label instead of falling back to the task id. Reachability is narrow: the producer emits this shape only when the cleaned title part is empty — a task whose prompt consists solely of control/bidi characters still passes the route's non-empty-after-trim() prompt validation (scheduled-tasks.ts), or a user renames a run into this shape. Grouping itself is unaffected (keyed by task id); only the header text is odd. Pinned as actual behavior in the round-trip harness ("pinned edge" check). A one-line fix would strip the suffix before trimming, but given the producer's cleanMetadataLine contract this is a nit.

N2 — Reviewer Test Plan step "collapse and re-expand the automatic group" is not pinned by any test (Suggestion). No test toggles a scheduled-task section collapsed and back, on either surface. The persistence machinery itself is shared and pinned for other section kinds (collapsedSessionSections helpers + existing collapse tests), and the section id (scheduled-task:<taskId>) is asserted by the render tests, so the untested link is only the toggle wiring. Per house rules, a missing test for changed behavior is a Suggestion, not a blocker.

Observation (not a finding): on the primary surface a brand-new task section appearing mid-session starts collapsed (the established "new sections mid-session start collapsed" semantics, shared with manual groups), while WorkspaceSection sections default to expanded. Consistent with pre-existing behavior for manual groups; noted for awareness only.

Not covered

  • Per-commit attribution: checkout is depth 2; git rev-list HEAD^1..HEAD^2 returns 1 against 11 commits in the metadata snapshot (shallow boundary), so the 10 intermediate commits (review fixes, deflakes, two main-merges with conflict resolutions) were not individually exercised. The aggregate HEAD^1..HEAD diff is what was verified.
  • Visual rendering (icon alignment, CSS): jsdom assertions cover DOM structure and class/attribute presence; pixel output on macOS/Windows/Linux was out of reach (no browser in the artifact contract).
  • End-to-end reproduction with a real daemon + Playwright (the PR's own validation method): this round reproduced the shape (component-level rendering from the same sourceId/displayName wire fields the daemon serves, validated against the real producer function), not the trigger path (daemon session creation → polling → sidebar).
  • Trial merge into current main: no network/token in this environment; base tip could not be compared against today's main.
  • Other packages' test suites: the diff touches packages/web-shell only, so no other workspace gate was run.
  • SessionOverviewPanel.test.tsx / WebShellSidebar.workspace-removal.test.tsx timeout bumps (}, 15000)): deflake-only changes; verified by inclusion in the green gate, not re-measured under load.

Methodology

CI verify container (node:22-bookworm, Node v22.23.2), npm ci + npm run build pre-run at the merge commit 8601b9c5. Head tree = the checkout itself; base tree = git worktree add tmp/base-tree HEAD^1 (removed after the A/B). A/B harnesses were vitest test files copied unmodified into both trees' client/components/sidebar/ and run under each tree's own vitest config (jsdom, real React 19 createRoot, no mocks of code under test — only the daemon client is faked, per the suite's own convention); the round-trip harness ran the real producer and client modules through tsx. Mutations were applied as scratch edits and reverted via git checkout (final git status clean, 0 dirty files). Raw per-cell logs live in logs/, harnesses in harness/, terminal witnesses in evidence/ (captured via scripts/verify-capture.mjs).

Flakiness gate log

rounds=5 files=6 skipped=0
file packages/web-shell/client/components/ChatEditor.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/ChatEditor.test.tsx
file packages/web-shell/client/components/SessionOverviewPanel.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/SessionOverviewPanel.test.tsx
file packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/sidebar/SessionGroupSection.test.tsx
file packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx
file packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: (cd packages/web-shell) npx --no-install vitest run ./client/components/sidebar/WorkspaceSection.test.tsx
file packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: (cd packages/web-shell) npx --no-install vitest run ./client/components/sidebar/scheduled-task-session-groups.test.ts


per-file results (P=pass F=fail I=infra-exit, one letter per run):
  packages/web-shell/client/components/ChatEditor.test.tsx: PPPPP
  packages/web-shell/client/components/SessionOverviewPanel.test.tsx: PPPPP
  packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: PPPPP
  packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: PPPPP
  packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: PPPPP
  packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: PPPPP

verdict: pass
summary: 6 changed test file(s) x 5 identical rounds, no divergence

--- per-invocation detail (full copy in the artifact) ---
round 1 · packages/web-shell/client/components/ChatEditor.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/SessionOverviewPanel.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: P (exit 0)
round 1 · packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: P (exit 0)
round 2 · packages/web-shell/client/components/ChatEditor.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/SessionOverviewPanel.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: P (exit 0)
round 2 · packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: P (exit 0)
round 3 · packages/web-shell/client/components/ChatEditor.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/SessionOverviewPanel.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: P (exit 0)
round 3 · packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: P (exit 0)
round 4 · packages/web-shell/client/components/ChatEditor.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/SessionOverviewPanel.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: P (exit 0)
round 4 · packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: P (exit 0)
round 5 · packages/web-shell/client/components/ChatEditor.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/SessionOverviewPanel.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/sidebar/SessionGroupSection.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/sidebar/WebShellSidebar.workspace-removal.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/sidebar/WorkspaceSection.test.tsx: P (exit 0)
round 5 · packages/web-shell/client/components/sidebar/scheduled-task-session-groups.test.ts: P (exit 0)

Evidence images

01-ab-head-grouped

02-ab-base-flat

03-roundtrip-producer-oracle

04-mutation-matrix

05-gate-web-shell-head

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

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot's only review on 868683029afb8a6050daf845b4d5390f55b00db3 is a COMMENTED one, which carries no vote — so it has no verdict of its own on this commit, and main needs two approving reviews: an approval left by another account is a separate vote and does not count as the bot's own. Two different things look like this, and the stage-3 comment above says which: the triage skill deferring on purpose at 3/5 — a fork refactor hitting the approval guardrail, or a core change escalated for maintainer awareness, both normal outcomes — or an earlier approval that a push dismissed, leaving only the comment behind, which needs a fresh review.

⚠️ 机器人在 868683029afb8a6050daf845b4d5390f55b00db3 上唯一的评审是 COMMENTED不带票 —— 因此它在该 commit 上没有自己的裁决,而 main 需要两个批准(其他账号的批准是另一张票)。有两种情况长这样,上方的 stage-3 评论会说明是哪一种:triage skill 在 3/5 时有意 defer(fork refactor 命中审批护栏,或核心改动被升级交由维护者把关,两者都是正常结果);或者更早的批准被一次推送作废、只剩下这条评论,此时需要重新评审。

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

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

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed at head 868683029a.

  • The round-1 Critical (auto-collapse consuming the initial-catalog latch against a stale pre-organized list when organizationEnabled flips mid-session) is fixed: the flip now re-gates during the same render and re-arms the default-source latch so the first organized settle registers scheduled-task sections as initial instead of collapsing them — pinned by the new workspace-removal test.
  • The grouping helper is a well-bounded pure module: membership keys off the structured sourceId prefix (not display text), the mirrored producer constants are documented with their source files and the known rename-shape collision is called out with its consequence, and label precedence favors generated run names over renames deterministically.
  • 12/12 threads resolved; the remaining review rounds' Suggestions were addressed in 17e6808e. No new Critical issues found. CI on this head has no failures; per the channel convention the call is on the review itself.

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review passed.

  • Grouping identity is server-derived (sourceType + sourceId prefix), not name guessing; the label-recovery regex for generated run names carries an explicit documented limit (a user rename shaped like a run name is classified generated) and the label-stability logic (generated-name preference, first-wins among generated) prevents header flipping when catalog order shifts.
  • The sidebar changes keep the right guards: color sections stay gated on organizationEnabled, the grouped branch in WorkspaceSection falls back to the flat read-only rows for untrusted secondaries (no trust gate needed in the grouped branch itself), and the collapse-state id convention is documented for scheduled-task sections.
  • The first-sync latch handling is the subtle part and it is handled: org-disable settle re-arms the default source, and switching Channels→Tasks closes the catalog gate in the same render so the settle cannot consume the latch against the emptied group catalog.
  • Removal/rename across groups, search interplay, and the org-disabled path all have dedicated tests; the module's own grouping tests cover prefix/suffix/label edge cases.

CI: ubuntu Test green; the web-shell E2E Smoke failure is the known main-level flake (no assertion failure in the log), seen across recent PRs.

@qqqys
qqqys added this pull request to the merge queue Sep 2, 2026
Merged via the queue into QwenLM:main with commit d5ac66d Sep 2, 2026
118 of 122 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.23.0.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants