Skip to content

fix(serve): Route session continue, language, and artifacts by owner - #6833

Merged
wenshao merged 2 commits into
QwenLM:mainfrom
doudouOUC:fix/session-owner-mutations
Jul 13, 2026
Merged

fix(serve): Route session continue, language, and artifacts by owner#6833
wenshao merged 2 commits into
QwenLM:mainfrom
doudouOUC:fix/session-owner-mutations

Conversation

@doudouOUC

@doudouOUC doudouOUC commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This PR routes the legacy REST mutations for continuing a session, changing its language, adding an artifact, and deleting an artifact through the runtime that owns the live session. It preserves the existing archive lease, request validation, authentication gates, bridge error mapping, request and response shapes, and the requirement that artifact mutations target a live session. The protocol documentation now lists these routes as owner-routed, while the historical Phase 2a design notes that its original primary-only limitation has been superseded.

Why it's needed

Trusted secondary-workspace sessions can already be resolved to their owning runtime, but these four mutations still used the primary-only guard and returned non_primary_session_route_not_supported. That prevented clients from continuing interrupted turns, changing output language, or managing artifacts for an otherwise valid secondary session. This is the P0 owner-routing portion of #6378 and follows the same incremental routing pattern as #6798.

Reviewer Test Plan

How to verify

Start a daemon with a primary workspace and one trusted secondary workspace, create a live session in the secondary workspace, and complete at least one turn before testing continue. Confirm that language changes, artifact add/delete, and continue all succeed against the secondary session and invoke only the secondary runtime. Confirm that continue preserves the optional client identity and produces a non-empty unique prompt identifier; language preserves the requested language, output-language synchronization flag, and optional client identity; artifact mutations preserve the artifact payload or artifact identifier and required client identity. Also confirm that primary and single-workspace sessions retain their existing behavior, untrusted owners return 403 untrusted_workspace, missing owners return 404 session_not_found without falling back to primary, ambiguous ownership returns 500 ambiguous_session_owner, continue and artifact mutations still require authentication, and language keeps its existing non-strict authentication behavior.

Automated verification passed on the latest main: the multi-workspace session suite passed 76/76, the serve regression suite passed 693/693, and the repository build and typecheck completed successfully. Formatting and lint checks for the changed files also passed.

Evidence (Before & After)

Before: with global Qwen Code 0.19.9, all four requests against a trusted secondary session returned 400 non_primary_session_route_not_supported.

After: with the local bundle, language change and artifact add/delete returned 200; continue returned 200 with accepted: true and a new prompt identifier after an interrupted turn. Requests were handled by the secondary runtime rather than the primary runtime.

Tested on

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

Environment (optional)

macOS, Node.js v22.22.3, npm 10.9.8, local build and bundle, sandbox disabled.

Risk & Scope

  • Main risk or tradeoff: Incorrect owner resolution could mutate the wrong workspace runtime; the coverage explicitly checks secondary-only dispatch, primary non-regression, missing and ambiguous ownership, trust boundaries, authentication, and argument forwarding.
  • Not validated / out of scope: This PR changes only legacy REST owner routing. Artifact operations over ACP-over-HTTP continue to use the runtime bound to their dispatcher, and legacy session-route telemetry may still use the primary workspace hash. Branch/fork admission, cd ownership, export, runtime removal, and new capabilities remain out of scope. The branch is rebased onto main after feat(serve): support multi-workspace rewind and shell #6826 merged.
  • Breaking changes / migration notes: None. No URL, capability, SDK API, type, response field, or validation contract changes.

Linked Issues

Refs #6378

Related: #6826

中文说明

本 PR 做了什么

本 PR 将继续会话、修改会话语言、添加 artifact 和删除 artifact 这四个 legacy REST mutation 路由到拥有该 live session 的 runtime。现有的 archive lease、请求校验、鉴权 gate、bridge 错误映射、请求与响应结构以及 artifact mutation 必须针对 live session 的约束均保持不变。协议文档现已将这些路由列为 owner-routed,历史 Phase 2a 设计文档也注明其最初的 primary-only 限制已被后续实现取代。

为什么需要它

可信 secondary workspace 中的 session 已经能够解析到其 owning runtime,但这四个 mutation 仍使用 primary-only guard,并返回 non_primary_session_route_not_supported。这导致客户端无法为一个原本有效的 secondary session 继续被中断的 turn、修改输出语言或管理 artifact。本 PR 是 #6378 中 P0 owner-routing 的部分,并遵循与 #6798 相同的增量路由模式。

