Skip to content

feat(web-shell): hide sources panel add-source button behind URL flag - #11639

Merged
callmeYe merged 1 commit into
mainfrom
web-shell/hide-sources-add-button
Sep 11, 2026
Merged

feat(web-shell): hide sources panel add-source button behind URL flag#11639
callmeYe merged 1 commit into
mainfrom
web-shell/hide-sources-add-button

Conversation

@callmeYe

Copy link
Copy Markdown
Collaborator

What this PR does

Hides the "+" button in the header of the Web Shell sources panel by default. The button's code path — including the add-source dialog it opens — is kept intact: appending the URL parameter ?addSource=1 brings it back, following the same escape-hatch pattern the Web Shell already uses for switches like ?composer=. Everything else in the panel (source list, attachments, empty state, view-all toggle) is unchanged. Existing panel tests opt into the flag in a shared setup hook, and new collocated tests cover both the hidden default and the enabled state.

Why it's needed

The plus button in the sources panel header serves no practical purpose in the current product flow, but deleting the code outright would throw away a working add-source interaction that may still be wanted for debugging or future iterations. Hiding it behind a URL flag declutters the default UI while keeping the behavior one parameter away.

Reviewer Test Plan

How to verify

  1. Open the Web Shell as usual and navigate to a session's environment panel: the sources section header shows the title and count but no "+" button.
  2. Reload with ?addSource=1 appended to the URL: the "+" button reappears and opens the add-source dialog as before.
  3. Run cd packages/web-shell && npx vitest run client/components/panels/SourcesSection.test.tsx client/components/panels/EnvironmentPanel.test.tsx — all 38 tests pass.

Evidence (Before & After)

New collocated tests render the panel in jsdom and assert the button is absent by default and present with the flag; the full existing environment-panel suite (36 tests) passes unchanged against the enabled state. tsc --noEmit for the package is clean, and eslint passes on the touched files.

Tested on

OS Status
🍏 macOS ✅ tested
🪟 Windows ⚠️ not tested
🐧 Linux ⚠️ not tested

Environment (optional)

jsdom component tests via the package vitest config; Web Shell is browser- and OS-independent for this change.

Risk & Scope

  • Main risk or tradeoff: none beyond the intended default-hidden button — the gate is a single additional render condition evaluated from the URL.
  • Not validated / out of scope: no new e2e coverage; no existing e2e spec exercises the sources panel, so nothing there could regress.
  • Breaking changes / migration notes: the add-source interaction is no longer reachable by default; set ?addSource=1 to restore it.

Linked Issues

N/A — supersedes the closed #11632, which targeted the retired Electron desktop package.

中文说明

本 PR 做了什么

默认隐藏 Web Shell 来源面板头部的 "+" 按钮。按钮的代码路径——包括它打开的添加来源对话框——完整保留:在 Web Shell URL 后追加参数 ?addSource=1 即可恢复显示,沿用了 Web Shell 已有的 ?composer= 等逃生开关模式。面板的其他部分(来源列表、附件、空状态、查看全部开关)均不受影响。现有面板测试在共享的 setup 钩子中开启该开关,新增的随源测试同时覆盖默认隐藏和开启两种状态。

为什么需要

来源面板头部的加号按钮在当前产品流程中没有实际意义,但直接删除代码会丢掉一个可用的添加来源交互,将来调试或迭代时可能仍需要。用 URL 开关把它隐藏起来,既让默认界面更干净,又让该行为只需一个参数即可找回。

评审者验证计划

如何验证

  1. 照常打开 Web Shell 并进入某个会话的环境面板:来源区域的头部只显示标题和数量,没有 "+" 按钮。
  2. 在 URL 后追加 ?addSource=1 刷新:"+" 按钮重新出现,且照常打开添加来源对话框。
  3. 运行 cd packages/web-shell && npx vitest run client/components/panels/SourcesSection.test.tsx client/components/panels/EnvironmentPanel.test.tsx——38 个测试全部通过。

证据(前后对比)

