Skip to content

feat(cli): Add Phase 1 workspace runtime registry - #6394

Merged
wenshao merged 2 commits into
QwenLM:mainfrom
doudouOUC:codex/phase1-workspace-registry
Jul 6, 2026
Merged

feat(cli): Add Phase 1 workspace runtime registry#6394
wenshao merged 2 commits into
QwenLM:mainfrom
doudouOUC:codex/phase1-workspace-registry

Conversation

@doudouOUC

Copy link
Copy Markdown
Collaborator

What this PR does

This PR implements Phase 1 of the daemon multi-workspace plan by introducing an internal single-runtime registry for qwen serve. The existing primary workspace runtime now groups the bridge, workspace service, REST-route filesystem factory, and client-MCP sender registry behind a registry boundary while preserving the current single-workspace route behavior and legacy route locals.

It also applies the Phase 1 guardrails from issue #6378: daemon log files and telemetry service instance ids are now daemon-scoped, with workspace hash kept as metadata, and repeated explicit --workspace inputs now fail clearly at boot instead of being mistaken for a single workspace path.

Why it's needed

Phase 1 gives later multi-workspace work a narrow internal assembly boundary without changing public route schemas, SDK types, /capabilities, or enabling multi-workspace CLI behavior. It also aligns daemon identity and repeatable workspace parsing with the latest issue guidance before Phase 2 adds workspace routing.

Reviewer Test Plan

How to verify

Run cd packages/cli && npx vitest run --fileParallelism=false src/commands/serve.test.ts src/serve/daemon-logger.test.ts src/serve/run-qwen-serve.test.ts src/serve/server/telemetry.test.ts src/serve/workspace-registry.test.ts src/serve/server.test.ts src/serve/routes/workspace-file-read.test.ts; expect all targeted serve tests to pass, including registry lookup, legacy file-route locals, daemon-scoped identity, per-request workspace hashing, yargs single/repeated workspace parsing, and repeated workspace boot rejection.

Run npm run build && npm run typecheck; expect the repository to build and typecheck successfully. Existing Browserslist and chunk-size warnings may still appear during frontend builds.

Evidence (Before & After)

N/A. This is an internal daemon assembly change plus daemon identity and boot-guard behavior; there is no TUI or visual surface to compare.

Tested on

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

Environment (optional)

Local macOS worktree using the repository npm scripts, Node.js/npm from the configured development environment, and gh 2.92.0 for GitHub operations.

Risk & Scope

  • Main risk or tradeoff: daemon log file naming and telemetry service.instance.id intentionally migrate from workspace-scoped values to daemon-scoped values, so operators that key off the old identity format need to account for the new serve-<pid>.log and daemon:<pid> forms.
  • Not validated / out of scope: this PR does not locally validate Windows or Linux, does not add multi-workspace routes, does not add workspaces[] capability data, and does not implement session ownership indexing, env overlays, total-session capacity, or workspace-qualified ACP/voice/channel-worker behavior.
  • Breaking changes / migration notes: repeated explicit --workspace values now produce a clear boot error until multi-workspace support is enabled; single --workspace and omitted workspace behavior remain unchanged.

Linked Issues

Related to #6378.

中文说明

What this PR does

这个 PR 实现 daemon multi-workspace 方案的 Phase 1,为 qwen serve 引入内部 single-runtime registry。现有 primary workspace runtime 现在通过 registry 边界聚合 bridge、workspace service、REST route filesystem factory 和 client-MCP sender registry,同时保留当前单 workspace route 行为和 legacy route locals。

它也落实 issue #6378 中 Phase 1 的两个 guardrail:daemon log 文件和 telemetry service instance id 改为 daemon-scoped,workspace hash 保留为元数据;重复显式传入的 --workspace 现在会在 boot 阶段清晰失败,而不是被误当成单 workspace 路径。

Why it's needed

Phase 1 为后续 multi-workspace 工作建立一个窄的内部装配边界,同时不改变 public route schema、SDK types、/capabilities,也不启用 multi-workspace CLI 行为。它还先把 daemon identity 和 repeatable workspace parsing 与 issue 最新要求对齐,为 Phase 2 的 workspace routing 做准备。

Reviewer Test Plan

How to verify