Reviewer 测试计划

如何验证

启动一个包含 primary workspace 和一个可信 secondary workspace 的 daemon,在 secondary workspace 中创建 live session,并在测试 continue 前至少完成一个 turn。确认 language change、artifact add/delete 和 continue 均能针对 secondary session 成功,并且只调用 secondary runtime。确认 continue 保留可选 client identity 并生成非空且唯一的 prompt identifier;language 保留请求的 language、output-language synchronization flag 和可选 client identity;artifact mutation 保留 artifact payload 或 artifact identifier 以及必需的 client identity。还需确认 primary 和 single-workspace session 保持现有行为,untrusted owner 返回 403 untrusted_workspace,missing owner 返回 404 session_not_found 且不 fallback 到 primary,ambiguous ownership 返回 500 ambiguous_session_owner,continue 和 artifact mutation 仍要求鉴权,而 language 保持现有的非 strict 鉴权行为。

在最新 main 上自动化验证已通过:multi-workspace session 测试 76/76 通过,serve 回归测试 693/693 通过,仓库 build 和 typecheck 成功完成。变更文件的 formatting 和 lint 检查也已通过。

证据(修改前与修改后)

修改前:使用全局 Qwen Code 0.19.9 时,针对可信 secondary session 的四个请求均返回 400 non_primary_session_route_not_supported

修改后:使用本地 bundle 时,language change 和 artifact add/delete 返回 200;在 turn 被中断后,continue 返回 200accepted: true 和新的 prompt identifier。请求由 secondary runtime 而不是 primary runtime 处理。

测试平台

OS 状态
🍏 macOS ✅ 已测试
🪟 Windows ⚠️ 未测试
🐧 Linux ⚠️ 未测试

环境(可选)

macOS、Node.js v22.22.3、npm 10.9.8、本地 build 和 bundle、禁用 sandbox。

风险与范围

  • 主要风险或权衡:错误的 owner resolution 可能 mutation 到错误的 workspace runtime;测试覆盖明确验证了仅向 secondary dispatch、primary 行为不回归、missing 和 ambiguous ownership、trust boundary、鉴权以及参数透传。
  • 未验证或不在范围内:本 PR 只修改 legacy REST owner routing。ACP-over-HTTP 的 artifact 操作继续使用其 dispatcher 绑定的 runtime,legacy session-route telemetry 仍可能使用 primary workspace hash。Branch/fork admission、cd ownership、export、runtime removal 和新增 capability 仍不在范围内。feat(serve): support multi-workspace rewind and shell #6826 合入后,本分支现已 rebase 到 main
  • Breaking change 或迁移说明:无。没有 URL、capability、SDK API、类型、响应字段或校验契约变更。

关联 Issue

Refs #6378

Related: #6826

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

E2E test report

Tested on macOS with Node.js v22.22.3, using a primary workspace plus a trusted secondary workspace and bearer authentication.

  • Baseline (qwen 0.19.9): continue, language change, artifact add, and artifact delete each returned 400 non_primary_session_route_not_supported for the secondary session.
  • Local bundle: language change returned 200 and applied to the secondary session; artifact add and delete each returned 200; continue returned 200 with accepted: true and a new prompt identifier after cancelling an active turn.
  • Automated boundary coverage: untrusted owner (403), unknown owner (404 without primary fallback), ambiguous owner (500), authentication behavior, primary/single-workspace compatibility, argument forwarding, and secondary-only bridge dispatch.

Automated results: build passed, typecheck passed, multi-workspace session tests passed 75/75, and serve regression tests passed 692/692.

@doudouOUC
doudouOUC marked this pull request as ready for review July 13, 2026 15:44
@doudouOUC
doudouOUC requested review from Copilot and wenshao July 13, 2026 15:44

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed bug with evidence. The PR documents that continue, language, artifact add, and artifact delete against trusted secondary sessions returned 400 non_primary_session_route_not_supported on baseline (Qwen Code 0.19.9), and the E2E test report confirms the fix on the local bundle.

Direction: aligned. This is the P0 owner-routing portion of #6378, following the same incremental pattern as #6798. The approach — switching route wrappers to owner-aware variants — is consistent with previously merged work.