新增的随源测试在 jsdom 中渲染面板,断言按钮默认不存在、带开关时存在;现有环境面板测试套件(36 个)在开启开关的状态下全部原样通过。该包的 tsc --noEmit 无错误,改动文件通过 eslint。

已测试平台

macOS ✅ 已测试;Windows ⚠️ 未测试;Linux ⚠️ 未测试(本改动为浏览器端条件渲染,与操作系统无关)。

环境(可选)

通过包的 vitest 配置运行 jsdom 组件测试。

风险与范围

  • 主要风险或权衡:除预期的默认隐藏按钮外无其他影响——开关只是从 URL 读取的一处额外渲染条件。
  • 未验证 / 不在范围内:未新增 e2e 覆盖;现有 e2e 没有用例涉及来源面板,因此无回归面。
  • 破坏性变更 / 迁移说明:添加来源入口默认不再可达,设置 ?addSource=1 即可恢复。

关联 Issue

无——替代已关闭的 #11632(该 PR 误投向已移除的 Electron 桌面包)。

The "+" button in the sources panel header serves no practical purpose
in the current product flow, so it is now hidden by default. The code
path is kept intact and can be re-enabled by appending ?addSource=1 to
the Web Shell URL, following the existing ?composer= escape-hatch
pattern. Existing EnvironmentPanel tests opt into the flag in a
beforeEach; new collocated tests cover both the hidden default and the
enabled state.
@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Qwen Triage finished — CI landed green on 23780bd and the deferred approval was posted. finalize run

Qwen Triage 已完成 —— 23780bd 的 CI 全绿,延迟审批已提交。查看 finalize 运行

@callmeYe
callmeYe enabled auto-merge September 11, 2026 08:52

@ytahdn ytahdn 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.

What this PR does / PR 主旨

EN: Hides the "+" (add-source) button in the Web Shell sources-panel header by default, gating it behind a ?addSource=1 URL parameter while keeping the whole add-source dialog code path intact. The gate is a single extra render condition state?.supported && isAddSourceEnabled(); isAddSourceEnabled() reads window.location.search with an SSR guard. Existing panel tests opt into the flag via a shared beforeEach, and new collocated tests assert hidden-by-default and shown-with-flag.

中文:默认隐藏 Web Shell 来源面板头部的 "+"(添加来源)按钮,改为通过 URL 参数 ?addSource=1 开启,同时完整保留添加来源对话框的代码路径。开关是一处额外的渲染条件 state?.supported && isAddSourceEnabled()isAddSourceEnabled() 带 SSR 守卫地读取 window.location.search。现有面板测试通过共享的 beforeEach 开启该开关,新增随源测试断言"默认隐藏"和"带开关显示"两种状态。

