fix(desktop): hide internal workspace during startup - #8988
Conversation
|
Re-run on the new head — full gate pass, prior comments updated in place.
Moving on to code review. 🔍 中文说明新 head 上的重跑——完整门检查,历史评论就地更新。
进入代码审查。🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewIndependent proposal before reading the diff: hide the workspace UI behind a body state attribute, make live runtime events win over a stale What I traced against the base blobs (they match the diff's parents exactly, so this is a review of the real delta):
No blockers, no convention violations. The one race this PR exists for, for reviewers validating the ordering fix: sequenceDiagram
participant P1 as User
participant P2 as Bootstrap page
participant P3 as Tauri backend
P2->>P3: invoke bootstrap_state, still pending
P1->>P2: click Retry
P2->>P2: set override flag to starting
P2->>P3: invoke restart_runtime
P3-->>P2: stale snapshot resolves
P2->>P2: override flag set, snapshot discarded, path stays hidden
Testing — the PR's own CI at
|
| Check | Conclusion |
|---|---|
| Classify PR | success |
| Desktop Shell (ubuntu-22.04) | success |
| Desktop Shell (windows-2022) | success |
| Test (ubuntu-latest, Node 22.x) | failure (pre-existing flake, see prose) |
| Test (macos-latest, Node 22.x) | skipped (CI classification) |
| Test (windows-latest, Node 22.x) | skipped (CI classification) |
| Integration Tests (CLI, No Sandbox) | skipped (CI classification) |
Sandboxed verification
The central claim here is behavioural — path hidden during startup, events winning over stale snapshots — and a sandboxed @qwen-code /verify A/B run against the base build is already in flight for this exact head (run 31612096185); its report lands as a separate comment when done. The prior head's verify run already included a mutation matrix showing the harness fails when the guard is removed, so this run re-confirms rather than explores. Nothing further to trigger — and note /tmux is the wrong lane here (desktop GUI, not a TUI surface).
中文说明
代码审查
读 diff 之前的独立方案:用 body 状态属性隐藏 workspace 界面、让运行时事件优先于过期的 bootstrap_state 快照、让快照返回正在启动的 workspace 而不只是持久化的那个。PR 正是这么做的,而且时序保护收敛为一个 snapshotOverrideStatus 标志——这是最小正确形态,我没有找到更简单的路径。
对照 base blob 逐条追踪(blob 与 diff 父哈希完全一致,审的是真实增量):
start_runtime_async在发出runtime-starting事件之前写入last_workspace,因此新的bootstrap_workspace优先级(尝试启动的优先于持久化的)总能返回真正在启动的 workspace——这正是错过事件后快照仍能显示正确路径的原因。- 所有流程都走得通:冷启动(首屏即 splash)、事件先于快照到达(提前返回保留新状态)、任何事件之前先失败(
currentWorkspace ||=采用快照 workspace 并展示)、快照未返回时点击 Retry(过期响应不会复活路径、也不会覆盖重试标题)、取消目录选择(idle 展示上次尝试的路径)。早返回路径上version.textContent仍会从快照更新——细节到位。 - reduced-motion 的 CSS 选择器与真实
.statusDOM 一致,正常动效下状态块以视觉隐藏方式保留在aria-live区域内供读屏播报。 - 回归 harness 在
vm上下文里执行真实bootstrap.js并配可脚本化的 Tauri bridge,断言的是时序而非标记文本;Rust 单测覆盖bootstrap_workspace全部分支。
无阻塞项,无规范违规。
测试——d70101fc 上 PR 自己的 CI(本次 triage 未执行任何 PR 代码)
两个 Desktop Shell 作业(真正执行本改动的包级门槛)在受审 head 上双平台均为绿。ubuntu 日志:cargo test → 38 通过 0 失败(含新增测试;作者本地"39 个"是多一个平台 cfg 测试的计数,windows 作业相应报告 39 通过);node scripts/test-release.js → 通过(含新增启动页可见性 harness)。
仓库级 Test (ubuntu-latest) 作业最终为红,但失败与本 PR 无关:唯一失败文件是 packages/cli 的 src/serve/server.test.ts(Live 运行时/Appshot 套件的 5 个用例),全部死于同一拆除期签名:ENOTEMPTY: directory not empty, rmdir '/tmp/qwen-live-…/qwen-home/extension-store'——测试拆除阶段临时目录清理竞态。判为既有噪声的依据来自 diff 与检查身份:本 PR 全部 5 个文件都在 packages/desktop-shell,CLI serve 套件不 import 其中任何内容,启动页改动不存在导致 Live 临时目录 ENOTEMPTY 的机制。另:今天 main 的 CI 本身也因 checkout 网络错误变红。未验证:像素级渲染(由沙箱 A/B 在行为层面覆盖)。
沙箱验证
核心主张是行为性的,针对该 head 的 @qwen-code /verify A/B 运行已在进行中,报告会另行发布;上一个 head 的验证已含变异矩阵(移除保护则 harness 失败),本次是复核而非探索。无需再触发——/tmux 不适用(桌面 GUI,不是 TUI)。
— Qwen Code · qwen3.8-max
Reviewed at d70101fc56ea538ff257c2a8ba4315308909c183 · re-run with @qwen-code /triage
|
Confidence: 4/5 — clean, minimal fix whose tests actually pin the behavior; the only withholding is pixel-level rendering resting on the author's viewport check plus the A/B harness. Stepping back: this is exactly the change I would have written. The problem is verifiable in the base code (the internal workspace path was displayed on every normal startup), the fix is the minimal shape of it — one state attribute, one ordering flag, one snapshot preference — and the regression harness runs the real bootstrap script against a scriptable bridge rather than asserting markup. I traced every state transition against the base blobs and found no flow where the path leaks back during startup or the stale snapshot wins. The reduced-motion and aria-live handling are correct against the actual DOM. Nothing in the diff is unrelated to the goal. On the red CI: the only failing check is the repo-wide ubuntu suite, and its 5 failures are all the same Verdict: approve — pinned to the reviewed commit. (The earlier draft of this comment deferred approval pending CI while the suite was still running; CI has since settled, the one red is classified above, and the approval is posted explicitly rather than through the deferred marker.) 中文说明置信度:4/5 —— 干净、最小的修复,且测试真正钉住了行为;唯一保留项是像素级渲染依赖作者的视口检查加 A/B harness。 整体看:这正是我会写的改法。问题可以在 base 代码中直接验证(内部 workspace 路径过去每次正常启动都会展示),修复是最小形态——一个状态属性、一个时序标志、一个快照优先级——回归 harness 用可脚本化的 bridge 执行真实启动脚本,而不是断言标记文本。逐条对照 base 追踪了所有状态流转,没有发现任何路径会在启动期间泄漏、或让过期快照胜出。reduced-motion 与 aria-live 处理与真实 DOM 一致。diff 中没有与目标无关的改动。 关于红色 CI:唯一失败的检查是仓库级 ubuntu 套件,其 5 个失败全部是 结论:批准——绑定受审 commit。(本评论早前的版本在套件运行中时延迟批准;CI 现已出结果,唯一红色按上述归类,批准改为显式发布而非通过延迟标记。) — Qwen Code · qwen3.8-max Reviewed at |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): You are review agent reverse-audit — Reverse audit agen...: could not compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started — cargo is present but cargo test fails building libdbus-sys …; This PR replaces the Desktop bootstrap loading page with ...: Rust compile/unit-test run ( cargo test bootstrap_prefers_the_workspace_being_started ) — cargo unavailable on this runner; verified by reading instead.; You are review agent reverse-audit — Reverse audit agen...: none — all planned checks completed within budget..
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):You are review agent reverse-audit — Reverse audit agen...:could not compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started — cargo is present but cargo test fails building libdbus-sys …;This PR replaces the Desktop bootstrap loading page with ...:Rust compile/unit-test run ( cargo test bootstrap_prefers_the_workspace_being_started ) — cargo unavailable on this runner; verified by reading instead.;You are review agent reverse-audit — Reverse audit agen...:none — all planned checks completed within budget.。
— qwen3.8-max via Qwen Code /review (v0.21.10)
|
Fixed the current startup-page regression where a secondary error, such as failed Open Logs, hid the failed workspace path again. Verified |
|
@qwen-code-review-bot review this pr and approve if no blockers |
chiga0
left a comment
There was a problem hiding this comment.
Code Review Overview (AI Generated)
PR: #8988 fix(desktop): hide internal workspace during startup
Author: @yiliang114
Type: Bug fix (Desktop UX) + presentational change + test infra
Change size: +190/-21 across 5 files
HEAD reviewed: 0924d84 (fix(desktop): use Qwen logo on startup screen, 2026-08-12T11:31Z)
CI at HEAD: green (Desktop Shell (ubuntu-22.04), Desktop Shell (windows-2022), Test (ubuntu-latest) all pass). mergeable_state: blocked = awaiting required approval, not a failing check.
This is an independent blind review: Rounds 0-6 (incl. the 8 structural audits and the Pass E adversarial challenge) were completed before reading any existing review.
Findings Summary
- Critical: 0
- Major: 0
- Minor: 4
- Nit: 3
Key Observations
The core design is right and I reached the same conclusion independently: keep the attempted workspace in a JS variable, gate its display on the error state, let live runtime events win over a stale bootstrap_state snapshot, and make the backend report the workspace actually being started. The Rust side (bootstrap_workspace) is clean, correctly unit-tested, and provably has only two consumers.
My concerns are all fallout from the last two commits:
541a3b15(which applied the previous reviewer's suggestion) moved the reveal intosetStatus()but left the two now-redundant explicitsetWorkspace(currentWorkspace)calls in place (bootstrap.js:148,:183) and silently regressed theidlerecovery state, which used to show the path and no longer does.0924d846(the<img>logo swap + SVG + 2 asserts) landed ~3h after the only prior review and has had zero review coverage. My index.html andqwen-code-logo.svgfindings all sit in that commit.
None of these block merge on their own; items 1 and 2 in the table below are the ones I would want addressed.
Cross-Validation
| Finding | Other Reviewer | My Assessment |
|---|---|---|
R1-1 setStatus() hides #workspace on unrelated errors |
qwen-code-ci-bot | Obsolete at HEAD. Applied verbatim in 541a3b15; bootstrap.js:35 now reads setWorkspace(kind === 'error' ? currentWorkspace : ''). Verified against HEAD file content, not the author's claim. The fix is correct — but it produced Unique-1 and Unique-2 below. |
R1-2 snapshot-only recovery path untested (test-release.js) |
qwen-code-ci-bot | Valid, still open (author declined). Partial disagreement on the rationale: the mutation it cites — deleting "the two setWorkspace(currentWorkspace) reveal lines" — is a behavioural no-op after 541a3b15, so it no longer discriminates. The genuinely uncovered load-bearing lines are bootstrap.js:159 (currentWorkspace ||= backfill) and bootstrap.js:161 (if (runtimeStatus === 'failed') setWorkspace(...)). A future test should target those two. |
R1-3 fake-DOM element() fabricates any selector |
qwen-code-ci-bot | Valid, still open (author declined). Agree it is Nit-level for a fix this small; declining is defensible. A cheaper adjacent guard is Unique-4. |
| Triage stage-3: "catch-path display gap ... acceptable" | qwen-code-ci-bot | Superseded — R1-1's fix closed that gap entirely. |
Unique-1: dead setWorkspace(currentWorkspace) at bootstrap.js:148 / :183 |
— | New (Minor) |
Unique-2: idle recovery state lost the workspace path (bootstrap.js:35 vs :185) |
— | New (Minor) — behaviour regression vs main |
Unique-3: no status text, version or "Open logs" for up to ~45s (index.html:93) |
— | New (Minor) |
Unique-4: logo assertion never checks the SVG exists (test-release.js:63) |
— | New (Minor) |
Unique-5: sr-only block missing border: 0 leaves a ~2px artifact (index.html:115) |
— | New (Nit) |
Unique-6: mock assertion swallowed by retryRuntime catch; vm has no timeout (test-release.js:88) |
— | New (Nit) |
Unique-7: runtimeStatus stays 'starting' after a cancelled picker (bootstrap.js:40) |
— | New (Nit) |
Additional Audit Coverage
Areas I independently checked that go beyond the existing findings — all of these came back clean, recorded here so the author does not have to re-verify them:
- Asset packaging:
tauri.conf.jsonsetsbuild.frontendDist: "../bootstrap", so the whole directory is bundled. The newqwen-code-logo.svgships without abundle.resourcesentry. No broken-image risk in the packaged app. - CSP: the page's
img-src 'self' data:(duplicated intauri.conf.jsonapp.security.csp) permits the relative same-originsrc="qwen-code-logo.svg"under bothtauri://localhost(macOS/Linux) andhttp://tauri.localhost(Windows). - Asset duplication: the SVG path data is byte-identical to
packages/desktop/apps/electron/resources/brands/qwen-code/icon.svgandpackages/zed-extension/qwen-code.svg. Duplication is unavoidable here becausefrontendDistmust be self-contained — not a finding. - Data-structure blast radius:
BootstrapState.workspacehas exactly two consumers repo-wide (main.rs,bootstrap.js);local-control.jsdoes not read it.last_workspaceis written only atmain.rs:483and read atmain.rs:369(restart_runtime) plus the new call site. No hidden consumer breaks. - Data provenance: the
runtime-startingpayload (main.rs:489) andbootstrap_workspace()both return the pre-canonicalisationworkspace(resolve_workspaceruns later,main.rs:501), so the event path and the snapshot path yield byte-identical strings. No optimistic/echo divergence. - Missed-event / replay divergence:
setup()emitsruntime-failedatmain.rs:296withlast_workspace == None;bootstrap_workspacethen correctly falls back tosettings.workspace()and the JSstate.errorbranch backfillscurrentWorkspace. Theemit_runtime_failuregeneration guard (main.rs:592-598) also prevents a superseded start from poisoning the JSruntimeStatusmachine. Both paths verified sound. - State-field init matrix:
runtimeStatus∈ {undefined,'starting','failed'};data-state∈ {starting,error,idle}. Onlystartinghas CSS;error/idlefall through to the full card. The initial<body data-state="starting">matches the static "Starting Qwen Code" markup, so there is no flash-of-wrong-state. Only gap found is Unique-7. - Bounded worst case:
runtime.rs:18STARTUP_TIMEOUT = 45scaps the blank-splash window — this is what keeps Unique-3 at Minor rather than Major. - CI enforcement:
.github/workflows/ci.yml:1214runsnode scripts/test-release.jswheneverpackages/desktop-shell/**changes, so the new check is genuinely gating. - Rust test correctness:
bootstrap_prefers_the_workspace_being_startedcovers all three arms (Some/Some,None/Some,None/None). No clippyor_fun_callrisk —.or()receives an already-materialised value. - Process (CONTRIBUTING.md): §1 asks every PR to link an issue and §6 asks for a screenshot/video; this PR states "No linked issue" and describes the visual check in prose only. Non-blocking, flagged for maintainer discretion.
- AGENTS.md scope gate: confined to
packages/desktop-shell/**, so the core-infrastructure two-tier gate does not apply.
Final Verdict
LGTM with minor follow-ups — recommend merge after Unique-1 and Unique-2 are addressed. The design is correct, the event/snapshot race is genuinely well handled, and CI is green at 0924d84. Unique-2 is the only real behaviour regression (idle state silently lost the workspace path) and it is a one-token fix; Unique-1 is a two-line deletion that removes the second, now-dead mechanism for the same DOM state. Everything else is optional polish.
This review was generated by QoderWork AI
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): 本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...: cargo test for the new bootstrap_prefers_the_workspace_being_started Rust test was not run — no prebuilt target/ exists in this worktree and a cold Tauri/…; 本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...: none — all planned checks completed within budget.; 本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...: cargo is not installed on this runner — could not compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started ; the Rust change was review…; 本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...: cargo test for src-tauri — cargo is not installed in this environment; the new Rust unit test ( bootstrap_prefers_the_workspace_being_started ) and the boo…; 本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...: none — all checks I started were completed within budget..
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...:cargo test for the new bootstrap_prefers_the_workspace_being_started Rust test was not run — no prebuilt target/ exists in this worktree and a cold Tauri/…;本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...:none — all planned checks completed within budget.;本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...:cargo is not installed on this runner — could not compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started ; the Rust change was review…;本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...:cargo test for src-tauri — cargo is not installed in this environment; the new Rust unit test ( bootstrap_prefers_the_workspace_being_started ) and the boo…;本 PR 将 Desktop 启动页改为居中的 Qwen 图标并在启动/加载/恢复期间隐藏内部 workspace...:none — all checks I started were completed within budget.。
— qwen3.8-max via Qwen Code /review (v0.21.10)
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 98 passed · 0 failed · 98 total 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:98 通过 · 0 失败 · 98 总计 Verification reportPR #8988 — fix(desktop): hide internal workspace during startupVerdict: 中文摘要
Central claim + A/BCentral claim: while the bundled runtime is starting/loading/restarting, the bootstrap page shows only the centered Qwen mark and never the auto-selected internal workspace path; the detailed recovery UI (error text, attempted workspace, Retry/Choose) returns exactly when startup fails. Secondary claims: (a) runtime events outrank an older The unit under test is the real
Five behavior flips, four controls holding on both arms: the hiding is load-bearing for exactly the starting/ready/retry paths, and failure visibility (the information the PR suppresses during startup) survives on every error path, including subsequent unrelated errors (S3b). Structural checks on the markup the minimal screen is built from all pass: Reviewer Test Plan walkthrough
FindingsNo blocking findings. Two informational notes, neither a defect:
Not covered
MethodologyEnvironment: Evidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
|
Triage re-run completed without a new review.
The stage comments above were updated with the latest result. View workflow run. 上方各阶段评论已更新为最新结果。查看工作流运行。 |
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 87 passed · 0 failed · 87 total 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:87 通过 · 0 失败 · 87 总计 Verification reportPR 8276 — fix(core): preserve prompt cache across deferred tool discoveryVerdict: 中文 — 判定:✅ 通过 · 可合入(agent 判定)· 第 2 轮(head 未变化,全部重新测量)第 2 轮验证。本轮 head(
Previous-finding status (follow-up round)Round 1 verified head
Central claim and A/B proofCentral claim: main-session provider function declarations stay byte-stable across deferred-tool discovery; the real schema reaches the model only in the Harness (rebuilt this round): real bundled CLI (
Witnesses: Wire facts asserted on the head arm (in Delta probes (new coverage this round)Oversized-schema escape hatch, driven E2E (
Hostile-schema sweep of the Fail-closed matrix (head, 30/30)Seven scripted sessions (
S7 re-confirms the ordering invariant: a response cannot both present and authorize a new target in the same batch. Mutation matrix (vacuity, re-measured)Unmutated controls green first: normalization 27/27, tool-registry 63/63, tool-search 66/66 (registry and tool-search counts match round 1 exactly). Single-point mutants applied in a scratch worktree at HEAD, restored via
No survivors. Every red run failed on expected-vs-actual behavioral assertions, not imports. Positive control: four planted deletions each turned the affected suite red, so the green suites cited in Targeted gates are live. Targeted gates (re-measured, full A/A)All four suites run this round (witness
Attribution, at failing-name level (
FindingsNo blocking findings. Informational (both carried from round 1, re-measured):
Not covered
MethodologyEnvironment: CI verify container ( Evidence images1 additional image(s) did not pass the hosting checks (PNG magic, unique sanitized name, ≤2 MB, max 8) and remain in the run artifacts. Harness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
|
No blockers found. The current head preserves the intended startup, failure, retry, and snapshot/event ordering while keeping workspace details hidden until recovery UI is needed. Verified with |
|
@qwen-code-review-bot review this pr and approve if no blockers |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): You are review agent reverse-audit — Reverse audit agen...: compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started (no cargo toolchain in this environment).
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):You are review agent reverse-audit — Reverse audit agen...:compile/run the new Rust unit test bootstrap_prefers_the_workspace_being_started (no cargo toolchain in this environment)。
— qwen3.8-max via Qwen Code /review (v0.21.10)
| }); | ||
| } | ||
| if (command === 'open_logs') throw new Error('no file handler'); | ||
| if (command === 'choose_workspace') return null; |
There was a problem hiding this comment.
[Suggestion] The changed success branch if (path) currentWorkspace = path; in chooseWorkspace() is never exercised: the harness mock hardcodes choose_workspace to resolve null here, so all three scenarios run only the no-selection branch — Failure scenario: deleting or breaking that assignment (the exact line this diff changed from setWorkspace(path)) leaves every assertion in testBootstrapWorkspaceVisibility green (mutation-proven), while the behaviour it guards — user picks a folder, the runtime then fails, and the recovery panel must show the folder the user chose — would silently regress to showing the stale auto-selected path (verified by probe: with choose_workspace resolving a path and a later runtime-failed, the mutated code shows the stale path). Suggested fix: parameterize the harness mock so choose_workspace can resolve a path, and add one picker-success scenario:
// createBootstrapHarness({ chooseResult: '/Users/example/Chosen' }) →
// if (command === 'choose_workspace') return chooseResult ?? null;
const picker = await createBootstrapHarness({
chooseResult: '/Users/example/Chosen',
});
await picker.element('#choose').listeners.click();
picker.listeners['runtime-failed']({ payload: 'runtime failed' });
picker.resolveBootstrapState({
desktopVersion: '0.2.0',
status: 'idle',
workspace: '/Users/example/Auto',
error: 'runtime failed',
});
await new Promise((resolve) => setImmediate(resolve));
assert.equal(
picker.element('#workspace').textContent,
'/Users/example/Chosen',
);中文说明
[Suggestion] chooseWorkspace() 中被修改的成功分支 if (path) currentWorkspace = path; 从未被执行到:harness 的 mock 在这里把 choose_workspace 硬编码为返回 null,因此三个场景都只走到未选择目录的分支 — 失败场景:删除或破坏这行赋值(正是本 diff 从 setWorkspace(path) 改过来的那一行)后,testBootstrapWorkspaceVisibility 的所有断言仍然全绿(已通过变异验证),而它所保护的行为——用户选择了目录、运行时随后启动失败、排障面板必须展示用户选择的目录——会静默回退为展示旧的自动选择路径(已用探针验证:让 choose_workspace 返回一个路径、随后触发 runtime-failed,变异后的代码显示的是旧路径)。建议修复:让 harness 的 mock 可配置,使 choose_workspace 能返回路径,并新增一个“选择成功”场景(见上方代码)。
— qwen3.8-max via Qwen Code /review (v0.21.10)
| </style> | ||
| </head> | ||
| <body> | ||
| <body data-state="starting"> |
There was a problem hiding this comment.
[Suggestion] The initial data-state="starting" attribute is load-bearing for the first paint but asserted nowhere: the static HTML checks only pin the logo <img> and the SVG's existence, and the vm harness injects body = { dataset: {} }, so the first-paint state is never verified — Failure scenario: removing or renaming the attribute keeps every check green, yet between page load and the first setStatus (which runs only after the async listen() registrations plus the bootstrap_state round trip) none of the body[data-state='starting'] rules apply and the page renders the full shell panel — brand copy, status card, actions row, footer — reintroducing exactly the loading UI this PR replaces (mutation-proven). Suggested fix: add this assertion next to the logo checks in testBootstrapWorkspaceVisibility:
assert.match(bootstrapHtml, /<body data-state="starting">/);中文说明
[Suggestion] 初始的 data-state="starting" 属性对首屏渲染是承重的,但没有任何断言钉住它:静态 HTML 检查只钉住了 logo <img> 和 SVG 文件的存在,而 vm harness 注入的是 body = { dataset: {} },因此首屏状态从未被验证 — 失败场景:删除或改名该属性后所有检查仍然全绿,但在页面加载到第一次 setStatus(要等异步 listen() 注册加上 bootstrap_state 往返之后才会执行)之间,所有 body[data-state='starting'] 规则都不生效,页面会渲染出完整的外壳面板——品牌文案、状态卡片、操作按钮行、页脚——恰好把本 PR 要替换掉的加载界面又带了回来(已通过变异验证)。建议修复:在 testBootstrapWorkspaceVisibility 的 logo 检查旁加入上方断言。
— qwen3.8-max via Qwen Code /review (v0.21.10)
|
Reviewed the current head and found no blockers. The startup, failure, retry, and event/snapshot ordering paths look correct, and the Desktop release regression checks pass. |
|
Released in v0.21.11. |
…ion startup (QwenLM#9064) * fix(desktop): hide the Windows runtime terminal and align reduced-motion startup On Windows the bundled runtime (node.exe, a console application) was spawned without CREATE_NO_WINDOW, so the desktop (a GUI application) allocated a visible terminal window for it; closing that window stopped the runtime with exit code 1 (QwenLM#9043). Route the spawn through a platform-specific helper that sets CREATE_NO_WINDOW via the command-group builder (group_spawn would overwrite creation flags set directly on the command). Add a Windows-only regression test that asserts the spawned child receives no console window. The reduced-motion bootstrap fallback showed the logo left-aligned inside the shell while the newly visible status text was centered in a wider card, so the two did not share a horizontal center. Stack and center both inside the shell and drop the leftover card chrome, mirroring the simplified startup view from QwenLM#8988, and extend the bootstrap release check to guard the centering rules. * fix(desktop): simplify reduced-motion startup centering * fix(core): hide daemon-side console spawns on Windows With the bundled runtime spawned console-less, console-app children of the daemon no longer inherit a console and each allocates a visible window. Pass windowsHide at the git attribution, git notes, and taskkill spawn sites in the shell tool, matching shellExecutionService. Also loosen the reduced-motion bootstrap assertion so it no longer hard-codes rule order inside the media block. * fix(desktop): hide runtime descendant consoles * test(desktop): pin the hidden-console spawn helper at the production call site The Rust test exercises spawn_runtime_group directly; nothing guarded that DesktopRuntime::start still routes through it. Assert the call site in the release gate so a refactor reverting to group_spawn() fails the suite.











What this PR does
Replaces the normal Desktop loading page with a minimal centered Qwen icon and keeps the automatically selected internal workspace hidden while Qwen Code Desktop is starting, loading, or beginning a recovery action. If the runtime actually fails, the bootstrap page restores the detailed recovery UI and shows the attempted workspace so the user can diagnose the failure or choose another directory.
Runtime events now take precedence over an older bootstrap snapshot, and a snapshot taken after an early missed event reports the workspace currently being started rather than only the previously persisted workspace. An executable regression check covers startup, failure, and retry ordering.
Why it's needed
The Desktop app already starts with an internal primary workspace and does not require the user to select a directory. The card-style loading page looks interactive, and showing its internal path resembles a mandatory workspace picker. A centered brand mark communicates transient loading; the detailed screen and path are useful only when startup needs user action.
Reviewer Test Plan
How to verify
Launch the Desktop app with either fresh or persisted settings and confirm that no workspace path is shown while the bundled runtime starts. Force a runtime startup failure and confirm that the attempted workspace appears with the error. Start Retry while the initial bootstrap state request is still pending and confirm that an older state response does not restore the path or replace the retry status.
Evidence (Before & After)
Before: the normal “Starting Qwen Code” page displayed a large workspace card and the automatically selected local workspace path.
After: normal startup and retry show only a centered Qwen icon with a reduced-motion-safe animation; a runtime failure restores the detailed recovery screen and reveals the attempted path. This was visually checked at a 1440×900 viewport, and the executable bootstrap regression check confirms the state transitions. The full packaged build reached the runtime assembly stage but could not finish locally because two downloads of the official Node.js archive timed out after 120 seconds; no compile or test failure occurred.
Tested on
Environment (optional)
macOS arm64, Node.js 22.22.0. Desktop release helper checks, all 39 Rust tests, Prettier, ESLint, and diff checks passed.
Risk & Scope
Linked Issues
No linked issue.
中文说明
本 PR 做了什么
正常启动时改为只展示全局居中的 Qwen 图标,并且在启动、加载或开始恢复操作时不再展示自动选择的内部 workspace。只有运行时真正启动失败时,启动页才会恢复完整的排障界面并显示本次尝试启动的 workspace,方便用户排查失败或选择其他目录。
运行时事件现在会优先于较旧的启动状态快照;如果页面错过了较早的事件,后续快照也会返回当前正在启动的 workspace,而不只是之前持久化的 workspace。新增的可执行回归检查覆盖了启动、失败和重试的时序。
为什么需要
Desktop 已经会使用内部 primary workspace 自动启动,并不要求用户先选择目录。原来的卡片式加载页看起来像一个需要交互的界面,其中的内部路径也容易被理解成必须操作的 workspace 选择器。居中的品牌图标更适合表达短暂加载,完整界面和路径只在需要用户处理启动问题时有帮助。
Reviewer Test Plan
如何验证
分别使用全新设置和已有设置启动 Desktop,确认内置运行时启动期间不展示 workspace 路径。人为制造运行时启动失败,确认错误状态会展示本次尝试的 workspace。在初始启动状态请求尚未返回时点击 Retry,确认旧状态响应不会重新显示路径,也不会覆盖重试状态。
证据(修改前后)
修改前:正常的“Starting Qwen Code”页面会展示大型 workspace 卡片和自动选择的本地 workspace 路径。
修改后:正常启动和重试时只展示居中的 Qwen 图标,并提供遵循 reduced-motion 设置的轻量动画;运行时失败时恢复完整排障界面并展示本次尝试的路径。已在 1440×900 视口进行视觉检查,可执行的启动页回归检查也确认了这些状态切换。完整打包在本地已运行到运行时组装阶段,但两次下载官方 Node.js 压缩包都在 120 秒后超时,因此未能完成;没有出现编译或测试失败。
测试平台
环境(可选)
macOS arm64,Node.js 22.22.0。Desktop 发布辅助检查、全部 39 个 Rust 测试、Prettier、ESLint 和 diff 检查均通过。
风险与范围
关联 Issue
没有关联 Issue。