Repository navigation
refactor(web-shell): simplify remote workspace flow - #12264
Conversation
E2E test report✅ Dedicated Chromium remote-workspace flow passed: 6/6 scenarios. Covered behaviors:
Also passed locally: root build; Web Shell typecheck, lint, and format check; 1,270 focused unit tests. |
E2E test report — independent execution at
|
| arm | commit | result |
|---|---|---|
| base | ef16196c08 |
6 passed (58.7s) |
| head | 3fdc8e473e |
6 passed (56.6s) |
Unit arm over the six test files this PR changes: Test Files 6 passed (6), Tests 262 passed (262).
Mutation witness (the arm that makes the green mean something)
A green browser run alone proves nothing, so I re-added the one line this PR deletes — rememberRemoteConnection(baseUrl) after confirmDaemonTarget(baseUrl) in StandaloneAuth.tsx, plus its import:
Test Files 1 failed (1)
Tests 1 failed | 47 passed (48)
× retries with the typed token, stores it per tab, and creates no connection
131| expect(localStorage.getItem('qwen-remote-connections')).toBeNull();
It fails on exactly the headline assertion, and only on it. Restoration was witnessed three ways rather than assumed: git diff --exit-code <head-ref> -- packages/web-shell → rc=0, git status --porcelain -- packages/web-shell → 0 lines, grep -c rememberRemoteConnection StandaloneAuth.tsx → 2 before / 0 after, and a re-run → 48 passed (48).
So "an ordinary daemon link no longer writes to the persistent connection catalog" is now independently pinned, not just asserted.
Dangling-reference census (the real risk surface of a −129-line diff)
Grepped across the whole head tree, not just the patch, because a diff against the merge base cannot show a collision main contributed:
| removed symbol | remaining references at head |
|---|---|
getRemoteWorkspaceAddStep |
0 |
RemoteWorkspaceAddStep (the type) |
0 (7 substring hits are all clearRemoteWorkspaceAddStep) |
sidebar.workspacesOnHost |
0 |
continueRemoteWorkspaceAdd / continueRemoteConnectionAdd |
0 / 0 |
.projectsHeaderRemote |
0 |
data-testid="remote-workspace-indicator" |
0 — no test or spec queries the removed node |
GlobeIcon, formatOriginHost in WebShellSidebar.tsx |
0 / 0; isPageOriginDaemon retains 4 uses, so its import stays live |
Locale parity holds: i18n.tsx declares exactly two Messages objects (EN at 18, ZH at 3998) and the key is dropped from both. Globe2Icon, the per-row badge in WorkspaceSection.tsx:25,106, is untouched — so "remote folders keep their globe marker" is true at the code level and is now also pinned at DOM level by marks each remote workspace folder / leaves local workspace folders unmarked.
No dead switch: main.tsx:464 renders <StandaloneAuth> without an onChangeTarget, so the default at StandaloneAuth.tsx:160 (onChangeTarget = navigateToDaemon) is the migrated function; StandaloneContext.Provider value={true} makes standalone a boolean, so standalone && isRemoteWorkspaceAddActive() is type-sound and behaviourally identical to the old standalone ? getRemoteWorkspaceAddStep() : undefined compared against 'browse'.
The two gaps the review named
"No test pins the fresh-tab re-prompt" — half closed, and the half that is open is not this PR's to close. main.tsx:40-43, which composes UNCONFIRMED_DAEMON_TARGET from !isKnownDaemonTarget(...) and !isRemoteConnectionKnown(...), is byte-identical at base and head (same line numbers, same text). So the fresh-tab re-prompt is caused solely by the catalog no longer being written on a gate pass — it is the intended change, and it is strictly more conservative on the trust axis. The catalog half is pinned and mutation-witnessed above; the main.tsx composition remains untested, but it is unchanged here, so that gap pre-dates this diff.
"Nothing witnesses the chip removal visually" — still true, and I could not close it either. What I can add is that the gap is narrower than it reads: the removal has a DOM-level witness in the two retained sidebar tests, and the visuals suite reporting "no screenshot changed" means no scenario renders a sidebar driven by a cross-origin daemon. That is a coverage gap in the visuals scenarios, not a defect in this diff.
CI at this commit
Lane census complete and per-lane, not read off the rollup: total_count=92 fetched=92 MATCH=True, 37 distinct lane names, zero non-green, zero incomplete. All six product lanes success — Test (ubuntu-latest, Node 22.x), Lint & Static (ubuntu-latest, Node 22.x), Integration Tests (no-AK, No Sandbox), Desktop Shell (ubuntu-22.04), Desktop Shell (windows-2022), web-shell E2E Smoke (ubuntu-latest, Node 22.x). The skipped rows (Test (macos-latest), Test (windows-latest), Integration Tests (CLI)) are event-type skips present on every PR; they are counted as their own bucket here and are not folded into "green".
One non-blocking note on the spec, not on this diff
web-shell.remote-workspace-add.spec.ts:15 hardcodes const REMOTE_ORIGIN = 'http://127.0.0.1:5199', and its own doc comment says any origin works "as long as it differs from the page origin". Running the suite with PLAYWRIGHT_PORT=5199 therefore makes the page origin collide with the mock-daemon origin and fails 5 of 6 scenarios — I hit this myself and it cost a wasted arm before I read line 15. Deriving REMOTE_ORIGIN from the configured port (or asserting the two differ in a beforeAll) would make the suite portable. This is a test-infrastructure robustness point only; it does not affect the PR under review, whose own CI runs on the default port.
qqqys
left a comment
There was a problem hiding this comment.
Approving on a re-read at an unmoved head, cashing the deferral our own e2e report recorded ("the approval decision is left to a re-read at an unmoved head").
State at the moment of this write (re-enumerated immediately before it, not carried over from the report):
- Head is still
3fdc8e473ec6— unmoved since the independent run, so nothing below is stale against a newer tree. - CI census complete and per-lane, not read off the rollup:
total_count=92 fetched=92 MATCH=True, all six product lanessuccess(Test (ubuntu-latest, Node 22.x),Lint & Static (ubuntu-latest, Node 22.x),Integration Tests (no-AK, No Sandbox),Desktop Shell (ubuntu-22.04),Desktop Shell (windows-2022),web-shell E2E Smoke (ubuntu-latest, Node 22.x)), zero non-green lanes and zero lanes still incomplete. Theskippedrows are event-type skips present on every PR and are counted as their own bucket, not folded into "green". - Zero
[Critical]findings at this head on both surfaces — the inline comment thread and the review bodies — so the approval is not sitting on top of an unaddressed defect. qwen-code-ci-bot APPROVEDat this head (16:03:01Z), which post-dates the head commit's own committer date (15:12:25Z), so it is an approval of this tree rather than one re-anchored onto it.- No
CHANGES_REQUESTEDrow from anyone at any commit, and the PR is not a draft.
The independent verification behind this is in the report comment above: the shipped Playwright suite re-run in an isolated worktree at this exact commit, with a base arm and a mutation arm, which is what closed the two gaps the static triage could not.
One non-blocking note, already recorded in the report and repeated here only so it is not lost: web-shell.remote-workspace-add.spec.ts:15 hardcodes REMOTE_ORIGIN = 'http://127.0.0.1:5199', so running the suite with PLAYWRIGHT_PORT=5199 collides the page origin with the mock-daemon origin and fails 5 of 6 scenarios. That is test-infrastructure portability, it pre-dates this diff, and it does not affect CI here.
What this PR does
This follow-up simplifies the remote workspace interaction introduced by #12085 without changing the normal Add workspace entry. The directory browser still opens directly for local users, while previously verified computers remain available through the Folder source selector. Remote-add and connection-add navigation now share one explicit continuation intent, ordinary daemon links stay tab-scoped instead of silently becoming saved connections, and remote folders keep their globe marker without a duplicate host label above the workspace list.
Why it's needed
The normal local workflow should remain unsurprising for users who never use remote computers, and persistent remote connections should reflect an explicit user action. The previous implementation also carried parallel flags and duplicate host chrome that were no longer needed once source selection moved into the directory browser.
Reviewer Test Plan
How to verify
Evidence (Before & After)
Before: every successful cross-origin gate probe could save the daemon, and the sidebar showed both a host chip and per-folder remote markers. After: only explicit connection forms save the daemon, the host chip is removed, and Add workspace keeps the direct directory-browser interaction with Folder source selection. The dedicated browser suite passed all 6 remote-workspace scenarios, including local default behavior, remote switching, cancellation, source switching, and the no-connection path.
Tested on
Environment (optional)
Local Web Shell with mocked local and remote daemons in Chromium, plus focused unit tests.
Risk & Scope
Design documents: English design · 中文设计
Linked Issues
Follow-up to #12085 for the Web Shell milestone of #11475.
中文说明
本 PR 做了什么
这是 #12085 的后续简化,不改变普通的“添加工作区”入口。本地用户仍会直接进入目录浏览器,已验证的远程计算机则继续通过“目录来源”选择器提供。远程工作区添加和连接添加现在共用一个明确的续接意图;普通 daemon 链接只在当前标签页生效,不再被静默保存为持久连接;远程目录继续保留地球标记,同时移除工作区列表上方重复的主机标签。
为什么需要
对于从不使用远程计算机的用户,普通本地流程应保持直观;持久化远程连接也应来自用户的明确操作。目录来源已经收进目录浏览器后,原实现中的并行标记和重复主机展示都不再需要。
Reviewer Test Plan
如何验证
证据(前后对比)
之前:任何跨 origin 连接页探测成功都可能保存 daemon,侧边栏同时显示主机标签和每个目录的远程标记。之后:只有显式连接表单会保存 daemon;移除主机标签;“添加工作区”继续直接进入目录浏览,并通过“目录来源”切换机器。专用浏览器测试的 6 个远程工作区场景全部通过,覆盖本地默认行为、远程切换、取消、来源切换和无远程连接路径。
测试平台
环境(可选)
本地 Web Shell、Chromium 中模拟的本地和远程 daemon,以及专项单元测试。
风险与范围
设计文档:English design · 中文设计
关联问题
这是 #12085 的后续,属于 #11475 的 Web Shell 里程碑。