运行 cd packages/cli && npx vitest run --fileParallelism=false src/commands/serve.test.ts src/serve/daemon-logger.test.ts src/serve/run-qwen-serve.test.ts src/serve/server/telemetry.test.ts src/serve/workspace-registry.test.ts src/serve/server.test.ts src/serve/routes/workspace-file-read.test.ts;预期所有 targeted serve tests 通过,包括 registry lookup、legacy file-route locals、daemon-scoped identity、per-request workspace hashing、yargs single/repeated workspace parsing,以及 repeated workspace boot rejection。

运行 npm run build && npm run typecheck;预期仓库构建和 typecheck 成功。前端构建期间仍可能出现已有的 Browserslist 和 chunk-size warnings。

Evidence (Before & After)

N/A。这是内部 daemon 装配变更,以及 daemon identity 和 boot-guard 行为变更;没有 TUI 或视觉界面可对比。

Tested on

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

Environment (optional)

本地 macOS worktree,使用仓库 npm scripts、当前开发环境配置的 Node.js/npm,以及用于 GitHub 操作的 gh 2.92.0。

Risk & Scope

  • Main risk or tradeoff: daemon log file naming 和 telemetry service.instance.id 有意从 workspace-scoped 迁移为 daemon-scoped;如果运维侧依赖旧 identity 格式,需要适配新的 serve-<pid>.logdaemon:<pid> 形式。
  • Not validated / out of scope: 这个 PR 没有在本地验证 Windows 或 Linux,不新增 multi-workspace routes,不新增 workspaces[] capability data,也不实现 session ownership indexing、env overlays、total-session capacity 或 workspace-qualified ACP/voice/channel-worker 行为。
  • Breaking changes / migration notes: 重复显式传入的 --workspace 现在会在 multi-workspace 支持启用前产生清晰 boot error;单个 --workspace 和省略 workspace 的行为保持不变。

Linked Issues

关联 #6378

Introduce the internal single-workspace runtime registry for qwen serve and wire the primary runtime through the existing server assembly without changing route schemas.

Also migrate daemon log and telemetry identity to daemon-scoped values, keep workspace hash as metadata, and reject repeated explicit --workspace inputs until multi-workspace serve is enabled.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC
doudouOUC marked this pull request as ready for review July 6, 2026 12:17
Copilot AI review requested due to automatic review settings July 6, 2026 12:17
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: This is a structural preparation PR — Phase 1 of the daemon multi-workspace plan described in issue #6378. No user-facing bug; the goal is to introduce an internal registry boundary so future phases can add workspace routing without restructuring the serve assembly layer. Motivation is clearly stated and linked to the tracking issue.

Direction: Aligned with the phased approach in #6378. The scope is intentionally narrow — no new routes, no SDK changes, no multi-workspace CLI behavior. This is the right shape for a Phase 1: establish the boundary, wire it through, preserve existing behavior. CHANGELOG has no direct reference to multi-workspace daemon plans, but the area is clearly within serve/daemon infrastructure evolution.