Verification / 核对(static only, head 23780bd6

  • The gate is sound and no orphan dialog path remains. setAdding(true) is reachable only from the button's onClick (SourcesSection.tsx:107-115); with the button hidden, adding stays false, so the DialogShell and the onDialogOpenChange?.(adding && state?.supported === true) effect can never fire from a hidden UI. Grepped the package: the only non-test references to sources.add / the button are i18n.tsx (key definition) and SourcesSection.tsx itself — the actions.ts hit is an unrelated "Add source timed out" string. No e2e/.spec.ts exercises the sources panel, so nothing regresses there.
  • Test assertion matches the rendered label. The button's aria-label is t('sources.add'), which resolves to "Add source" in EN (i18n.tsx:2892), so button[aria-label="Add source"] in the new test is correct; the ZH value (添加来源, i18n.tsx:6385) is present too.
  • The shared beforeEach is necessary and does not weaken existing assertions. The three dialog tests (EnvironmentPanel.test.tsx:820/853/891) query the button and .click() it, so they genuinely need ?addSource=1 now that the flag is ANDed into the gate. The two toBeNull() assertions (646, 935) live in render paths where state?.supported is already false, so turning the flag on cannot resurrect the button there — they stayed valid before and after. afterEach resets the URL to /, keeping per-test isolation clean.
  • Convention consistency. new URLSearchParams(window.location.search).get('…') matches the established escape-hatch pattern in App.tsx (2247/2256), main.tsx (94/136/148/153), and config/daemon.ts (5/73). Reading it non-reactively at render is consistent with those call sites and appropriate for a load-time switch.
  • Cross-PR check. The author's other open PR touching this area (PR 11641, "move source download to the header") modifies ArtifactPanel.tsx/SourcePreview.test.tsx, not SourcesSection.tsx — no file-level conflict or shared-literal collision between the two.

No Critical and no Important issues found.

Non-blocking note / 非阻塞小点(Nit)

  • The "is hidden by default" test relies on the ambient URL being clean rather than setting it explicitly at the start of the test (it's first in the file and afterEach resets to /, so it's correct today). For order-independence you could add an explicit window.history.replaceState({}, '', '/') at the top of that case — purely defensive, no current failure.

CI status at review time / 审查时的 CI 状态

Honest note: at review time on head 23780bd6, Lint & Static, Integration Tests (no-AK) and both Desktop Shell lanes were green, but Test (ubuntu-latest, Node 22.x) (which runs the new SourcesSection.test.tsx) and Capture web-shell visuals were still pending. This approval rests on static verification of the head tree; recommend confirming the Test lane lands green before merge.

如实说明:审查时 head 23780bd6Lint & StaticIntegration Tests (no-AK) 与两个 Desktop Shell lane 已通过,但跑新增 SourcesSection.test.tsxTest (ubuntu-latest, Node 22.x)Capture web-shell visuals 仍在 pending。此批准基于对 head tree 的静态核验;建议合并前确认 Test lane 变绿。

Verdict / 结论: ✅ Approve — a minimal, well-scoped, convention-consistent UI gate with correct test coverage; no blocking issues. Merge should wait for the pending Test lane to confirm green.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR — and for redoing this against packages/web-shell after #11632 ran into the retired desktop tree.

Template looks good ✓ — every required section is filled in, and the Chinese translation tracks the English paragraph for paragraph.

Problem: this isn't a bug fix, so there's nothing to reproduce — it's a product judgment, and the description is honest about that. One thing worth putting on the record for the maintainer: the add-source button shipped in v0.23.3 (2026-09-10) via #11262, so this gates a user-facing entry point roughly a day after it landed. There's no linked issue, no design doc, and no user feedback cited. You authored #11262, so you know this surface better than anyone reviewing it — but "serves no practical purpose in the current product flow" is an assertion a maintainer will want to confirm rather than take on faith.

Direction: plausible and in scope. Web Shell UI decluttering touches no auth, sandbox, model-selection, telemetry, release, or public-contract surface, and the reference CHANGELOG has no direct signal either way. My reservation isn't about whether to declutter — it's about how. See Approach.

Size: core paths are not touched (everything sits under packages/web-shell/client/, not src/), so the two-tier core gate doesn't apply. For the record: 9 production lines (SourcesSection.tsx +8/−1) against 70 test lines (+69/−1 across two test files). Comfortably under every threshold, and the production-to-test ratio is the right way round.

Approach: the implementation is clean, but I'd like a maintainer to settle flag-vs-delete, because that's where I think this PR is genuinely arguable rather than merely stylistic. AGENTS.md puts Simplicity First at the top of its working principles — "nothing speculative", "no flexibility or configurability that wasn't requested" — and the stated rationale for keeping the code is speculative future use ("may still be wanted for debugging or future iterations"). Concretely, hiding the button leaves the ~110-line AddSourceDialog and all 8 sources.* add-flow locale keys (in both en and zh-CN) in the shipped bundle, reachable only through an undocumented URL parameter. Deleting the button and the dialog would reach the same stated goal — a decluttered default UI — with less code and no new configuration surface, and git history keeps the interaction recoverable if it's ever wanted again.

To be clear, that's a question, not a defect. The ?composer= escape hatch in useIsTouchComposer.ts is real precedent and you follow it faithfully, comment style included. But ?composer= guards a risky behavioural switch where a rollback path earns its keep; a button that "serves no practical purpose" is a different case, and there the simpler answer may just be removal. If the maintainer agrees the flag is the right call, I have nothing further — the code does it well.

Risk: no elevated risk signals. None of the changed files match the revert-correlated paths from the high-risk screen, the blast radius is one render condition, and the change is trivially reversible.

Flagging the flag-vs-delete question for a maintainer before this goes further. Code review and CI evidence follow below. 🔍

中文说明

感谢贡献!也感谢你在 #11632 撞上已下线的 desktop 目录之后,重新对 packages/web-shell 提交了这一版。

模板完整 ✓ —— 所有必填章节都写了,中文说明与英文逐段对应。

问题: 这不是 bug fix,所以没有可复现的东西——它是一个产品判断,PR 描述对此也很坦诚。有一点需要记录给 maintainer:这个"添加来源"按钮是刚刚通过 #11262v0.23.3(2026-09-10) 发布的,也就是说本 PR 在功能上线约一天后就把这个面向用户的入口关掉了。没有关联 issue、没有设计文档、也没有引用用户反馈。#11262 是你写的,你比任何评审者都更了解这块——但"在当前产品流程中没有实际意义"这个判断,maintainer 大概会想自己确认一下,而不是直接采信。

方向: 合理且在范围内。Web Shell 的界面精简不涉及 auth、sandbox、模型选择、telemetry、发布或公开契约,参考仓库的 CHANGELOG 也没有直接信号。我的保留意见不在于"要不要精简",而在于"怎么精简",见下面的"方案"。

规模: 未触及核心路径(改动都在 packages/web-shell/client/ 下,不是 src/),因此两层核心门禁不适用。记录一下:生产代码 9 行SourcesSection.tsx +8/−1),测试代码 70 行(两个测试文件 +69/−1)。远低于所有阈值,而且生产代码与测试代码的比例是健康的。

