Repository navigation
Conversation
E2E verification reportVerified on macOS with Node.js 22.22.2 and Chromium. Mode-selection screenshots in the PR body come from actual browser runs with mocked daemon requests. The additional first-message initialization screenshot uses the changed local Web Shell with a real isolated Qwen Code 0.25.0 daemon.
Browser command, from PLAYWRIGHT_PORT=5190 npx playwright test client/e2e/web-shell.git-mode.spec.ts --project=chromium --workers=1The original six-scenario browser suite verifies UI state and the outgoing request contract. An additional real-daemon initialization test now verifies actual Git worktree creation and session ownership. Model execution was not tested. Root build, typecheck, and bundle did not pass because the existing installation is missing email/A2A dependencies and contains stale bridge build output. No new CLI bundle was produced. The PR body includes the real Before/After screenshots hosted on Pre-commit review: two consecutive open-ended/adversarial audit rounds found zero Critical and zero Suggestion issues. Four additional adversarial browser cases passed: keyboard selection with prefilled text does not submit early, both branch/Worktree transitions clear the other mode, and escaping an invalid unconfirmed branch preserves the selected intent correctly. Each case rechecked exactly one session creation request after the prompt request. Additional first-message initialization evidenceReal initialization screenshot is embedded at the start of the PR description’s English and Chinese evidence sections. The test passed 1/1 in 8.2 seconds: while the real creation request was still pending, the first input remained visible and the send button showed Loading and was disabled. There was no artificial response delay. The daemon then returned HTTP 200 with persisted ownership; the actual directory, Git registration and branch, owner marker, and daemon session association all matched. Zero prompt/generate/recap requests were sent. The isolated daemon was stopped afterward. Review follow-up verificationReview follow-up adds two real-component tests to the existing PR unit-test gate and links the superseded confirmation behavior in both design languages. Both requested mutations were rejected by the new tests: the old pending-only click fails the intent callback assertion, and resetting the selection on reopen fails the checked-state assertion. Unchanged controls passed 18/18 before and after. Two further pre-commit audits (round 3 open-ended and round 4 adversarial) were clean; the adversarial rerun also passed 18/18 with unhandled-error ignoring explicitly disabled. Only tests and the bilingual design documentation changed in this follow-up; the browser and real-daemon screenshot evidence above remains from the unchanged product implementation. Web Shell build/typecheck, changed-file ESLint/Prettier and whitespace checks passed again. Root build/typecheck remain blocked by the existing dependency/build-output problems described above. |
|
⏳ Approval still deferred — 1 PR CI workflow run(s) still in progress for ⏳ 审批仍在延迟中 —— |
|
Thanks for the PR! Template looks good ✓ — every required section filled in, both languages, before/after evidence attached. Problem: real, and confirmable from the code rather than taking the description's word for it. Direction: aligned. One click is already the norm on this surface — the Worktrees manager path creates a new session with a worktree intent directly and no confirmation, and the "Current branch" option in this same popover commits immediately. Worktree was the odd one out, and it was odd in the direction of extra friction. No direct reference in the upstream Claude Code CHANGELOG to a git-mode selector confirmation; worktree isolation is a heavily worked area there, so the surface itself is clearly relevant. Size: not applicable — no core paths are touched (all six files are Web Shell client or Approach: close to the minimal edit, which is what I'd have written from the title alone — drop the button, drop its now-orphaned styles and the two translation keys, rename the handler to say what it does, and fix the description copy so it states when the copy is created. Turning the clear-button test into a two-mode loop is assertion-preserving: every branch assertion survives, and the worktree path gains coverage plus a "no session request before send" check. No drive-by refactors or unrelated churn ride along. Design doc is present in both languages with matching sections and reciprocal links. Risk: no elevated risk signals — none of the changed files match the revert-correlated high-risk paths. The component has exactly one consumer (the composer), and it only renders while the workspace is git-eligible and no session is loaded, so the blast radius is the empty-session composer. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ —— 各必填章节齐全,中英文对照,附有改动前后证据。 问题: 真实存在,并且可以直接从代码验证,而不必只信描述。原来的 方向: 对齐。这个界面本来就是一次点击生效——Worktrees 管理入口新建会话时直接带上 worktree 意图、不需要确认;同一个弹层里的「当前分支」选项也是点击即生效。Worktree 是唯一的例外,而且例外的方向是增加多余操作。上游 Claude Code 的 CHANGELOG 没有关于 git 模式选择器二次确认的直接条目,但 worktree 隔离在上游是持续投入的领域,说明这个界面本身是相关的。 规模: 不适用——未触及核心路径(6 个文件全部属于 Web Shell client 或 方案: 基本就是最小改动,也正是只看标题时我会写的方案——删掉按钮、删掉随之失效的样式和两条翻译、把处理函数改成能说明行为的名字、并把说明文案改成明确「何时」创建副本。把清除按钮的测试改成两种模式的循环是保留断言的写法:分支相关断言一条没少,同时补上了 worktree 路径,还新增了「发送前不发创建请求」的检查。没有夹带无关重构或格式抖动。设计文档中英双语齐备,章节对应、互链完整。 风险: 无升级风险信号——改动文件均未命中与回滚相关的高风险路径。该组件只有一个使用方(输入区),且仅在工作区可用 Git、尚未加载会话时渲染,影响面就是空会话输入区。 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewNo Critical blockers and no AGENTS.md violations. This is a removal, so most of the review is proving nothing was left behind and nothing else depended on what went away — I could settle both statically. The premise checks out in the code, not just in the description. The deleted handler only recorded The removal is complete. A repo-wide search for the deleted translation key, the
Reversibility is real, and now tested. The ✕ reset renders for both branch and worktree intents, unchanged, and the rewritten spec drives it for worktree. Consumers, named. The composer is the only renderer of this component, and App only wires the intent props while the workspace is git-eligible and no session is loaded; the intent is reset on session start and workspace switch and read exactly once, at first-prompt session creation. Nothing else reads the removed key or test id. The tests come out stronger, not weaker. The worktree test trades a "the confirm button stayed visible for 300 ms" guard for assertions on the thing that actually matters: the chip reads Worktree, no Design docs meet Two non-blocking notes, take them or leave them:
TestingThis was an unattended CI run, so nothing in the PR was built or executed here — the evidence below is the PR's own CI, read through the API for the reviewed commit, plus static reading of the diff against the surrounding code. CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 No check is red, so there is no failure log to excerpt. Reading the green ones for what they actually cover: The changed browser specs do not run in this PR's CI. The CI browser job runs the smoke lane ( Sandboxed verification would settle it: 中文说明代码审查无 Critical 阻塞项,也没有违反 AGENTS.md 的地方。这是一次「删除」型改动,审查重点在于证明没有遗留、也没有别处依赖被删掉的东西——这两点都可以静态确认。 前提在代码里成立,不只是描述里的说法。 被删掉的处理函数只记录 删除是干净的。 全仓搜索被删的翻译键、
可撤销是真实的,并且现在有测试覆盖。 ✕ 重置按钮在 branch 和 worktree 两种意图下都会渲染,逻辑未变,改写后的用例对 worktree 走了这条路径。 下游使用方已点名。 该组件只有输入区一个渲染方,App 只在工作区可用 Git 且未加载会话时接入意图 props;意图会在会话开始和工作区切换时重置,并且只在首条消息创建会话时读取一次。没有其他地方读取被删的键或测试 id。 测试变得更强,而不是更弱。 worktree 用例把「确认按钮在 300ms 内仍可见」的守护换成了真正关键的断言:chip 显示 Worktree、仅选择模式时没有发出 设计文档符合 两点非阻塞建议,取舍随意:
测试本次为无人值守的 CI 运行,因此没有构建或执行 PR 中的任何代码——下面的证据来自通过 API 读取的该提交自身 CI 结果,以及对 diff 与周边代码的静态阅读。 CI 表格见上方标记区域:审查时 0 个失败, 本 PR 改动的浏览器用例不会在 CI 中执行。 CI 的浏览器任务只跑 smoke 通道( 沙箱验证可以把这件事定下来: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 4/5 — clean, minimal removal whose premise I could verify in the code; the only reservations are about test reach, not about the change. Stepping back: this is the rare UI PR where the diff is smaller than the justification. My own independent read of the title and the "why" was exactly what landed — make the Worktree option behave like the Current-branch option next to it, delete the button that never did what its label claimed, and correct the copy so it says when the isolated copy appears. There was no simpler version of this that I could find, and no scope to cut: 38 production lines, all of them deletions or a renamed handler, plus the copy and the tests that had to follow. What convinces me it's right rather than just tidy: the second click was not a safety confirmation, it was a label lying. Nothing behind that button created a worktree; creation has always happened on the first message, and the Worktrees manager already starts a worktree draft in one click without anyone worrying about mis-selection. Reset before sending covers the accidental-click case and is now tested for worktree, which is the one real risk the design doc names. Six months from now this reads as "the selector has three options and all three behave the same way" — that's a maintenance win, not a debt. Where I'd hold back a point: the tests that prove the behaviour are the ones CI doesn't run. The rewritten specs are genuinely better than what they replace — asserting one CI is still running on the reviewed commit — 中文说明Confidence: 4/5 —— 改动干净、范围最小,前提可以在代码里直接验证;保留的一点意见针对测试覆盖面,而不是改动本身。 退一步看整体:这是一个 diff 比论证还短的 UI PR。只看标题和「为什么需要」,我自己会写的方案与最终落地的完全一致——让 Worktree 选项和旁边的「当前分支」选项行为一致,删掉那个名不副实的按钮,并把文案改成说明独立副本何时创建。我找不到比这更简单的写法,也没有可裁的范围:38 行生产代码,全是删除或一个改名的处理函数,其余是文案和必须跟随的测试。 让我认为它是「对的」而不只是「整洁」的关键在于:那第二次点击并不是安全确认,而是一个说谎的按钮标签。按钮背后没有任何东西创建 worktree;创建一直发生在首条消息发送时,而 Worktrees 管理入口本来就是一次点击直接进入 worktree 草稿,也没人因此担心误选。发送前的重置控件覆盖了误点场景,并且现在对 worktree 有了测试——这正是设计文档点名的唯一实质风险。半年后再看,这段代码读起来就是「选择器有三个选项,三个行为一致」,是维护上的收益而不是负担。 扣掉一分的地方在于:真正证明行为的用例恰好是 CI 不跑的那些。改写后的用例确实比原来更强——断言只有一个携带 审查时该提交的 CI 仍在运行—— — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterFull-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
Maintainer verification — PR #13607:
|
| Cell | Build | Spec | Result |
|---|---|---|---|
| Head | 8b2d319a5ab6 |
PR version | 6/6 passed (18.9s) |
| Base | 718ae1e6c6da |
PR version | 2 failed / 4 passed — the two worktree tests fail at expect(popover).not.toBeVisible() (the popover stays open awaiting the deleted confirm button); branch, default, clear-branch and non-git tests pass |
| Symmetry | 8b2d319a5ab6 |
Base version | Old worktree-confirm test fails (git-mode-confirm-worktree no longer exists) — the old flow is gone |
Witnesses: 01-ab-head-spec-green.png, 02-ab-base-spec-red.png.
Mutation check (vacuity): reverting only the onClick={handleSelectWorktree} line back to setSelectedMode('worktree') at head — keeping everything else — turns exactly the two worktree tests red (the branch-clear test stays green, correctly). The onClick hunk alone is load-bearing, and the new spec is pinned by the behavior, not by construction.
Independent harness (maintainer-written, not from the PR)
The PR description cites four adversarial browser scenarios that are not committed to the repo. I re-implemented them as an independent spec driving the head build through the same mock-daemon seam (29 scripted assertions, all passing — 03-independent-harness.png):
- Worktree → Branch: select Worktree (chip flips, zero POSTs of any kind), switch to New branch, confirm — send carries
branch, noworktree. - Branch → Worktree: confirm branch first, switch to Worktree — send carries
worktree: {}, nobranch. - Keyboard select with prefilled composer: Enter on the Worktree radio selects and closes without submitting; composer text preserved; explicit send then issues exactly one
POST /sessionwithworktree: {}. - Escape unconfirmed invalid branch: invalid name disables confirm; Escape restores current-branch mode; send carries neither key.
Real-daemon arm (head qwen serve + real Chromium)
Drove the head-built web-shell served by the head-built daemon (packages/cli/dist/index.js serve --workspace /tmp/pr13607-wt-test, isolated git repo, scratch HOME seeded with auth) in real Chromium: one click on Worktree → type → send.
- Wire: exactly one
POST /session, body{"cwd":…,"sessionScope":"thread","approvalMode":"yolo","sourceType":"default","worktree":{}}—worktree: {}present, nobranchkey; zero POST requests before the first message. - Disk:
/tmp/pr13607-wt-test/.qwen/worktrees/bright-fox-41c1e6created, registered ingit worktree list, branchworktree-bright-fox-41c1e6checked out inside it. 10/10 assertions.
Witnesses (live browser shots against the real daemon): rd-2-popover.png (new copy "Creates an isolated copy when you send your first message"; no confirm button), rd-3-selected.png (one click → chip shows Worktree with reset control), rd-4-after-send.png (session created; real model turn started).
Environment note: with a scratch HOME lacking credentials, the same flow fails at POST /session with 500 Authentication required and leaves no worktree on disk — a clean, pre-existing daemon failure mode unrelated to this PR (the PR only changes what the UI sends; the wire body was verified correct in that run too).
Gates
| Gate | Result |
|---|---|
npm run build (full monorepo, head) |
pass |
tsc --noEmit (web-shell, head) |
pass |
| web-shell full unit suite (head) | 10,907/10,907 passed (412 files) |
| git-mode targeted unit tests (head) | 20/20 (16 branch-name validation + 4 intent) |
| ESLint on changed files | pass — liveness proven: a planted unused var on the changed file was caught (exit 1), clean files exit 0 |
| Prettier on all 6 changed files | pass |
| Design docs EN/ZH | structure, decisions, constraints and acceptance criteria match; reciprocal language links present |
| Dangling-reference sweep | zero confirmWorktree references remain in web-shell |
Findings
Suggestion (non-blocking): the one-click Worktree selection has no unit-level pin. GitModePopover.test.tsx (16 tests) exercises only branch-name validation — the word "worktree" appears in neither unit test file. All behavioral coverage is e2e-only; a component-level test (click Worktree → onIntentChange({mode:'worktree'}) + popover closes) would catch a regression faster than the browser suite. The e2e coverage itself is proven load-bearing by the A/B above, so this is a test-pyramid nicety, not a gap in protection.
Not covered
- Windows / Linux (macOS only, Node 22.23.1, Chromium 1.61.1).
- Model output quality: the real-daemon arm did start a real model turn, but only session/worktree creation was asserted.
- Mobile webkit viewport of the popover.
- The branch-mode flow is covered only by the committed spec (passes at both builds) — unchanged code path.
Methodology
Two git worktrees at the exact headRefOid/baseRefOid resolved from the PR, each installed with corepack pnpm install --frozen-lockfile --ignore-scripts, with only @qwen-code/acp-bridge + @qwen-code/sdk + (head) the full monorepo built. Workspace links verified tree-local via readlink -f (no cross-tree leak). Browser suites ran via Playwright against each tree's own Vite dev server (ports 5191/5192); the base arm ran the PR's spec copied verbatim into the base tree, changing no base production code. The real-daemon arm used the head-built CLI daemon with an isolated git workspace and a scratch HOME (auth block seeded from the maintainer's settings; no secret material copied into artifacts). Raw logs: tmp/pr13607-verify-20261007-221640/ (logs-head-spec.txt, logs-base-spec.txt, serve-5196.log, evidence/).
Local verification by @wenshao's maintainer harness; evidence images hosted on the verify-pr13607-assets branch of wenshao/qwen-code.
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): "agent 4": none — I stopped at 8 of ~37 tool calls with every planned check completed..
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):"agent 4":none — I stopped at 8 of ~37 tool calls with every planned check completed.。
— qwen3.8-max via Qwen Code /review (v0.25.0)
qwen-code-review-bot
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
Not explored to full depth (tool budget reached): "agent 1d": none — every check above completed (no Budget gap: items to disclose)..
中文说明
未发现问题。LGTM!✅
未探索到全部深度(达到工具调用预算):"agent 1d":none — every check above completed (no Budget gap: items to disclose).。
— qwen3.8-max via Qwen Code /review (v0.25.0)




What this PR does
Selecting Worktree for a new Web Shell session now selects that mode and closes the menu immediately. Sending the first message uses the existing session creation flow to automatically name and create the isolated worktree. The description explains this timing, and the reset control remains available before sending.
Why it's needed
Previously, choosing Worktree required another click on “Create worktree”, although that button only recorded the pending mode and did not create anything. Removing the redundant confirmation makes the UI match the existing automatic creation behavior.
Reviewer Test Plan
How to verify
worktree: {}and nobranch.Evidence (Before & After)
Initialization after the first message — real daemon
Captured after sending the first message from the changed local Web Shell to an isolated test repository served by global Qwen Code 0.25.0. At capture time, the single real
POST /sessionrequest carryingworktree: {}was still in flight, the input remained visible, and the bottom-right send button showed its existing loading spinner and was disabled. The response was not artificially delayed; this UI currently has no separate “Initializing worktree” message or progress bar.The test passed (1/1, 8.2 seconds). The daemon subsequently returned HTTP 200 with persisted worktree ownership. The actual directory, Git worktree registration and branch, session marker, and daemon session association were verified. No prompt/generate/recap request was sent; model execution was not exercised.
Mode selection — before and after
These are screenshots captured from real browser test runs on macOS with a test workspace and intercepted daemon requests. Before uses the globally installed Qwen Code 0.25.0; After uses the changed local Web Shell source. They demonstrate the UI and request contract, not real Git worktree creation.
All images are hosted on the
wenshao/qwen-codefork’sassets/web-shell-automatic-worktree-session-20261007branch.Validation passed: six Chromium browser scenarios, a baseline screenshot check, a post-change screenshot check, 18 unit tests (16 existing branch-name cases and two real popover interaction cases), Web Shell build and typecheck, changed-file ESLint and Prettier, and whitespace checks. The browser scenarios cover one-click selection, deferred creation, exactly one outgoing creation request, both reset paths, branch selection, and non-Git visibility.
Two consecutive pre-commit audit rounds completed with no Critical or Suggestion findings: an open-ended audit followed by an adversarial audit. The adversarial audit also passed four additional browser scenarios covering keyboard selection with a prefilled prompt, branch/Worktree transitions in both directions, and escaping an unconfirmed invalid branch selection.
Review follow-up adds two real-component tests to the existing PR unit-test gate and links the superseded confirmation behavior in both design languages. Both requested mutations were rejected by the new tests: the old pending-only click fails the intent callback assertion, and resetting the selection on reopen fails the checked-state assertion. Unchanged controls passed 18/18 before and after. Two further pre-commit audits (round 3 open-ended and round 4 adversarial) were clean; the adversarial rerun also passed 18/18 with unhandled-error ignoring explicitly disabled.
Tested on
Environment (optional)
macOS, Node.js 22.22.2, Chromium Playwright, local Vite Web Shell, and mocked daemon responses. Baseline UI verification used an isolated loopback server from global Qwen Code 0.25.0.
Risk & Scope
Design: English · 简体中文. Both versions have matching decisions, constraints, and acceptance criteria.
Linked Issues
None.
中文说明
本 PR 的改动
在 Web Shell 新会话中选择 Worktree 后,立即选中该模式并关闭菜单。发送首条消息时,沿用现有会话创建流程自动命名并创建隔离 Worktree。说明文案明确了创建时机,发送前仍可通过重置控件取消选择。
为什么需要
此前选择 Worktree 后,还要再点击“创建 Worktree”,但该按钮实际上只记录待使用的模式,并不创建任何内容。移除这次多余确认,让界面与已有的自动创建行为一致。
审阅者测试计划
如何验证
worktree: {},且不含branch。证据(改动前后)
首次发送后的初始化 — 真实 daemon
当前修改后的本地 Web Shell 向全局 Qwen Code 0.25.0 管理的隔离测试仓库发送首条消息后拍摄。截图时,唯一的真实
POST /session请求携带worktree: {}且仍在处理中,输入内容仍可见,右下角发送按钮显示现有加载动画并处于禁用状态。没有人为延迟响应;当前界面尚无单独的“正在初始化 Worktree”文案或进度条。该测试通过(1/1,8.2 秒)。随后 daemon 返回 HTTP 200,Worktree 所有权已持久化。实际目录、Git Worktree 注册信息及分支、Session marker 和 daemon 会话关联均已验证。未发送 prompt/generate/recap 请求,未测试模型执行。
模式选择 — 改动前后
以下截图来自 macOS 上实际运行的浏览器测试,使用测试工作区并拦截 daemon 请求。改动前使用全局安装的 Qwen Code 0.25.0,改动后使用修改后的本地 Web Shell 源码。截图展示界面和请求契约,不代表真实 Git Worktree 创建验证。
所有图片均存放于
wenshao/qwen-codefork 的assets/web-shell-automatic-worktree-session-20261007分支。已通过的验证包括:六项 Chromium 浏览器场景、一次基线截图检查、一次改动后截图检查、18 项单元测试(16 项现有分支名校验及 2 项真实弹层交互)、Web Shell 构建和类型检查、改动文件的 ESLint 和 Prettier,以及空白检查。浏览器场景覆盖单击选择、延迟创建、仅发出一次创建请求、两种重置路径、分支选择和非 Git 工作区可见性。
提交前连续两轮审计均无 Critical 或 Suggestion:先进行无方向审计,再进行对抗审计。对抗审计还通过了四项额外浏览器场景,覆盖已输入消息时用键盘选择模式、分支与 Worktree 双向切换,以及退出未确认的无效分支选择。
评论处理补充了两项进入现有 PR 单元测试门禁的真实组件测试,并在双语设计中明确旧确认流程的替代关系。两种指定回退均被新测试拦截:旧的仅待选点击在意图回调断言处失败,重新打开时重置选择在选中态断言处失败。变异前后正常对照均为 18/18 通过。随后提交前第 3 轮无方向审计及第 4 轮对抗审计均无发现;对抗复跑显式禁用忽略未处理异常后,仍为 18/18 通过。
已测试系统
环境(可选)
macOS、Node.js 22.22.2、Chromium Playwright、本地 Vite Web Shell 和模拟 daemon 响应。基线界面验证使用全局 Qwen Code 0.25.0 启动的隔离本地回环服务。
风险与范围
设计文档:English · 简体中文。两份文档的决策、约束和验收标准一致。
关联 Issue
无。