Approach: The registry pattern is minimal (~36 lines of new code in workspace-registry.ts) and the rest is mechanical variable renaming in server.ts (bridgeprimaryBridge, etc.). Daemon identity migration from workspace-scoped to daemon-scoped (daemon:<pid>, serve-<pid>.log) is clean and well-tested. One minor observation: in serve.ts, argv.workspace (which is string | string[] per the updated ServeArgs) is passed to runQwenServe directly. The runtime handler (resolveSingleWorkspaceInput) correctly accepts unknown and handles arrays. However, the yargs option definition for --workspace uses type: 'string' without array: true — in command mode, yargs may silently take the last value rather than accumulating into an array, meaning the repeated---workspace boot guard might not fire from the actual CLI. The unit tests pass because they use .parseSync() outside command mode. Not a blocker for Phase 1 (single-workspace behavior is unaffected), but worth adding array: true before Phase 2 relies on it.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题: 这是结构性准备 PR——daemon multi-workspace 方案(issue #6378)的 Phase 1。没有用户可见的 bug;目标是引入内部 registry 边界,使后续 phase 可以添加 workspace routing 而无需重构 serve 装配层。动机清晰,关联了跟踪 issue。

方向:#6378 的分阶段方案一致。范围刻意收窄——无新路由、无 SDK 变更、无 multi-workspace CLI 行为。这是 Phase 1 的正确形态:建立边界、贯穿接线、保留现有行为。

方案: Registry 模式极简(workspace-registry.ts 约 36 行新代码),其余是 server.ts 中的机械变量重命名。Daemon identity 从 workspace-scoped 迁移到 daemon-scoped(daemon:<pid>serve-<pid>.log)干净且有测试覆盖。一个小观察:--workspace 的 yargs option 定义为 type: 'string' 但没有 array: true——在 command 模式下 yargs 可能静默取最后一个值而非累积为数组,导致重复 --workspace boot guard 在实际 CLI 中不触发。单元测试通过是因为用了 .parseSync() 脱离了 command 模式。Phase 1 不阻塞(单 workspace 行为不受影响),但建议在 Phase 2 依赖它之前添加 array: true

进入代码审查 🔍

Qwen Code · qwen3.7-max

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements Phase 1 of the daemon multi-workspace plan for qwen serve by introducing an internal single-runtime WorkspaceRegistry boundary, while keeping the current single-workspace route behavior and adding guardrails from #6378 (daemon-scoped identity and clear rejection of repeated --workspace inputs).

Changes:

  • Introduces a WorkspaceRegistry/WorkspaceRuntime abstraction and wires it into createServeApp via app.locals.workspaceRegistry.
  • Makes daemon identity daemon-scoped (log filename serve-<pid>.log, telemetry service.instance.id = daemon:<pid>), preserving workspace hash as metadata.
  • Updates --workspace parsing/boot validation to handle yargs’ repeatable option shape (string vs string[]) and reject multiple explicit values.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/cli/src/serve/workspace-registry.ts Adds Phase 1 single-runtime registry interfaces + factory.
packages/cli/src/serve/workspace-registry.test.ts Unit tests for registry primary/list/lookup behavior.
packages/cli/src/serve/server/telemetry.ts Resolves workspace hash per request (future multi-workspace readiness).
packages/cli/src/serve/server/telemetry.test.ts Updates telemetry middleware unit tests for request-time resolution.
packages/cli/src/serve/server.ts Builds registry for primary runtime and threads primary runtime values through server assembly.
packages/cli/src/serve/server.test.ts Asserts registry is parked on app.locals and wiring preserves injected fsFactory.
packages/cli/src/serve/run-qwen-serve.ts Adds boot-time resolution for workspace when provided as array; updates telemetry instance id and startup profiling id.
packages/cli/src/serve/run-qwen-serve.test.ts Adds coverage for rejecting multiple --workspace, accepting single array input, and daemon-scoped telemetry id/log file name.
packages/cli/src/serve/daemon-logger.ts Switches daemon id and log naming to daemon-scoped; moves workspace identity into structured ctx metadata.
packages/cli/src/serve/daemon-logger.test.ts Updates expectations for daemon id/log path/log line metadata ordering.
packages/cli/src/commands/serve.ts Updates CLI arg typing to allow repeatable --workspace inputs and adjusts settings load to use primary workspace.
packages/cli/src/commands/serve.test.ts Adds parsing tests for single vs repeated --workspace.
.qwen/design/daemon-multi-workspace-phase1-registry.md Design note documenting Phase 1 registry scope/bounds and verification.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/cli/src/serve/server/telemetry.ts
Comment thread packages/cli/src/commands/serve.ts Outdated
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Code Review

Clean implementation. The registry module (workspace-registry.ts) is 36 lines — an interface, a frozen list, and an exact-match lookup. No over-engineering.

The server.ts changes are mechanical: every reference to bridge, boundWorkspace, workspace is replaced with primaryBridge, primaryBoundWorkspace, primaryWorkspace extracted from workspaceRegistry.primary. This is the right pattern — no route signatures change, the boundary is purely at the assembly layer.

Telemetry middleware (telemetry.ts): signature changed from (boundWorkspace: string, ...) to (resolveWorkspaceCwd: (req) => string, ...). The workspace hash now computes per-request instead of being closed over at startup, with memoization by cwd. Correct for future multi-workspace routing, zero behavior change in Phase 1 (always resolves to primary).

Daemon identity (daemon-logger.ts): daemon:<pid> replaces serve-<pid>-<hash>. Log file name is serve-<pid>.log. Workspace hash moves to log record context metadata. Clean migration.

Workspace arg handling (serve.ts + run-qwen-serve.ts): ServeArgs.workspace widened to string | string[] for yargs. resolveSingleWorkspaceInput in the runtime correctly handles all shapes (string, single-element array, multi-element array → boot error, undefined → cwd). One observation: the yargs option definition uses type: 'string' without array: true. In my real-CLI test, repeated --workspace /tmp/a --workspace /tmp/b did NOT trigger the boot guard — the daemon started and bound to /tmp/b (the last value). The unit tests pass because .parseSync() outside command mode produces an array, but yargs in command mode with type: 'string' appears to take the last value instead. This means the repeated-workspace boot guard is effectively inert from the actual CLI. Not a correctness issue for Phase 1 (single-workspace behavior is unchanged), but array: true should be added before Phase 2 relies on array-aware parsing.

Reuse check: no new utility functions that duplicate existing infrastructure. The registry is genuinely new surface.

No critical blockers found. No AGENTS.md violations.

Real-Scenario Testing

Built the PR branch (npm run build && npm run bundle), booted the daemon, tested API, log naming, and daemon status.

Daemon startup (tmux)

$ node packages/cli/dist/index.js serve --port 0 --hostname 127.0.0.1 --workspace /tmp/triage-ws-6394 2>&1 | tee /tmp/triage-daemon-6394.log
qwen serve: daemon log → /tmp/triage-5738b-214806/qwen-home/debug/daemon/serve-1553120.log
qwen serve: Web Shell UI served from .../packages/web-shell/dist
qwen serve listening on http://127.0.0.1:38719 (mode=http-bridge, workspace=/tmp/triage-ws-6394)
qwen serve: bound to workspace "/tmp/triage-ws-6394"
qwen serve: startup timing: processToListenMs=170 runQwenServeToListenMs=48
qwen serve: bearer auth disabled (loopback default). Set QWEN_SERVER_TOKEN to enable.

/capabilities endpoint

$ curl -s http://127.0.0.1:38719/capabilities | python3 -m json.tool
{
    "v": 1,
    "protocolVersions": {"current": "v1", "supported": ["v1"]},
    "qwenCodeVersion": "0.19.6",
    "mode": "http-bridge",
    "features": ["health", "daemon_status", "capabilities", "session_create", ...],
    "workspaceCwd": "/tmp/triage-ws-6394",
    ...
}

Daemon status (new daemon-scoped identity)

$ curl -s http://127.0.0.1:38719/daemon/status | python3 -m json.tool
{
    "v": 1,
    "detail": "summary",
    "status": "ok",
    "daemon": {
        "pid": 1553120,
        "daemonId": "daemon:1553120",
        "mode": "http-bridge",
        "workspaceCwd": "/tmp/triage-ws-6394",
        ...
    }
}

Daemon log file (new naming: serve-<pid>.log)

$ ls -la debug/daemon/
serve-1553120.log     ← daemon-scoped naming confirmed
latest -> serve-1553120.log

Daemon log content (workspace hash as metadata, daemon identity is pid-scoped)

$ head -1 debug/daemon/serve-1553120.log
2026-07-06T13:50:17.024Z [INFO] [DAEMON] workspace=/tmp/triage-ws-6394 workspaceHash=281e9df9 daemon started pid=1553120

Repeated --workspace from CLI (boot guard NOT triggered)

$ node packages/cli/dist/index.js serve --port 0 --hostname 127.0.0.1 --workspace /tmp/triage-ws-6394 --workspace /tmp/triage-ws-secondary 2>&1
qwen serve: daemon log → .../debug/daemon/serve-1583498.log
qwen serve listening on http://127.0.0.1:36799 (mode=http-bridge, workspace=/tmp/triage-ws-secondary)
qwen serve: bound to workspace "/tmp/triage-ws-secondary"

⚠️ The daemon started with the second workspace instead of rejecting. This confirms the yargs type: 'string' option without array: true takes the last value in command mode. The resolveSingleWorkspaceInput guard never sees an array.

Unit tests (all 821 pass)

 ✓ src/commands/serve.test.ts (28 tests)
 ✓ src/serve/daemon-logger.test.ts (21 tests) 188ms
 ✓ src/serve/run-qwen-serve.test.ts (131 tests)
 ✓ src/serve/server/telemetry.test.ts (8 tests) 9ms
 ✓ src/serve/workspace-registry.test.ts (2 tests) 4ms
 ✓ src/serve/server.test.ts (600 tests)
 ✓ src/serve/routes/workspace-file-read.test.ts (31 tests)

 Test Files  7 passed (7)
      Tests  821 passed (821)

Build and typecheck both pass cleanly.

中文说明

代码审查

实现干净。Registry 模块(workspace-registry.ts)36 行——接口、冻结列表、精确匹配查找。无过度工程。

server.ts 变更是机械性的:所有 bridge/boundWorkspace/workspace 引用替换为从 workspaceRegistry.primary 提取的 primaryBridge/primaryBoundWorkspace/primaryWorkspace。这是正确的模式——路由签名不变,边界纯粹在装配层。

Telemetry 中间件:签名从 (boundWorkspace: string, ...) 改为 (resolveWorkspaceCwd: (req) => string, ...)。workspace hash 改为每次请求计算并缓存。对未来 multi-workspace 路由正确,Phase 1 零行为变化。

Daemon identitydaemon:<pid> 替代 serve-<pid>-<hash>。日志文件名 serve-<pid>.log。workspace hash 移至日志记录上下文元数据。迁移干净。

Workspace 参数处理ServeArgs.workspace 放宽为 string | string[]。运行时 resolveSingleWorkspaceInput 正确处理所有形态。观察:yargs option 定义为 type: 'string' 没有 array: true,在实际 CLI 中重复 --workspace 不触发 boot guard(daemon 使用最后一个值启动)。单元测试通过因为脱离了 command 模式。Phase 1 不阻塞,但 Phase 2 之前需要加 array: true

无关键阻塞项。无 AGENTS.md 违规。

真实场景测试

从 PR 分支构建启动 daemon,验证了启动、API、日志命名和 daemon status。daemon 日志文件确认为 serve-<pid>.log(daemon-scoped),日志内容中 workspace hash 作为元数据出现。daemon status 返回 daemonId: "daemon:1553120"。重复 --workspace 从实际 CLI 不触发 boot guard(yargs 在 command 模式下取最后一个值)。821 个单元测试全部通过,构建和类型检查均通过。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Final Decision: ✅ Approve

Gate Summary

Stage Result
Stage 0 (Scope) All changes in packages/cli/src/ — no core modules touched. Two-tier gate does not apply.
Stage 1 (Direction) Template complete ✓ · PR description matches code ✓ · Aligned with Phase 1 plan in #6378 ✓ · Approach sound ✓
Stage 2 (Review + Test) Code clean, no blockers · 821 tests pass · Real-scenario: daemon boots, API responds, log naming correct · Build + typecheck pass

Decision Rationale

This PR is a clean Phase 1 foundation change: introduce a WorkspaceRegistry abstraction, rename internal variables to primary* for future multi-workspace support, migrate daemon identity from workspace-scoped to daemon-scoped (daemon:<pid>), and add a boot guard for repeated --workspace args.

No behavioral change for end users in Phase 1 — the daemon still binds to a single workspace. The changes are purely structural preparation for Phase 2.

Observations (non-blocking)

  1. Yargs array: true missing: The --workspace option is defined as type: 'string' without array: true. The resolveSingleWorkspaceInput boot guard for repeated --workspace values works in unit tests (which call .parseSync() outside command mode) but is inert from the actual CLI. In command mode, yargs takes the last value rather than accumulating into an array. This should be fixed before Phase 2 relies on array-aware parsing. Filed as an observation, not a blocker — Phase 1 behavior is unchanged regardless.

Cross-repo Guardrail Check

  • PR is from a fork (cross-repo) ✓
  • PR title: feat(cli): Add Phase 1 workspace runtime registry — this is a feature, not a refactor
  • Cross-repo refactor guardrail: does not apply (title prefix is feat, not refactor)
  • Auto-approve: allowed

Approval

gh pr review 6394 --repo QwenLM/qwen-code --approve
中文说明

最终决定:✅ 批准

门禁总结

阶段 结果
Stage 0(范围) 所有变更在 packages/cli/src/ — 未触及核心模块。两级门禁不适用。
Stage 1(方向) 模板完整 ✓ · PR 描述与代码一致 ✓ · 与 #6378 Phase 1 计划对齐 ✓ · 方案合理 ✓
Stage 2(审查+测试) 代码干净无阻塞 · 821 个测试通过 · 真实场景:daemon 启动、API 响应、日志命名正确 · 构建和类型检查通过

决策理由

这是 Phase 1 的基础变更:引入 WorkspaceRegistry 抽象、重命名内部变量为 primary*、将 daemon identity 从 workspace-scoped 迁移到 daemon-scoped、添加重复 --workspace 启动守卫。

Phase 1 对终端用户无行为变化,纯粹是 Phase 2 的结构性准备。

观察项(非阻塞)

  1. Yargs 缺少 array: true--workspace option 定义为 type: 'string'array: true,导致实际 CLI 中重复 --workspace 的 boot guard 不生效。Phase 1 不阻塞,Phase 2 前需修复。

跨仓库门禁检查

  • PR 来自 fork(跨仓库)✓
  • PR 标题前缀为 feat,非 refactor — 跨仓库 refactor 门禁不适用
  • 自动批准:允许

Qwen Code · qwen3.7-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.

LGTM, looks ready to ship. ✅

@doudouOUC
doudouOUC requested review from wenshao and yiliang114 July 6, 2026 12:29
@doudouOUC doudouOUC self-assigned this Jul 6, 2026
Memoize daemon telemetry workspace hashes and let runQwenServe honestly accept yargs workspace array inputs while keeping internal ServeOptions single-workspace.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@samuelhsin samuelhsin 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 against the Phase 1 scope agreed in #6378 — the PR matches it: single-runtime WorkspaceRegistry wrapper, daemon-scoped log/telemetry identity, request-time telemetry workspace resolution, and repeatable --workspace input handling with a clear pre-boot error for multiple values. The primaryBridge/primaryWorkspace/primaryRouteFileSystemFactory switches in server.ts are pure aliases of the same objects, so route/session behavior is unchanged as intended.

Things I specifically verified, in case they save others the same pass:

  • Early opts.workspace resolution breaks no explicitness checks. After resolveSingleWorkspaceInput normalizes the value at options construction, the only remaining consumer is the createServeApp fallback canonicalizeWorkspace(opts.workspace ?? process.cwd()) (server.ts:315), which now receives the same resolved value — no production path branches on workspace === undefined anymore.
  • The daemon:<pid> colon is safe. Remaining getDaemonId() consumers are JSON payloads (daemon-status.ts:319-320, run-qwen-serve.ts:1137-1138); the one filename consumer, finalizeStartupProfile, was switched to serve-${process.pid} in this PR, which avoids the Windows-invalid colon.
  • Registry lookup semantics match the RFC rule. getByWorkspaceCwd is exact-match with trailing-slash/nested-path cases tested returning undefined; canonicalization stays with the future resolver, as specified.
  • The multi-value boot guard fires before any runtime side effects (token/bridge/listener), and a single-element array degrades to the existing single-workspace path — both covered by tests.

One non-blocking note for the release-notes callout this PR already plans: with the workspace hash removed from the log filename, a recycled pid can append a different workspace's daemon log to the same serve-<pid>.log. Each line carries workspaceHash so entries stay distinguishable, and same-workspace pid-reuse append was already possible today — fine to leave as-is, just worth a sentence alongside the identity-migration note.

LGTM.

中文说明

#6378 约定的 Phase 1 范围逐项核对,本 PR 完全一致:单 runtime 的 registry 包装(server.tsprimary* 替换是同对象纯别名,路由/会话行为不变)、daemon-scoped 身份迁移、telemetry 按请求解析 workspace、--workspace 多值在 runtime boot 前明确报错。

已专门验证的点:opts.workspace 提前解析后没有破坏任何"是否显式传参"判断(仅剩 server.ts:315 兜底且值相同);daemon:<pid> 的冒号安全(其余消费者都是 JSON,唯一文件名用途 finalizeStartupProfile 本 PR 已同步改为 serve-<pid>,避开 Windows 非法字符);registry 精确匹配语义符合 RFC(canonicalize 留给后续 resolver);多值 boot 守卫在任何 runtime 副作用之前触发,单元素数组退化为现有单 workspace 路径,均有测试。

一个不阻塞的备注:日志文件名去掉 workspace hash 后,pid 复用时不同 workspace 的日志可能追加进同一个 serve-<pid>.log;每行带 workspaceHash 可区分,且同 workspace 的 pid 复用追加是既有行为——保持现状即可,建议在 identity 迁移的 release note 里带一句。

LGTM.

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

No review findings at high confidence. All 790 tests pass, deterministic analysis (tsc + eslint) is clean. Downgraded from Approve to Comment: CI still running.

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

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

Approved via triage pipeline. Clean Phase 1 foundation: WorkspaceRegistry abstraction, daemon identity migration, boot guard for repeated --workspace. All 821 tests pass, real-scenario verified. One non-blocking observation: add array:true to yargs --workspace option before Phase 2.

@wenshao
wenshao added this pull request to the merge queue Jul 6, 2026
Merged via the queue into QwenLM:main with commit 3744cd0 Jul 6, 2026
35 checks passed
doudouOUC added a commit to doudouOUC/qwen-code that referenced this pull request Jul 6, 2026
Make repeated --workspace values reach the serve runtime guard in both the yargs and fast-path CLI entrypoints.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
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