方案: 实现本身很干净,但"加开关还是直接删"这一点我希望由 maintainer 来定,因为这里我认为是有实质争议的,而不只是风格问题。AGENTS.md 把 Simplicity First 放在工作原则的第一位——"不做投机性设计"、"不引入未被要求的可配置性"——而保留这段代码的理由恰恰是投机性的未来用途("将来调试或迭代时可能仍需要")。具体来说,隐藏按钮之后,约 110 行的 AddSourceDialog 以及全部 8 个 sources.* 添加流程文案(en 和 zh-CN 各一份)仍留在产物里,只能通过一个未写入文档的 URL 参数访问。直接删掉按钮和对话框同样能达成 PR 声明的目标——默认界面更干净——而且代码更少、不新增配置面;如果将来真的需要,git 历史随时可以找回这个交互。

需要说明的是,这是一个疑问,不是缺陷。useIsTouchComposer.ts 里的 ?composer= 逃生开关确实是既有先例,你也严格沿用了它(连注释风格都一致)。但 ?composer= 保护的是一个有风险的行为切换,回滚通道是有价值的;而一个"没有实际意义"的按钮情况不同,更简单的答案可能就是直接移除。如果 maintainer 认为开关是正确选择,我这边没有别的意见——代码把这件事做得很好。

风险: 无升级风险信号。改动文件均未命中高风险路径筛查中与 revert 相关的模式,影响面只是一个渲染条件,且极易回滚。

在继续推进之前,先把"加开关还是直接删"这个问题提给 maintainer。代码审查与 CI 证据见下方。🔍

Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 23780bd694aa9875d59dedc9299adc575babab00 · re-run with @qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Code review