Size: no core paths touched (packages/core/src/** untouched). Production logic: ~252 lines across packages/cli/src/serve/ (~137 lines) and packages/sdk-typescript/src/daemon/ (~34 lines), plus ~81 lines of docs. Test coverage: ~1,285 lines. Well within normal bounds.

Approach: the scope is mostly minimal — the route handler changes are surgical wrapper swaps (withMutableSessionwithOwnerMutableSession, withOwnerReadSession for rewind snapshots). The SDK restFetch addition to force rewind through REST even with ACP transport is a clean design choice. One observation: the PR title says "continue, language, and artifacts" but the diff also converts shell and rewind to owner routing, adds rewindFiles validation, extends daemon telemetry with session owner attribution, and introduces two new capability flags (multi_workspace_session_rewind, multi_workspace_session_shell). The PR body mentions "these four mutations" matching the title scope, but the actual diff goes broader. Not a blocker — the changes are related and the design doc covers them — but the title undersells the scope. Worth updating for accuracy.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的 bug,有复现证据。PR 记录了在基线版本(Qwen Code 0.19.9)中,针对可信 secondary session 的 continue、language、artifact add 和 artifact delete 返回 400 non_primary_session_route_not_supported,E2E 测试报告确认本地构建已修复。

方向:对齐。这是 #6378 的 P0 owner-routing 部分,遵循与 #6798 相同的增量模式。方案——将路由 wrapper 切换为 owner-aware 变体——与已合入的工作一致。

规模:未触及核心路径(packages/core/src/** 未修改)。生产逻辑约 252 行,分布在 packages/cli/src/serve/(约 137 行)和 packages/sdk-typescript/src/daemon/(约 34 行),另有约 81 行文档。测试覆盖约 1,285 行。在正常范围内。

方案:范围基本精简——路由 handler 的改动是精确的 wrapper 替换(withMutableSessionwithOwnerMutableSession,rewind snapshots 用 withOwnerReadSession)。SDK 中新增 restFetch 使 rewind 即使在 ACP transport 下也走 REST 是合理的设计。一个观察:PR 标题写的是"continue, language, and artifacts",但 diff 还包含了 shell 和 rewind 的 owner routing 转换、rewindFiles 校验、daemon telemetry 的 session owner 归属扩展,以及两个新的 capability flag(multi_workspace_session_rewindmulti_workspace_session_shell)。PR 正文提到的"四个 mutation"与标题范围一致,但实际 diff 范围更广。不是阻塞问题——改动相关且设计文档已覆盖——但标题低估了范围,建议更新以准确反映。

进入代码审查 🔍

Qwen Code · qwen3.7-max

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC
doudouOUC force-pushed the fix/session-owner-mutations branch from 1886969 to 7f1d780 Compare July 13, 2026 16:01
@doudouOUC doudouOUC self-assigned this Jul 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration.

中文

请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal (before reading the diff): introduce owner-aware route wrappers for the four primary-only session mutations, using the same resolveLiveSessionRuntime pattern established by the stacking dependency (#6826). Add restFetch to the SDK transport interface so rewind stays on REST even with ACP configured.

Comparison with the diff: the PR's approach matches this proposal. The route handler changes are minimal wrapper swaps, the error handling (403/404/500) is consistent with other owner-routed routes, and the SDK restFetch pattern is clean — optional on the interface, fallback chain in DaemonClient (opts.fetch ?? opts.transport?.restFetch ?? globalThis.fetch).

No critical blockers found. The implementation is correct and well-structured:

  • withOwnerMutableSession and withOwnerReadSession (from feat(serve): support multi-workspace rewind and shell #6826) properly resolve the session owner via resolveLiveSessionRuntime and dispatch to the right bridge. Error codes follow the established pattern.
  • rewindFiles validation is correct: rejects non-boolean with 400, defaults to true when omitted, passes false through.
  • Shell abort signal propagation on HTTP disconnect is properly wired through req.once('close', ...) with cleanup.
  • The AcpWsTransport now takes restFetch as a constructor param, and negotiateTransport passes the negotiated fetchFn — so rewind uses the correct fetch even when the primary channel is WebSocket.
  • Telemetry middleware's optional third param (resolveSessionWorkspaceCwd) is backward-compatible.

One minor concern: the AGENTS.md edit (clarifying /review means Codex code-review workflow, not Qwen Review) is unrelated to the session routing changes. This is a documentation correction, but it should ideally be in a separate commit or PR to keep the diff focused.

Testing

Build: passed ✓
Typecheck: passed ✓

Test file Result
multi-workspace-sessions.test.ts 75/75 ✓
server.test.ts 692/692 ✓
telemetry.test.ts 14/14 ✓
DaemonClient.test.ts 238/238 ✓
workspace-qualified-acp.test.ts 29/29 ✓
transport.test.ts 272/272 ✓
AutoReconnectTransport.test.ts 19/19 ✓
acpRouteTable.test.ts 102/102 ✓

Test coverage pins owner dispatch, zero calls to non-owning bridges, trust/ambiguity failures, rewindFiles semantics, SDK REST fallback, shell abort propagation, conditional capability advertising, and ACP route table exclusion for rewind.

Real-scenario tmux testing is not feasible in this environment — the scenario requires a daemon with primary + trusted secondary workspace and live session state, which cannot be set up in this CI runner. The author's own E2E report (baseline vs local bundle) covers the before/after.

中文说明

代码审查

独立方案(阅读 diff 前):为四个 primary-only 的 session mutation 引入 owner-aware 路由 wrapper,使用 stacking 依赖(#6826)中建立的 resolveLiveSessionRuntime 模式。在 SDK transport 接口中添加 restFetch,确保 rewind 即使在 ACP transport 下也走 REST。

与 diff 的对比: PR 的方案与独立方案一致。路由 handler 改动是最小化的 wrapper 替换,错误处理(403/404/500)与其他 owner-routed 路由一致,SDK restFetch 模式简洁——接口上可选,DaemonClient 中有回退链(opts.fetch ?? opts.transport?.restFetch ?? globalThis.fetch)。

未发现关键阻塞问题。 实现正确且结构良好:

  • withOwnerMutableSessionwithOwnerReadSession(来自 feat(serve): support multi-workspace rewind and shell #6826)正确通过 resolveLiveSessionRuntime 解析 session owner 并分发到对应 bridge。错误码遵循已建立的模式。
  • rewindFiles 校验正确:非 boolean 返回 400,省略时默认 truefalse 正常传递。
  • Shell 的 HTTP 断开 abort signal 传播通过 req.once('close', ...) 正确连线并清理。
  • AcpWsTransport 现在接受 restFetch 构造参数,negotiateTransport 传递协商后的 fetchFn——rewind 即使主通道是 WebSocket 也使用正确的 fetch。
  • Telemetry middleware 的可选第三参数(resolveSessionWorkspaceCwd)向后兼容。

一个小问题: AGENTS.md 的修改(澄清 /review 指 Codex 代码审查工作流,不是 Qwen Review)与 session 路由改动无关。虽然是文档修正,但理想情况下应在单独的 commit 或 PR 中以保持 diff 聚焦。

测试

Build: 通过 ✓
Typecheck: 通过 ✓

测试文件 结果
multi-workspace-sessions.test.ts 75/75 ✓
server.test.ts 692/692 ✓
telemetry.test.ts 14/14 ✓
DaemonClient.test.ts 238/238 ✓
workspace-qualified-acp.test.ts 29/29 ✓
transport.test.ts 272/272 ✓
AutoReconnectTransport.test.ts 19/19 ✓
acpRouteTable.test.ts 102/102 ✓

测试覆盖固定了 owner dispatch、非 owning bridge 零调用、trust/ambiguity 失败、rewindFiles 语义、SDK REST 回退、shell abort 传播、条件 capability 广播以及 ACP 路由表排除 rewind。

真实场景 tmux 测试在当前环境不可行——该场景需要带有 primary + 可信 secondary workspace 的 daemon 和 live session 状态,无法在此 CI runner 中设置。作者自己的 E2E 报告(基线 vs 本地构建)覆盖了 before/after。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

This is a solid, well-tested piece of incremental multi-workspace routing work. The problem is real (secondary sessions were completely blocked from continue, language, and artifact operations), the before/after reproduction is documented, and the approach is the minimal change needed — wrapper swaps in session.ts plus a clean restFetch addition to the SDK transport interface.

The implementation matches what I'd have proposed independently. The test coverage is thorough: 75 multi-workspace session tests pinning owner dispatch, trust boundaries, ambiguity handling, and validation ordering; 692 serve regression tests confirming no breakage; plus SDK tests verifying the REST fallback for rewind with ACP transport.

Two minor hygiene items (not blocking):

  • The title says "continue, language, and artifacts" but the diff also converts shell and rewind to owner routing, adds telemetry attribution, and introduces two capability flags. Consider updating the title to reflect the actual scope.
  • The AGENTS.md edit (clarifying /review semantics) is unrelated to this PR's routing changes. A separate commit would keep the diff focused.

Approving. ✅

中文说明

这是一个扎实、测试充分的增量多 workspace 路由改动。问题是真实的(secondary session 完全无法使用 continue、language 和 artifact 操作),有 before/after 复现记录,方案也是最小必要改动——session.ts 中的 wrapper 替换加上 SDK transport 接口中简洁的 restFetch 新增。

实现与我独立提出的方案一致。测试覆盖全面:75 个多 workspace session 测试固定了 owner dispatch、trust boundary、ambiguity 处理和校验顺序;692 个 serve 回归测试确认无破坏;SDK 测试验证了 ACP transport 下 rewind 的 REST 回退。

两个非阻塞的小建议:

  • 标题写的是"continue, language, and artifacts",但 diff 还包含了 shell 和 rewind 的 owner routing 转换、telemetry 归属和两个新 capability flag。建议更新标题以反映实际范围。
  • AGENTS.md 的修改(澄清 /review 含义)与本 PR 的路由改动无关。单独的 commit 可以让 diff 更聚焦。

批准 ✅

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

yiliang114
yiliang114 previously approved these changes Jul 13, 2026

@yiliang114 yiliang114 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 — routing through withOwnerMutableSession is the right pattern, auth gates are preserved, single-workspace deployments are unaffected.

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

Reviewed — no blockers. Suggestions are inline.

Comment thread packages/cli/src/serve/multi-workspace-sessions.test.ts Outdated
Comment thread packages/cli/src/serve/multi-workspace-sessions.test.ts
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC
doudouOUC dismissed stale reviews from yiliang114 and qwen-code-ci-bot via 4a67ee8 July 13, 2026 17:16

@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 issues found. LGTM! ✅

— qwen3.7-max via Qwen Code /review

@wenshao wenshao 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 — no blockers. Suggestions are inline.

— qwen3.7-max via Qwen Code /review

Comment thread packages/cli/src/serve/routes/session.ts
Comment thread packages/cli/src/serve/routes/session.ts
@wenshao

wenshao commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

✅ Maintainer local verification — merge reference

I built and ran this PR from a real local build in an isolated worktree at the PR head (4a67ee8bf, on top of fix/session-owner-mutations). Every check below was executed against compiled sources — this is not a paper review.

Verification summary

What the change does

Four legacy REST mutations — POST /session/:id/continue, POST /session/:id/language, POST /session/:id/artifacts, DELETE /session/:id/artifacts/:artifactId — are moved from the primary-only withMutableSession to the owner-routed withOwnerMutableSession, and now dispatch to runtime.bridge.* (the runtime that owns the live session) instead of the primary bridge. Net source delta: +14 / −16 in packages/cli/src/serve/routes/session.ts.

Results

Check Command Result
Targeted suite vitest run src/serve/multi-workspace-sessions.test.ts 76 passed (76) — incl. 5 new routing tests
Full serve regression vitest run src/serve 2753 passed · 1 skipped (84 files)
Typecheck tsc --noEmit (@qwen-code/qwen-code) exit 0
ESLint eslint … --max-warnings 0 on changed files exit 0
Prettier prettier --check on all 4 changed files clean

Test run

The five new tests assert exactly the contract in the PR's reviewer plan: owner dispatch to the secondary bridge (never the primary); promptId is non-empty and unique per continue; language/artifact payloads are forwarded verbatim; untrusted → 403, missing → 404 (no primary fallback), ambiguous → 500; continue/artifacts stay auth-gated while language keeps its existing non-strict gate; and primary/single-workspace routing is unchanged.

Load-bearing controlled experiment

To prove the tests actually exercise the fix (and aren't vacuous), I reverted only the 4-route source change back to its pre-PR state while keeping the new tests, then re-ran them:

Load-bearing experiment

  • The two tests that assert the newly-enabled behavior flip red with AssertionError: expected 400 to be 200 — i.e. without the fix, a trusted secondary session still returns 400 non_primary_session_route_not_supported.
  • The three boundary/regression tests (403 untrusted / 404 missing / 500 ambiguous / primary routing) stay green — they encode invariants the PR preserves.

This is the ideal signature of a tightly-scoped change: the new-behavior assertions are load-bearing, the invariants are untouched. Restoring the fix returns the tree to clean and all five back to green.

Notes for merge

  • The branch base is a few commits behind current main; the touched files (serve/routes/session.ts, the test, two docs) don't overlap the intervening commits, so no conflict is expected — a routine rebase/merge is fine.
  • Independent live multi-workspace daemon exercise is already documented by the author's E2E report above; my verification independently drives the real Express routing stack end-to-end via the integration harness (only the model-facing bridge is faked), which is precisely where the routing decision lives.

Environment: macOS (darwin 24.6.0) · Node v22.23.1 · npm 10.9.8 · npm ci + build:core + workspace vitest.

LGTM from a verification standpoint — routing behavior, trust boundaries, and non-regression are all confirmed. ✅

🇨🇳 中文版本(点击展开)

✅ 维护者本地验证 —— 合并参考

我在一个隔离的 worktree 中,从 PR head(4a67ee8bf,基于 fix/session-owner-mutations)进行了真实的本地构建并运行了全部检查。以下每一项都是针对编译后的源码执行的,并非纸面 review。

该改动做了什么

四个 legacy REST mutation —— POST /session/:id/continuePOST /session/:id/languagePOST /session/:id/artifactsDELETE /session/:id/artifacts/:artifactId —— 从仅限 primary 的 withMutableSession 改为 owner-routed 的 withOwnerMutableSession,现在会 dispatch 到拥有该 live session 的 runtime(runtime.bridge.*),而不是 primary bridge。源码净变化:packages/cli/src/serve/routes/session.ts+14 / −16

验证结果

检查项 命令 结果
目标测试套件 vitest run src/serve/multi-workspace-sessions.test.ts 76 passed (76),含 5 个新增路由测试
serve 完整回归 vitest run src/serve 2753 passed · 1 skipped(84 个文件)
类型检查 tsc --noEmit(@qwen-code/qwen-code) exit 0
ESLint 对改动文件 eslint … --max-warnings 0 exit 0
Prettier 对全部 4 个改动文件 prettier --check 通过

这 5 个新测试正好验证了 PR reviewer 计划中的约束:owner dispatch 到 secondary bridge(绝不落到 primary);每次 continuepromptId 非空且唯一;language/artifact 参数原样透传;untrusted → 403missing → 404(不 fallback 到 primary)、ambiguous → 500continue/artifact 仍需鉴权,而 language 保持其现有的非 strict 鉴权;primary 及单 workspace 路由行为不变。

载荷性对照实验(load-bearing)

为证明这些测试确实覆盖了本次修复(而非空测试),我把这 4 个路由的源码改动回退到 PR 之前的状态、保留新测试,然后重新运行:

  • 断言新行为两个测试会变红:AssertionError: expected 400 to be 200 —— 即没有该修复时,可信 secondary session 仍返回 400 non_primary_session_route_not_supported
  • 三个边界/回归测试(403 untrusted / 404 missing / 500 ambiguous / primary 路由)保持绿色 —— 它们编码了本 PR 所保留的不变量。

这正是一个范围收敛良好的改动应有的特征:新行为断言是载荷性的,不变量则未被触碰。恢复修复后,工作树变干净,5 个测试全部恢复为绿色。

合并注意事项

  • 分支 base 比当前 main 落后若干 commit;改动文件(serve/routes/session.ts、测试、两个文档)与中间 commit 不重叠,预计不会冲突 —— 常规 rebase/merge 即可。
  • 独立的 live 多 workspace daemon 实测已由作者上方的 E2E 报告覆盖;我的验证则通过集成 harness 独立驱动了真实的 Express 路由栈端到端(仅 fake 面向模型的 bridge),而路由决策恰恰就发生在这里。

环境: macOS(darwin 24.6.0)· Node v22.23.1 · npm 10.9.8 · npm ci + 构建 core + workspace vitest。

从验证角度 LGTM —— 路由行为、信任边界、非回归均已确认。✅

Verification run in an isolated worktree; evidence images hosted on branch pr-assets/pr-6833-verify.

@wenshao
wenshao added this pull request to the merge queue Jul 13, 2026
Merged via the queue into QwenLM:main with commit 9dd8389 Jul 13, 2026
69 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.

5 participants