No correctness bugs, no security concerns, and no regressions that I can find. The production change is one extra term in a render condition, and it follows the existing ?composer= hatch closely enough that it reads as house style rather than an invention. What took the review time was checking the claims around it — several of them could have been quietly wrong, and none were:

  • The new test can't pass vacuously. button[aria-label="Add source"] looks like the kind of selector that silently matches nothing, which would make the "hidden by default" assertion true for the wrong reason. It's real: sources.add resolves to Add source in the en bundle (i18n.tsx:2892), and the tests mount under <I18nProvider language="en">. The paired flag-on assertion pins the other direction, so a copy change would fail loudly instead of turning test 1 into a no-op.
  • ?addSource=1 survives the app's URL rewriting. This was my main worry — main.tsx rewrites the URL on boot and on session switches, and a param stripped there would make the hatch work once and then silently stop working. replaceStandaloneSessionUrl and the mount-time scrub effect delete only theme, language, lang, token, daemon, workspace, and context. addSource is untouched, so the flag keeps working across navigation.
  • "Everything else in the panel is unchanged" is accurate. The header button is the only setAdding(true) call site, and state.upsert is called only from AddSourceDialog. So hiding the button genuinely retires the whole add flow by default rather than leaving a second entry point dangling. The desktop-era sidebar and empty-state entry points mentioned in feat(desktop): gate sources panel add-source button on launch flag #11632 don't exist here — the empty state is a plain <p>.
  • No e2e or visual regression. The claim that no e2e spec exercises the sources panel checks out: the only reference is web-shell.transcript-composer-alignment.spec.ts:222, which toggles environment-panel visibility and asserts composer alignment, never touching the add button. There are also no committed .png baselines in the package, so removing the button can't churn a snapshot.
  • The beforeEach in EnvironmentPanel.test.tsx is load-bearing, not cosmetic. Three existing tests (lines 814, 847, 885) grab the button with a non-null assertion and click it to drive the dialog lifecycle. Without the flag they'd throw on a null dereference rather than fail an assertion — so opting the suite in was the right call, and it's commented.
  • Conventions hold. // @vitest-environment jsdom is required, not redundant: the package vitest config sets no global environment, and sibling panel tests carry the same directive. The typeof window === 'undefined' guard mirrors resolveTouchComposer, so it isn't defensive code for an impossible case.

Non-blocking observations, none of which I'd hold the PR for:

  • The param is re-parsed on every render, whereas ?composer= deliberately freezes at mount via useState. Freezing has a documented reason there (swapping editor backends mid-session drops the draft); nothing similar applies here, so re-reading is fine and arguably more correct. Just noting the two hatches differ in shape.
  • With the button hidden by default, the 36 existing EnvironmentPanel tests now exercise the panel in the flag-on configuration. The default configuration is covered only by the 2 new component-level tests, so there's no panel-level integration assertion against the shipped default. Small gap, and closing it would mean duplicating the mount scaffolding.
  • If the flag stays, the 8 sources.* add-flow keys remain in both locale bundles with no default-path consumer. That's the expected cost of the approach, not an oversight — but it's the same cost the Stage 1 flag-vs-delete question is about.

Test evidence

This is an unattended CI run, so nothing here was built or executed locally — the evidence below is the PR's own CI, read from the checks API at the reviewed commit. At the time of writing the suite had not finished: Test (ubuntu-latest, Node 22.x), Lint & Static, and Capture web-shell visuals were still in progress. Nothing was red.

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

Check Conclusion
Capture web-shell visuals (ubuntu-latest, Node 22.x) ✅ success
Classify PR ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Integration Tests (no-AK, No Sandbox) ✅ success
Lint & Static (ubuntu-latest, Node 22.x) ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ✅ success

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

Outside the table: assign, authorize, Classify PR, delay-automatic-review, and label all succeeded. The remaining skipped entries are orchestration jobs this PR isn't eligible for (ack-review-request, precheck-pr, resolve-pr, review-config, publish-*, tmux-testing, verify, and the CLI-sandbox integration lane). The bot's own triage and review-pr jobs were in flight and are excluded from the signal.

Two caveats on reading this as evidence. Test (macos-latest) and Test (windows-latest) are skipped, so the "✅ tested on macOS" row in the description is the author's local run, not something CI corroborates — and the author's "38 tests pass" is likewise their claim, not independently re-run here. The still-pending ubuntu Test job is what actually covers the two changed test files; a green result there is the real evidence, and it didn't exist yet when this was written.

Sandboxed verification would settle what static review can't: @qwen-code /verify — the jsdom tests pin the render condition, but nothing here shows the rendered panel in a browser, so whether the header row still lays out correctly with the button gone (styles.sectionHeaderRow is a flex row that previously had two children) and whether the restored dialog actually works end-to-end through the real boot path are both unverified. Capture web-shell visuals is running and its artifacts would answer the layout half; /verify would answer the behavioural half.

中文说明

代码审查: 没有发现正确性问题、安全隐患或回归。生产代码改动只是在一个渲染条件上多加了一项,而且与既有的 ?composer= 开关高度一致,读起来像是仓库自有风格而不是新造的东西。审查时间主要花在核对 PR 的各项声明上——其中几条本来很有可能悄悄出错,结果都没有:

新测试不会"空过"。button[aria-label="Add source"] 这种选择器很容易什么都匹配不到,从而让"默认隐藏"的断言因为错误的原因成立。这里是有效的:en 文案里 sources.add 就是 Add sourcei18n.tsx:2892),测试也在 <I18nProvider language="en"> 下挂载。加上开启开关的那条断言把另一个方向也钉住了,所以文案一旦改动会明确失败,而不会让第一条测试退化成空断言。

?addSource=1 能在应用的 URL 改写中存活。这是我最担心的一点——main.tsx 在启动和切换会话时会改写 URL,如果参数在那里被清掉,这个开关就会"生效一次然后静默失效"。实际上 replaceStandaloneSessionUrl 和挂载时的清理 effect 只删除 themelanguagelangtokendaemonworkspacecontextaddSource 不在其中,因此切换会话后开关依然有效。

"面板其他部分不受影响"是准确的。头部按钮是唯一的 setAdding(true) 调用点,state.upsert 也只由 AddSourceDialog 调用,所以隐藏按钮确实让整条添加流程默认下线,不会留下第二个入口。#11632 里提到的 desktop 时代的侧边栏/空状态入口在这里并不存在——空状态就是一个纯 <p>

没有 e2e 或视觉回归。"现有 e2e 没有用例涉及来源面板"这一说法核实无误:唯一的引用是 web-shell.transcript-composer-alignment.spec.ts:222,它只切换 environment-panel 的显隐并断言输入框对齐,从不点击添加按钮。包内也没有已提交的 .png 基线,所以移除按钮不会引起快照变更。

EnvironmentPanel.test.tsx 里的 beforeEach 是必需的,不是顺手加的。现有三个测试(814、847、885 行)用非空断言取到按钮并点击它来驱动对话框生命周期。没有这个开关,它们会因为空引用直接抛错,而不是断言失败——所以让整个测试套件选择开启是对的,而且也写了注释说明。

约定方面没有问题。// @vitest-environment jsdom 是必需的而非冗余:包的 vitest 配置没有设置全局 environment,同级面板测试也带同样的指令。typeof window === 'undefined' 的判断与 resolveTouchComposer 一致,因此不是针对不可能场景的防御代码。

非阻塞的观察(都不足以卡住这个 PR):参数在每次渲染时都会重新解析,而 ?composer= 是通过 useState 在挂载时刻意冻结的。那边冻结有明确理由(会话中途切换编辑器后端会丢草稿),这里没有类似约束,所以每次重读没问题、甚至更正确,只是两个开关的形态不同。默认隐藏按钮后,现有 36 个 EnvironmentPanel 测试都是在开关开启的配置下运行面板,默认配置只由 2 个新的组件级测试覆盖,因此针对实际默认状态没有面板级集成断言——缺口很小,补上则要重复一遍挂载脚手架。如果保留开关,8 个 sources.* 文案会继续留在两种语言的包里且默认路径无人消费——这是该方案预期的代价,不是疏漏,但也正是 Stage 1 里"加开关还是直接删"那个问题所指的代价。

测试证据: 本次为无人值守 CI 运行,未在本地构建或执行任何 PR 代码——以上证据来自被审查提交上 PR 自身的 CI,通过 checks API 读取。撰写时测试套件尚未跑完:Test (ubuntu-latest, Node 22.x)Lint & StaticCapture web-shell visuals 仍在进行中,没有失败项。

表格之外:assignauthorizeClassify PRdelay-automatic-reviewlabel 均成功;其余 skipped 项是本 PR 不符合条件的编排类任务(ack-review-requestprecheck-prresolve-prreview-configpublish-*tmux-testingverify 以及 CLI sandbox 集成通道);机器人自身的 triagereview-pr 正在运行,不计入信号。

关于证据有两点需要说明:Test (macos-latest)Test (windows-latest) 被跳过,所以描述中"macOS ✅ 已测试"是作者本地的运行结果,CI 并未佐证——同样,作者所述"38 个测试全部通过"是作者的说法,本次未独立复跑。而仍在进行中的 ubuntu Test 任务才是真正覆盖这两个测试文件的那一环,它绿了才算数,撰写本评论时这个结果还不存在。

沙箱验证可以补上静态审查补不了的部分:@qwen-code /verify——jsdom 测试钉住了渲染条件,但这里没有任何东西展示浏览器中真实渲染出来的面板,因此按钮移除后头部行是否仍然排版正常(styles.sectionHeaderRow 原本是有两个子元素的 flex 行),以及恢复出来的对话框能否在真实启动路径下端到端工作,都未经验证。正在运行的 Capture web-shell visuals 其产物可以回答排版那一半,/verify 可以回答行为那一半。

Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 23780bd694aa9875d59dedc9299adc575babab00 · re-run with @qwen-code /triage

@qwen-code-ci-bot

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

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean implementation with no defects found at any stage; the single question I couldn't settle from the diff has been settled by a maintainer on this exact commit, and what remains is non-blocking.

This comment reverses an earlier verdict, so the reasoning is worth stating plainly. My first pass through this PR landed at 3/5 and deferred, for one reason: the code was clean, but choosing between a permanent URL flag and outright deletion is a product call, and with no issue, no design doc, and no user feedback behind it I didn't think it was mine to make. While that pass was running, @ytahdn — who has write access — reviewed and approved commit 23780bd694aa9875d59dedc9299adc575babab00, the same commit this review covers, with a substantive written review rather than a drive-by LGTM. That is precisely the call I said I couldn't resolve, made by someone entitled to resolve it. The premise for deferring is gone, so the verdict changes. I'd rather flag the reversal than quietly rewrite it.

On the merits, my read of the code didn't change and still holds up. The gate reuses a real in-repo precedent instead of inventing a mechanism, the tests are paired so neither direction can pass vacuously, and the things that usually break in this shape of change — a param silently stripped by URL rewriting, a selector matching nothing, a second entry point left dangling, an e2e spec clicking the now-hidden button — I checked each one and none of them bite. Nine production lines, well tested, trivially reversible.

Named non-blocking notes, recorded once and not relitigated:

  • I'd still lean toward deletion. The flag keeps the ~110-line AddSourceDialog and all 8 sources.* add-flow keys in both locale bundles, reachable only through a parameter that appears in no documentation, justified by speculative future use — which is the case AGENTS.md's Simplicity First principle is written against. The maintainer has chosen the flag; that's a legitimate call and it's theirs to make. If this hatch outlives its usefulness, the cleanup is small and obvious.
  • Default-configuration coverage is thin at panel level. The 36 existing EnvironmentPanel tests now run flag-on, so the shipped default is asserted only by the 2 new component-level tests. Closing that would mean duplicating the mount scaffolding, which isn't worth it here.

CI at the time of this update: Lint & Static, Capture web-shell visuals, Integration Tests (no-AK, No Sandbox), and Desktop Shell on both ubuntu and windows are green. Test (ubuntu-latest, Node 22.x) — the job that actually covers the two changed test files — was still running. The macOS and Windows unit lanes are skipped, so the description's "38 tests pass" remains the author's local result rather than something CI corroborates; I'm not treating it as evidence, and nothing here depends on it.

Not approving in this run. The unit suite is still in flight on the reviewed commit, and approving now would attest to a result that doesn't exist yet. Approval is deferred until CI lands green on 23780bd694aa9875d59dedc9299adc575babab00; if anything goes red or the head moves, that deferral is withdrawn rather than honoured.

中文说明

信心度:4/5 —— 实现干净,各阶段都未发现缺陷;我唯一无法从 diff 判断的问题,已由 maintainer 在同一个提交上给出结论,剩下的都是非阻塞项。

本评论推翻了先前的结论,所以有必要把理由讲清楚。 我第一轮审查给的是 3/5 并选择转交,原因只有一个:代码本身没问题,但"用永久 URL 开关还是直接删除"属于产品决定,而这个 PR 背后没有 issue、没有设计文档、也没有用户反馈,我不认为这个决定该由我来做。就在这一轮运行期间,@ytahdn(具备 write 权限)审查并批准了提交 23780bd694aa9875d59dedc9299adc575babab00——正是本次审查所覆盖的那个提交——而且给出了实质性的书面评审,不是随手 LGTM。这恰恰是我说自己无法判断、而应由有权者判断的那个问题。转交的前提已经不存在,所以结论随之改变。我愿意明确标出这次反转,而不是悄悄改写。

就代码本身而言,我的判断没有变化,而且依然站得住。这个开关复用了仓库里真实存在的先例,而不是自造机制;测试成对出现,因此任一方向都不会"空过";这类改动通常会出问题的几个点——参数被 URL 改写悄悄清掉、选择器什么都匹配不到、留下第二个悬空入口、某个 e2e 用例去点已被隐藏的按钮——我逐一查过,一个都没踩中。9 行生产代码,测试充分,且极易回滚。

以下非阻塞意见记录一次,不再反复:

  • 我仍然倾向于直接删除。 开关让约 110 行的 AddSourceDialog 以及两种语言共 8 条 sources.* 文案继续留在产物里,只能通过一个未出现在任何文档中的参数访问,而理由是投机性的未来用途——这正是 AGENTS.md 的 Simplicity First 原则所反对的情形。maintainer 选择了开关方案,这是合理且属于其职权范围的决定。如果这个开关将来失去用途,清理成本很小也很明确。
  • 默认配置在面板层面的覆盖较薄。 现有 36 个 EnvironmentPanel 测试现在都在开关开启的状态下运行,因此实际发布的默认状态只由 2 个新的组件级测试断言。要补上就得重复一遍挂载脚手架,在这里不值得。

截至本次更新的 CI 状态: Lint & StaticCapture web-shell visualsIntegration Tests (no-AK, No Sandbox),以及 ubuntu 与 windows 两端的 Desktop Shell 均已通过。Test (ubuntu-latest, Node 22.x)——真正覆盖这两个被改测试文件的那个任务——当时仍在运行。macOS 与 Windows 的单测通道被跳过,所以描述中"38 个测试全部通过"仍是作者本地的结果,CI 并未佐证;我没有把它当作证据,本次结论也不依赖它。

本次运行不批准。 被审查提交上的单元测试仍在进行,此刻批准等于为一个尚不存在的结果背书。批准推迟到 CI 在 23780bd694aa9875d59dedc9299adc575babab00 上全绿之后;如果出现失败或提交发生变动,该推迟即作废,不会执行。

Qwen Code · qwen3.8-max-2026-09-02

Reviewed at 23780bd694aa9875d59dedc9299adc575babab00 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

🖼️ web-shell visual preview

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

Screenshots · before / after

ℹ️ No screenshot changed against the PR base — but this PR edits 1 render-shaping file:

  • packages/web-shell/client/components/panels/SourcesSection.tsx

Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to packages/web-shell/client/e2e/visuals/screenshots.spec.ts that seeds whatever state the UI is gated on; it then appears here as a head-only (NEW) capture.

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

Qwen Code · web-shell visuals

@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. ✅

@callmeYe
callmeYe added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit e40bf35 Sep 11, 2026
65 of 66 checks passed
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.

3 participants