Skip to content

refactor(cli): Generalize the Conversations runtime foundation - #8890

Merged
wenshao merged 12 commits into
QwenLM:mainfrom
doudouOUC:docs/standalone-daemon-sessions-design
Aug 14, 2026
Merged

refactor(cli): Generalize the Conversations runtime foundation#8890
wenshao merged 12 commits into
QwenLM:mainfrom
doudouOUC:docs/standalone-daemon-sessions-design

Conversation

@doudouOUC

@doudouOUC doudouOUC commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This PR implements the PR0 Conversations runtime foundation from the standalone daemon sessions design. It moves the existing Conversations workspace and source helpers out of the Live-specific namespace, introduces a daemon-internal manager that safely creates or adopts the single Conversations runtime, and keeps Live Voice as an adapter that transactionally installs its three bridge handlers.

Live and future standalone sessions can therefore share one Conversations runtime and one ACP bridge. Runtime publication remains lazy with respect to ACP process startup: ensuring the runtime registers the runtime and bridge but does not call ACP preheat, probe the provider, or initialize the native Host. The existing live-conversation provenance, storage layout, relocation token, public dependency field names, persisted metadata, capability behavior, and user-visible Live semantics remain unchanged.

The dedicated Live Host workflow now also runs when the shared Conversations runtime code changes.

Why it's needed

The Conversations runtime lifecycle was previously embedded in Live Voice binding. Future projectless sessions need the same runtime without enabling Live or creating a second projectless runtime, while Live still needs strict ownership validation, one-flight publication, retryable failures, and clean handler teardown.

Separating runtime ownership from the Live adapter establishes that reusable boundary without adding standalone routes, source types, capabilities, SDK APIs, UI, virtual workspaces, per-session ACP children, or cross-daemon ownership.

Reviewer Test Plan

How to verify

Confirm concurrent runtime requests perform one publication, every later reuse revalidates the Conversations root, an existing active owned runtime is adopted, and invalid, draining, blocked, removed, or replaced runtimes fail closed without publishing a replacement or falling back to the primary runtime.

Confirm ensuring the runtime does not call ACP preheat or install Live handlers. With Live enabled, verify boot publication and a concurrent Host hello share the same publication; with Live disabled or ACP HTTP disabled, verify the Conversations root and runtime remain untouched.

Confirm a partial Live handler binding failure clears all three handlers, can retry without republishing the runtime, and invalidates the capability workspace cache as soon as publication succeeds. Confirm shutdown waits for in-flight Live binding, clears all handlers, and leaves runtime/bridge disposal to the existing workspace lifecycle.

Local verification completed with formatting, CLI lint, repository build, repository typecheck, 67 focused Conversations/Live unit tests, 17 Live server regression tests, 101 multi-workspace session tests, and 7 release-workflow tests. The full 933-test server file was also exercised repeatedly; all Live tests passed on every run, while unrelated existing tests showed nondeterministic shared-state failures when the entire file ran together.

Evidence (Before & After)

N/A — internal runtime refactor with no user-visible or TUI change.

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

macOS local checkout with the repository Node.js/npm toolchain; tests used Vitest with coverage disabled to avoid the known shared coverage temporary-directory race.

Risk & Scope

  • Main risk or tradeoff: Runtime publication and Live handler binding now have separate one-flight state, so regressions would most likely appear around concurrent boot/Host requests or shutdown; dedicated manager and server regression tests cover those transitions.
  • Not validated / out of scope: Windows and Linux path behavior was not run locally. Standalone session APIs, capability negotiation, SDK/UI integration, cross-daemon ownership, ordinary workspace isolation, attachments, quotas, Move to project, separate ACP processes, and stronger sandboxing remain follow-up work.
  • Breaking changes / migration notes: No public API, capability, persistence, source, error text, storage layout, or user-visible behavior changes are intended. Internal imports from the old Live-specific helper paths must use the new Conversations paths.

Linked Issues

Refs #8908

中文说明

本 PR 做了什么

本 PR 实现 standalone daemon sessions 设计中的 PR0 Conversations runtime 基础设施。它将现有 Conversations workspace 和 source helper 从 Live 专属命名空间迁出,引入一个 daemon 内部 manager,用于安全地创建或采用唯一的 Conversations runtime,并保留 Live Voice 作为事务式安装三个 bridge handler 的 adapter。

这样 Live 与未来的 standalone 会话可以共用一个 Conversations runtime 和一个 ACP bridge。Runtime publication 对 ACP 进程启动仍保持懒加载:ensure 只注册 runtime 和 bridge,不调用 ACP preheat、不探测 provider、也不初始化原生 Host。现有 live-conversation provenance、存储布局、relocation token、公开依赖字段名、持久化元数据、capability 行为以及 Live 的用户可见语义都保持不变。

Live Host 专用 workflow 现在也会在共享 Conversations runtime 代码变更时运行。

为什么需要

Conversations runtime 生命周期此前嵌在 Live Voice 绑定逻辑中。未来的无项目会话需要在不启用 Live、也不创建第二套 projectless runtime 的情况下复用同一 runtime,同时 Live 仍需要严格的所有权校验、one-flight publication、可重试失败以及干净的 handler 清理。

本次拆分建立了这个可复用边界,同时不增加 standalone 路由、source type、capability、SDK API、UI、虚拟 workspace、每会话 ACP 子进程或跨 daemon ownership。

Reviewer 测试计划

如何验证

确认并发 runtime 请求只执行一次 publication,每次后续复用都会重新校验 Conversations root;确认合法且 active 的已有 owned runtime 会被采用;确认非法、draining、blocked、removed 或被替换的 runtime 会 fail closed,不发布替代 runtime,也不回退 primary runtime。

确认 ensure runtime 不调用 ACP preheat,也不安装 Live handler。Live 启用时,验证 boot publication 与并发 Host hello 共用同一次 publication;Live 禁用或 ACP HTTP 禁用时,验证 Conversations root 和 runtime 完全不被访问或创建。

确认 Live handler 部分绑定失败会清除全部三个 handler,后续可以在不重复发布 runtime 的情况下重试,并且 publication 一成功就会失效 capability workspace cache。确认 shutdown 会等待进行中的 Live binding、清除所有 handler,并继续由既有 workspace 生命周期负责 runtime/bridge 的释放。

本地已完成格式检查、CLI lint、全仓 build、全仓 typecheck、67 个 Conversations/Live 聚焦单测、17 个 Live server 回归测试、101 个 multi-workspace session 测试和 7 个 release-workflow 测试。还重复运行了完整的 933 项 server 测试文件;所有 Live 测试每次都通过,但整文件共同运行时,若干与本 PR 无关的既有测试出现了非确定性的共享状态失败。

证据(Before & After)

N/A —— 内部 runtime 重构,没有用户可见或 TUI 变化。

测试平台

系统 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

macOS 本地 checkout,使用仓库 Node.js/npm 工具链;Vitest 关闭 coverage,以避开已知的共享 coverage 临时目录竞争。

风险与范围

  • 主要风险或权衡:Runtime publication 与 Live handler binding 现在使用独立的 one-flight 状态,因此潜在回归最可能出现在并发 boot/Host 请求或 shutdown 周边;专门的 manager 和 server 回归测试覆盖了这些状态转换。
  • 未验证 / 不在范围内:本地未运行 Windows 与 Linux 路径行为。Standalone session API、capability 协商、SDK/UI 集成、跨 daemon ownership、普通 workspace 隔离、附件、配额、Move to project、独立 ACP 进程和更强沙箱均留给后续工作。
  • 破坏性变更 / 迁移说明:不预期改变任何公开 API、capability、持久化格式、source、错误文本、存储布局或用户可见行为。内部代码需要从新的 Conversations 路径导入原 Live 专属路径下的 helper。

关联 Issue

Refs #8908

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR — re-run triage at head 9d087621 (review round 6 addressed).

Template looks good ✓

Problem: this is PR0 of the standalone daemon sessions design (issue #8908, labeled coding-plan / roadmap/session-management) — a structural precondition, not a bug fix, so the Stage 1 bar is "is the design sanctioned and is the boundary real", not a before/after repro. Both hold: #8908 is the tracked source of truth, and the Conversations runtime lifecycle genuinely lives inside Live Voice binding on main today — ensureLiveConversationRuntime in server.ts inlines publication, adoption, and handler binding into one one-flight.

Direction: aligned. Future projectless sessions need this runtime without a second runtime or an ACP child per chat, and this PR establishes exactly that seam while staying behaviorally invisible — no routes, no capability, no new source type; advertisement is deferred to PR3 by the design. CHANGELOG: no direct reference, but the area is on the roadmap via #8908.

Size: not a core-module change (no packages/core, no auth/providers/models/config/tools/services paths, single package). ~349 production lines vs ~860 test lines vs 1032 doc lines (the design companion) + 1 workflow line — inside the PR0 estimate stated in the design doc, and no size advisory applies.

Approach: matches my independent proposal — move the workspace/source helpers out of the Live namespace, one one-flight ConversationRuntimeManager with fail-closed revalidation and adoption, Live demoted to a transactional three-handler adapter. Scope discipline is good: every edit serves PR0's exit criterion, no drive-by changes. The 1032-line design doc is large, but it is the versioned contract for the whole PR0–PR6 program, committed where AGENTS.md says design docs live.

Risk: Stage 1e high-risk path matched — packages/cli/src/acp-integration/acpAgent.ts. The touch is a one-line import-path update, but that path family has elevated revert correlation, so Stage 2 carries full CI evidence plus the maintainer-sponsored /verify A/B run.

Moving on to code review. 🔍

中文说明

感谢贡献——这是在 head 9d087621(第 6 轮 review 已处理)上的复跑 triage。

模板完整 ✓

问题:这是 standalone daemon sessions 设计的 PR0(issue #8908,带 coding-plan / roadmap/session-management 标签)——结构性前置而非 bug 修复,因此 Stage 1 的标准是"设计是否被认领、边界是否真实",而不是 before/after 复现。两者都成立:#8908 是被跟踪的唯一事实来源,且 Conversations runtime 生命周期目前确实内嵌在 Live Voice 绑定里——main 上 server.ts 的 ensureLiveConversationRuntime 把发布、采用和 handler 绑定揉在同一个 one-flight 中。

方向:对齐。未来无项目会话需要复用该 runtime,且不能引入第二套 runtime 或每会话一个 ACP 子进程;本 PR 恰好建立这条接缝,同时保持行为不可见——无路由、无 capability、无新 source type,按设计推迟到 PR3 才广播。CHANGELOG:无直接引用,但该方向通过 #8908 在路线图上。

规模:非核心模块变更(未触及 packages/coreauth/providers/models/config/tools/services 路径,单包)。约 349 行生产代码、约 860 行测试、1032 行文档(设计伴侣文档)+ 1 行 workflow——在设计文档对 PR0 的估算范围内,也不触发大 PR 提示。

方案:与我独立提出的方案一致——把 workspace/source helper 迁出 Live 命名空间,一个带 fail-closed 重校验与采用逻辑的 one-flight ConversationRuntimeManager,Live 降级为事务式安装三个 handler 的 adapter。范围纪律良好:每处改动都服务于 PR0 的退出标准,无顺手改动。1032 行设计文档较大,但它是整个 PR0–PR6 程序的版本化契约,提交位置符合 AGENTS.md 对设计文档的要求。

风险:Stage 1e 高风险路径命中——packages/cli/src/acp-integration/acpAgent.ts。触碰仅是一行 import 路径更新,但该路径族与合并后回退相关性偏高,因此 Stage 2 携带完整 CI 证据与 maintainer 赞助的 /verify A/B 运行。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at 9d08762121df9918095d08baf2295f43415fe32a · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

📄 Docs-only change (superseded) — this badge no longer reflects the current review state of this PR. See the latest review activity on this PR.

中文说明

📄 纯文档变更 (已失效) —— 该徽章已不再反映本 PR 当前的评审状态。请以本 PR 上最新的评审动态为准。

doudouOUC and others added 3 commits August 12, 2026 18:32
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC
doudouOUC force-pushed the docs/standalone-daemon-sessions-design branch from 4de39f3 to 6d036ae Compare August 12, 2026 10:43
@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)为单个提交。

@doudouOUC doudouOUC changed the title docs: Design standalone daemon sessions refactor(cli): Generalize the Conversations runtime foundation Aug 12, 2026
@doudouOUC
doudouOUC marked this pull request as ready for review August 12, 2026 10:44
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

Built the PR base vs this PR head 9d08762, drove a fixed endpoint set against each, and diffed the JSON responses. Only fields that changed are shown.

No response changes against the PR base across 4 scenario(s).

Qwen Code · serve A/B

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC
doudouOUC requested a review from wenshao August 12, 2026 12:33
@doudouOUC doudouOUC self-assigned this Aug 12, 2026
@doudouOUC
doudouOUC requested a review from yiliang114 August 12, 2026 12:33

@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. Suggestions are inline.

Not explored to full depth (tool budget reached): You are review agent reverse-audit — Reverse audit agen...: none — all checks above were completed within budget.; You are review agent reverse-audit — Reverse audit agen...: none — all checks above completed within budget.; You are review agent reverse-audit — Reverse audit agen...: none — all checks above completed within budget.; You are review agent reverse-audit — Reverse audit agen...: none — all planned checks completed within budget..

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

已审查。 建议见行内评论。

未探索到全部深度(达到工具调用预算):You are review agent reverse-audit — Reverse audit agen...:none — all checks above were completed within budget.;You are review agent reverse-audit — Reverse audit agen...:none — all checks above completed within budget.;You are review agent reverse-audit — Reverse audit agen...:none — all checks above completed within budget.;You are review agent reverse-audit — Reverse audit agen...:none — all planned checks completed within budget.

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— qwen3.8-max via Qwen Code /review (v0.21.10)

Comment thread packages/cli/src/serve/server.ts
Comment thread scripts/tests/release-workflow.test.js Outdated
Comment thread .github/workflows/live-host.yml
Comment thread packages/cli/src/serve/conversations/conversation-runtime-manager.ts Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Clarify standalone transaction recovery outcomes and remove the unused Conversations-only Live Host workflow trigger.

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

Copy link
Copy Markdown
Collaborator Author

[codex] Addressed all 9 actionable R1 review suggestions in d50dbea72a.

Review Resolution
R1-1 Added a successful Live bind → teardown regression assertion covering all three bridge handlers.
R1-2, R1-4 Removed the Conversations-only Live Host CI trigger and its shape-only script test because that job does not consume the Conversations runtime.
R1-3 Added a cached-runtime generation-replacement regression test.
R1-5 Added a post-publication drain/retry regression test.
R1-6–R1-9 Completed the design contract for creation unwind, ACP teardown, UUID release, transcript deletion failure, and restart reconciliation with both private directories absent.

Verification on the pushed commit:

  • Conversations manager + full server tests: 949/949 passed
  • Targeted rerun of two unrelated flakes: 2/2 passed
  • CLI typecheck: passed
  • Release workflow script tests: 6/6 passed
  • Prettier and git diff --check: passed
  • Two consecutive broad diff audits: clean

The PR remains Ready for review; no implementation scope was added beyond the review fixes.

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

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— gpt-5.6-sol via Qwen Code /review (v0.21.10)

Comment thread packages/cli/src/serve/server.ts
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread packages/cli/src/serve/conversations/conversation-runtime-manager.ts Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Harden owned runtime publication and complete the standalone transaction safety contract.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
yiliang114
yiliang114 previously approved these changes Aug 12, 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.

Approving PR0 as a behavior-preserving generalization. Verified against head d50dbea.

Refactor correctness (checked line-by-line vs. the old inline logic in server.ts)

  • Cached / existing-entry / publication paths all preserve the old gate semantics (provenance live-conversation, trusted, removable === false, dev/ino root identity, entry state + generation identity). One intentional difference: a non-active entry at the Conversations root now rejects with "no longer an active owned runtime" instead of falling through to publishOwnedRuntime, which rejected with "Workspace is already registered" — both reject, no behavior regression.
  • The added post-publication re-verification in ConversationRuntimeManager is strictly more defensive than the old code (which never re-checked after publishOwnedRuntime); on failure it fails closed.
  • Handler binding now rolls back cleanly on partial bind, and teardown clears all three bridge handlers via liveBoundRuntime; ordering is safe (workspaceManagementHandle is unconditionally initialized at server.ts:2109 before any ensure() can fire — boot publication is at :2130, route handlers post-setup).
  • Renames are pure: session-source.* 100% moves; conversation-workspace.ts is identifier renames only (logic diffed, unchanged). invalidateServeFeaturesCache moving before handler bind only changes transient cache state; the partial-bind test pins the new behavior.

On the open Criticals in the prior automated review — I verified both code findings independently:

  • assertOwnedRuntime not rejecting runtime.primary: not reachable in this PR. The runtime factory sets primary: buildOptions?.primary ?? false and publishOwnedRuntime never passes primary; a pre-existing primary entry at the same cwd fails the provenance gate. The gate is also unchanged from the pre-refactor code. Reasonable defense-in-depth for PR1, not a blocker here.
  • Post-publication validation leaving a registered runtime: only triggerable by a mid-call root-identity swap (inFlight + registry re-checks already guard concurrency), and the outcome is fail-closed — no crash, no misrouting. The practical case (bind failure after publication) is deliberate reuse-on-retry and is asserted by the new rolls back a partial Live bind test. Worth a cleanup path eventually; P2 at most.
  • The remaining findings target docs/design/standalone-daemon-sessions.md contracts (UUID admission, journal identity binding/discovery, per-session pinning, rollback re-read) that belong to PR1–PR3 scope and are not implemented by this PR. Good follow-up questions for issue #8908 / the later PRs, not blockers for the foundation refactor.

Nits (P3): consider adding runtime.primary to the ownership gate as cheap insurance when PR1 lands; consider a disposal path for a runtime whose post-publication re-verification failed.

Tests: manager suite covers one-flight publication, adoption, cached-removal/replacement rejection, and retry-after-failure; server.test.ts adds concurrent-bind sharing, partial-bind rollback + retry-without-republish, and the speakHandler teardown assertion. Coverage matches the refactor surface.

CI: all checks green on head sha (only the in-progress review-pr job, i.e. this review, is pending).

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

[codex] Addressed all 8 actionable R2 findings in ecfd294969.

Review Resolution
R1-1 Expanded partial Live-handler binding rollback coverage to task and speech setter failures, including cleanup and retry/runtime-reuse assertions.
R1-2 Required daemon-wide standalone UUID admission across active runtimes, active/archived catalogs, Live ownership, and in-flight creation.
R1-3 Rejected primary runtimes at both Conversations adoption and owned-publication gates, with regressions for both paths.
R1-4 Kept newly published owned runtimes non-routable through post-registration root validation and added rollback/disposal on validation failure.
R1-5 Bound deletion recovery to recorded Conversations-root and staged-child filesystem identities, failing closed on mismatch.
R1-6 Located deletion journals beside the stable user-global Conversations owner record, independent of QWEN_RUNTIME_DIR.
R1-7 Pinned each active session child identity and documented the only authorized reset points.
R1-8 Added transcript/sidecar re-read classification after deletion errors: intact, absent, or partial/unknown.

Verification completed on the pushed commit:

  • Conversations manager, workspace management, and full server suites: 1,073/1,073 tests passed.
  • CLI typecheck passed.
  • Prettier and diff checks passed.
  • Two consecutive broad diff audits were clean.
  • Production churn remains 409 lines, below the 500-line core-refactor gate.

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@doudouOUC

doudouOUC commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed all five R4 review suggestions in 9f102ca43b.

Item Action
R4-1 Fixed — aligned PR0 and aggregate test-line estimates with the delivered diff.
R4-2 Fixed — removed duplicate validation and retained one final pre-publication validation callback.
R4-3 Fixed — specified standalone_creation_rolled_back after complete pre-persistence cleanup.
R4-4 Fixed — made PR2 responsible for explicit standalone and parent-chain source classification.
R4-5 Fixed — specified outcome-unknown preservation and exact lookup when the relocated child cannot be removed.

Verification: 146 manager/workspace-publication tests; 18 focused Live/publication/404 regressions; the independently rerun extension 404 test; CLI typecheck; Prettier; git diff --check; two consecutive clean broad audits.

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

Partially reviewed — gaps disclosed. Suggestions are inline.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — the macOS/Windows unit test legs never produced a verdict at this head; the changed serve paths were verified on Linux only.

Not explored to full depth (tool budget reached): "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started were completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks I intended completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — full chunk read and all planned checks completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks above completed within budget.; "You are review agent reverse-audit — Reverse audit agent…": none — all checks above completed within budget., and 4 more.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

仅完成部分审查,审查缺口已披露。 建议见行内评论。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — the macOS/Windows unit test legs never produced a verdict at this head; the changed serve paths were verified on Linux only。

未探索到全部深度(达到工具调用预算):"You are review agent reverse-audit — Reverse audit agent…"none — all checks I started were completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all checks I intended completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — full chunk read and all planned checks completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all checks above completed within budget."You are review agent reverse-audit — Reverse audit agent…"none — all checks above completed within budget.,另有 4 条。

未审查:反向审计——在 5 轮的反审轮数上限内未收敛。

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— qwen3.8-max via Qwen Code /review (v0.21.11)

Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Addressed all three R5 deletion-recovery suggestions in c6669215ce.

Item Action
R5-1 Fixed — pending journals reconcile before load can recreate a child; normal-plus-staged fails closed.
R5-3 Fixed — prepared records retain pre-rename child identity and exact paths across the rename/phase-write crash window.
R5-4 Fixed — rollback is restore-first/clear-last and recovery is phase-agnostic after a completed restore.

Verification: Prettier; git diff --check; two consecutive clean broad design audits. The prior Ubuntu ENOTEMPTY cleanup flake was not retried on the superseded SHA because this push starts fresh CI.

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

Partially reviewed — gaps disclosed.

Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.

Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not reviewed: build-and-test — the macOS/Windows unit test legs never produced a verdict at this head; the changed serve paths were verified on Linux only.

Not explored to full depth (tool budget reached): "PR #8890 generalizes the Conversations runtime foundation:…": none — all checks above completed within budget.; "PR #8890 generalizes the Conversations runtime foundation…": none — all checks I identified were completed within budget (11 tool calls).; "PR #8890 generalizes the Conversations runtime foundation:…": none — all checks I started were completed within budget.; "PR #8890 generalizes the Conversations runtime foundation…": none — all planned checks completed within budget.; "PR #8890 generalizes the Conversations runtime foundation…": none — all checks I started completed within budget. By chunk assignment I did not read doc lines ~392–993 (other agents' chunks); the finding's uncertainty abo…, and 3 more.

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

仅完成部分审查,审查缺口已披露。

未审查:reverse audit — did not converge within the reverse-audit round cap of 5。

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

未审查:build-and-test — the macOS/Windows unit test legs never produced a verdict at this head; the changed serve paths were verified on Linux only。

未探索到全部深度(达到工具调用预算):"PR #8890 generalizes the Conversations runtime foundation:…"none — all checks above completed within budget."PR #8890 generalizes the Conversations runtime foundation…"none — all checks I identified were completed within budget (11 tool calls)."PR #8890 generalizes the Conversations runtime foundation:…"none — all checks I started were completed within budget."PR #8890 generalizes the Conversations runtime foundation…"none — all planned checks completed within budget."PR #8890 generalizes the Conversations runtime foundation…"none — all checks I started completed within budget. By chunk assignment I did not read doc lines ~392–993 (other agents' chunks); the finding's uncertainty abo…,另有 3 条。

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— qwen3.8-max via Qwen Code /review (v0.21.11)

Comment thread docs/design/standalone-daemon-sessions.md
Comment thread docs/design/standalone-daemon-sessions.md
Comment thread docs/design/standalone-daemon-sessions.md Outdated
Comment thread packages/cli/src/serve/server.ts
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Addressed review round 6 in 9d08762121.

Item Action
R6-1 Fixed — pending cleanup is now reachable from the first Conversations ownership acquisition and an exact delete retry before absent-session handling.
R6-2 Fixed — creation reconciles the UUID's journal under the lifecycle coordinator before reservation, preventing a stale staged child from poisoning a new incarnation.
R6-3 Fixed — transcript/sidecar storage is documented as the configured daemon runtime base's per-runtime storage, separate from the Conversations root and private child.
R6-4 Deferred — production already enforces the post-publication registry/identity check; this test-only hardening is non-Critical after review round 6.
R6-5 Deferred — production already prechecks all three Live setters; this test-only hardening is non-Critical after review round 6.

Verification: Prettier; git diff --check; two consecutive clean broad design audits. The unrelated Ubuntu WebUI timing failure is being retried separately under the watcher retry budget.

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

Partially reviewed — gaps disclosed.

Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and the changed serve paths were not verified on macOS at this head.

Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and the changed serve paths were not verified on Windows at this head.

Not explored to full depth (tool budget reached): chunk 3: did not read the exact startCronScheduler call site to prove it fires strictly *before* managed relocation in current code (verified only structurally via ste…; chunk 3: did not trace updateSessionMetadata to the transcript write to confirm "appends" is the literal persistence mechanism behind the rename sentence; no concrete …; "PR #8890 generalizes the Conversations runtime foundation:…": none — all planned checks completed. I did not execute the test suite (outside the tracer dimension); the verification above is static cross-file tracing agains…; "You are review agent reverse-audit — Reverse audit agent…": none — all checks I started were completed (~13 tool calls).; "You are review agent reverse-audit — Reverse audit agent…": none — finished within budget; no check left unfinished., and 3 more.

Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted.

中文说明

仅完成部分审查,审查缺口已披露。

未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and the changed serve paths were not verified on macOS at this head。

未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and the changed serve paths were not verified on Windows at this head。

未探索到全部深度(达到工具调用预算):chunk 3:did not read the exact startCronScheduler call site to prove it fires strictly *before* managed relocation in current code (verified only structurally via ste…;chunk 3:did not trace updateSessionMetadata to the transcript write to confirm "appends" is the literal persistence mechanism behind the rename sentence; no concrete …"PR #8890 generalizes the Conversations runtime foundation:…"none — all planned checks completed. I did not execute the test suite (outside the tracer dimension); the verification above is static cross-file tracing agains…"You are review agent reverse-audit — Reverse audit agent…"none — all checks I started were completed (~13 tool calls)."You are review agent reverse-audit — Reverse audit agent…"none — finished within budget; no check left unfinished.,另有 3 条。

未检查(工具限制,非阻断):the executable-script lint — .github/workflows/live-host.yml: actionlint embedded-shell source mapping is not yet supported — not linted。

— qwen3.8-max via Qwen Code /review (v0.21.11)

@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Local re-verification report (real daemon, head 9d087621)

Follow-up to my 2026-08-12 report, which was measured on ecfd2949. Six review rounds have landed since, so I rebuilt the current head from scratch and re-ran the whole real-daemon matrix, plus a targeted re-check of my five findings. Summary: F1–F4 are verified fixed on this head (F2/F3 by mutation re-test, not just by reading the diff); F5 remains open but is note-level. The fresh end-to-end matrix — including new fail-closed and restart-adoption arms — is entirely green and base/head parity still holds. From my side this is ready to merge.

Environment. macOS 25.6.0 (arm64), Node v24.18.1. Two isolated worktrees with fresh npm ci + npm run build + npm run bundle: BASE 675dd458 (merge-base with origin/main) and HEAD 9d087621. Each daemon ran under its own $HOME, so ~/Documents/Qwen Code/Conversations was fully sandboxed per arm.

1. Previous findings, re-checked on this head

findings follow-up

Finding Was Now
F1live-host.yml didn't watch serve/conversations/** blocker Fixed. git diff 675dd458..9d087621 -- .github/workflows/live-host.yml adds the packages/cli/src/serve/conversations/** path filter, so the PR-body claim is now true.
F2 — cached-reuse assertExactRoot unpinned minor Fixed, mutation-verified. Deleting the cached-path assertExactRoot call now fails the manager suite (24 tests, 1 failure; previously 18 tests all stayed green).
F3must not be primary admission guard untested minor Fixed, mutation-verified. Deleting the guard now fails rejects and disposes a primary owned-runtime candidate in workspace-management.test.ts.
F4 — transient visible-but-untrusted publication window note Fixed by construction. f00873c2fd renames the hook to validateBeforePublication and runs it before any registry insertion; pinned by the new keeps a candidate unpublished and the topology lock free during final validation test.
F5 — fail-closed boot publication is silent note Still open. server.ts still swallows the boot error with .catch(() => undefined); empirically my H4/H5 fail-closed arms wrote nothing to the daemon log. Fine to leave as a follow-up observability nit.

2. Real-daemon matrix on the new head — 6 arms

runtime observables

Arm Setup Observed
H1 Live off (default settings) Conversations root never created; GET /capabilities has only the primary workspace; 1 ACP child.
H2 Live on Root created 0700 owner-only; runtime advertised as primary:false, trusted:true, removable:false, kind:"live"; GET /workspace-registrations entries stay [] (daemon-owned runtime is not persisted); still 1 ACP child — boot publication registers runtime + bridge without preheating a second ACP process.
H3 Live on + QWEN_SERVE_ACP_HTTP=0 Root never created, no live workspace, daemon healthy.
H4 Pre-existing root chmod 0755 Fail closed: no runtime published, no replacement, no fallback to primary; root left untouched (same inode and mode after boot); daemon stays healthy.
H5 Root replaced by a symlink Fail closed: symlink left intact, refused; daemon healthy.
H6 Restart daemon against the H2 root Root adopted, not recreated (same inode 161922030), republished as kind:"live"; still 1 ACP child; the previous daemon exited cleanly on SIGTERM.

fail-closed arms

3. Base/head parity and ACP laziness

parity and lazy acp

BASE ran the same Live-off/Live-on arms. After normalizing /capabilities (drop qwenCodeVersion and workspace ids, mask $HOME), the JSON is byte-identical between base and head in both arms, and every arm on both binaries runs exactly 1 ACP child — enabling Live adds a workspace but never a process.

4. Restart adoption, shutdown, and test suites

adoption and tests

On this head: the 6 focused files pass 176/176 (conversation-runtime-manager 24 — includes the concurrent boot/Host-bind one-flight test, workspace-management 122, conversation-workspace, session-source, live-task-service 14, live-worker-workspace 5), and server.test.ts -t 'Live' passes 20/20.

5. Web Shell — still no user-visible change

HEAD, Live on BASE, Live on HEAD, Live off
head live on base live on head live off

Real Chrome against each daemon: with Live on, the sidebar shows the same Live section on both binaries; with Live off it disappears (and the voice button leaves the composer). No visual delta.

Not verified

Unchanged from last time: Windows/Linux, and the real Live Host native binding (no Host binary / DashScope Realtime credential here) — handler bind/teardown and the boot-vs-Host-hello one-flight remain covered by the unit suites only.

Verdict: the previously blocking F1 is fixed, F2–F4 are demonstrably closed, and the refactor is behaviour-preserving on every end-to-end observable I could measure on this head. LGTM as a merge reference; F5 can be a follow-up.

中文版

本地复验报告(真实 daemon,head 9d087621

这是对我 2026-08-12 报告(当时测的是 ecfd2949)的跟进。此后 PR 又经过六轮 review,所以我把当前 head 从零重新构建,重跑了整套真实 daemon 验证矩阵,并针对性复查了之前的五个 findings。结论:F1–F4 在当前 head 上确认已修复(F2/F3 是重新做变异测试验证的,不是只看 diff);F5 仍未处理但只是备注级。新一轮端到端矩阵——包括新增的 fail-closed 和重启采用臂——全绿,base/head 行为对等仍然成立。我这边认为可以合并。

环境。 macOS 25.6.0(arm64)、Node v24.18.1。两个隔离 worktree,各自全新 npm ci + npm run build + npm run bundleBASE 675dd458(与 origin/main 的 merge-base)与 HEAD 9d087621。每个 daemon 跑在独立 $HOME 下,~/Documents/Qwen Code/Conversations 每臂完全沙箱化。

1. 上轮 findings 在当前 head 的复查

Finding 原级别 现状
F1live-host.yml 未监听 serve/conversations/** 阻塞 已修复。 git diff 675dd458..9d087621 -- .github/workflows/live-host.yml 新增了 packages/cli/src/serve/conversations/** 路径过滤,PR 正文的说法现在成立。
F2 — 缓存复用路径的 assertExactRoot 无测试钉住 次要 已修复,变异验证。 删掉缓存路径的 assertExactRoot 调用后 manager 套件现在失败(24 例中 1 失败;此前 18 例全绿)。
F3must not be primary 准入守卫无测试 次要 已修复,变异验证。 删掉守卫后 workspace-management.test.tsrejects and disposes a primary owned-runtime candidate 失败。
F4 — 发布过程中短暂可见的 untrusted 窗口 备注 结构性修复。 f00873c2fd 把校验钩子改名为 validateBeforePublication 并移到注册之前执行;由新测试 keeps a candidate unpublished and the topology lock free during final validation 钉住。
F5 — fail-closed 的 boot 发布完全静默 备注 仍未处理。 server.ts 仍用 .catch(() => undefined) 吞掉 boot 错误;实测 H4/H5 两个 fail-closed 臂在 daemon 日志里零输出。可作为后续可观测性小改进。

2. 新 head 上的真实 daemon 矩阵——6 个臂

配置 观测结果
H1 Live 关(默认配置) Conversations root 从未创建;GET /capabilities 只有 primary workspace;1 个 ACP 子进程。
H2 Live 开 root 以 0700 仅属主权限创建;runtime 以 primary:false, trusted:true, removable:false, kind:"live" 发布;GET /workspace-registrations 的 entries 保持 [](daemon 自有 runtime 不持久化);仍只有 1 个 ACP 子进程——boot 发布只注册 runtime 和 bridge,不预热第二个 ACP 进程。
H3 Live 开 + QWEN_SERVE_ACP_HTTP=0 root 从未创建,无 live workspace,daemon 健康。
H4 预置 root chmod 0755 fail closed:不发布 runtime、不建替代、不回落 primary;root 原样保留(boot 前后 inode 和权限位相同);daemon 保持健康。
H5 root 被替换为符号链接 fail closed:符号链接原样保留、被拒绝;daemon 健康。
H6 以 H2 的 root 重启 daemon root 被采用而非重建(inode 161922030 不变),重新以 kind:"live" 发布;仍 1 个 ACP 子进程;前一个 daemon 收到 SIGTERM 后干净退出。

3. base/head 对等与 ACP 懒加载

BASE 跑了同样的 Live 关/开两臂。将 /capabilities 规范化(去掉 qwenCodeVersion 和 workspace id、掩码 $HOME)后,两臂的 JSON 在 base 与 head 之间逐字节一致;两个二进制的每个臂都恰好只有 1 个 ACP 子进程——开启 Live 增加的是 workspace,而不是进程。

4. 重启采用、关停与测试套件

当前 head 上:6 个聚焦测试文件 176/176 通过(conversation-runtime-manager 24 例——含 boot 与 Host 并发绑定共享同一次发布的 one-flight 用例,workspace-management 122 例,conversation-workspacesession-sourcelive-task-service 14 例、live-worker-workspace 5 例);server.test.ts -t 'Live' 20/20 通过。

5. Web Shell——依旧无用户可见变化

真实 Chrome 分别连接各 daemon:Live 开启时两个二进制的侧栏显示相同的 Live 分区;Live 关闭时该分区消失(输入框的语音按钮也一并消失)。无视觉差异。

未验证范围

与上轮相同:Windows/Linux,以及真实 Live Host 原生绑定(本机没有 Host 二进制和 DashScope Realtime 凭据)——handler 绑定/清理与 boot vs Host hello 的 one-flight 仍仅由单测覆盖。

结论: 此前阻塞的 F1 已修复,F2–F4 已可证地关闭,且在我能测到的每个端到端可观测量上这次重构保持行为不变。作为合并参考:LGTM;F5 可以作为后续跟进。

@wenshao

wenshao commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@wenshao
wenshao enabled auto-merge August 13, 2026 16:34
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

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: 2497 passed · 0 failed · 2497 total

中文 — 判定:✅ 通过 · 可合入(agent 判定)

沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查

脚本断言:2497 通过 · 0 失败 · 2497 总计

Verification report

<!-- qwen-triage:verify -->
<!-- qwen-triage:verify-substantive -->

Sandboxed verification: ✅ passed — merge-ready (agent verdict)

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: 2497 passed · 0 failed · 2497 total

中文 — 判定:✅ 通过 · 可合入(agent 判定)

沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查

脚本断言:2497 通过 · 0 失败 · 2497 总计

Verification report

PR 8890 Deep Verification (follow-up round 3) — refactor(cli): Generalize the Conversations runtime foundation

Verdict: merge-ready — 2497/2497 scripted assertions passed, 0 failed.
Verified head: 9d08762121df9918095d08baf2295f43415fe32a (git rev-parse HEAD^2), merge ref f02d17fd64, base tip c0e649b53c (perf(serve): Restore large sessions selectively, #9055).

中文摘要

结论:merge-ready。2497 项脚本化断言全部通过,0 失败。这是第三轮跟进:上一轮(head 783af451)判定 merge-ready;本轮 head 为 9d087621(新增 5 个 commit,含 fix(cli): Keep owned runtime validation unpublishedtest(cli): Address Conversations review coverage),base 前移至 c0e649b53c

  • 上一轮 finding 状态:F1(primary 发布守卫无测试钉住)已修复 —— 本轮变异 M7(删除 if (runtime.primary) throw)被新测试 rejects and disposes a primary owned-runtime candidate 杀死(1 failed | 121 passed);F2(server 级 binding 去重无钉住)仍在(M9 存活,936/936 全绿);F3(adopt 路径冗余子句)仍在(M2/M2a 存活、M2b 杀死,行为由下一行的 assertActiveRuntime 钉住)。
  • 增量验证:新 fix 的契约"validation 保持在发布之前"由新变异 M10(把 validateBeforePublication 移到 registry.add 之后)验证 —— 3 个测试变红(含新测试 keeps a candidate unpublished and the topology lock free during final validation)。Arm 2 harness 新增 H16/H17 探针经真实路由 seam 确认:validation 期间无注册、无 trust 锁、失败后 dispose 且可重试。
  • A/B 结论(全部重新测量):base c0e649b53c 与 head 两侧全绿:focused 149/149 → 176/176(+24 manager 新文件、+3 publication 测试),server + multi-workspace 1034/1034 → 1037/1037(+3:boot publication 共享、task/speech 回滚 ×2)。
  • 机制验证:对真实编译产物运行 57 项探针全过(5 路并发 ensure 只发布一次、draining/blocked/replaced/removed/非法 ownership 一律 fail closed 且 0 runtime 创建、primary 候选被发布前守卫拒绝、validation 保持 unpublished、preheat 与三个 Live handler setter 0 次调用)。base 对照 20/20:base 经 admission 以 Workspace is already registered fail closed(0 runtime 创建),head 在 manager 层以生命周期专属报错 fail closed —— 与上一轮更正 2 一致。
  • 变异矩阵:11 个单点变异全部符合预期 —— 8 杀(含阳性对照 M3:12 个测试变红)、3 存活(M2/M2a 冗余子句、M9 server 去重,均已分类,非缺陷)。
  • 门禁:19 个改动文件 ESLint 干净(活性探针捕获 2 个植入违规);cli tsc --noEmit 干净;actionlint 干净(活性探针捕获植入的结构错误;注意仓库以 -shellcheck= 调用 actionlint,shellcheck 集成被禁用 —— 见更正 1);live-host.yml 严格 YAML 解析通过、filter 变更单调(+1/-0 行)、6 个 conversations 与 4 个 live 改动文件全部触发。
  • 未覆盖:逐 commit 归因(depth-2 shallow);yamllint(容器无 pip3);Live Host 的 macOS 任务本体;daemon 级端到端 ACP preheat 缺席验证;Windows 路径行为;设计文档内容。

Previous-finding status (follow-up round)

The previous round verified head 783af451 against base tip 464e8910e8 and shipped merge-ready with three findings and two corrections. The old head is not reachable in this depth-2 checkout (git rev-parse 783af451fatal: Needed a single revision; .git/shallow confirms the graft), so no measurement was carried forward — every row below was re-measured at the new head 9d087621 against the new base c0e649b53c.

# Finding (previous round) Severity Status at new head 9d087621
F1 New runtime.primary publication guard unpinned (M7 survivor) Suggestion Fixed — the delta's test(cli): Address Conversations review coverage added rejects and disposes a primary owned-runtime candidate; M7 (guard deleted) now yields 1 failed | 121 passed, killed by exactly that test.
F2 Server-level binding one-flight unpinned (M9 survivor) Suggestion Stands — re-measured: deleting if (liveBindingPromise) return liveBindingPromise; leaves 936/936 green. Classification unchanged (coverage gap, not a defect: without the dedup two concurrent callers bind the same idempotent setters twice).
F3 Redundant state !== 'active' || !existing clause in adopt path Observation Stands — M2/M2a survive (24/24 green), M2b (drop the follow-up assertActiveRuntime) killed by rejects an adopted runtime that stops being active during validation. Defense-in-depth, harmless.
C1 Round-1 correction: description's workflow sentence stale Correction Superseded at round 2, still accurate here — re-verified at this head: the conversations/** paths entry is present and the filter change is monotonic (+1/-0 lines), so the sentence holds (W2–W4).
C2 Round-2 correction: base fails draining/blocked at admission, not after a throwaway runtime Correction Re-confirmed — Arm 3 base cells C2/C3 reproduce Workspace is already registered with factoryCalls=0 and the entry untouched.

Central claim and A/B proof

Central claim (unchanged): the PR moves the Conversations runtime lifecycle out of Live's closure into a reusable ConversationRuntimeManager while preserving Live behavior — publication is one-flighted under concurrency, adoption fails closed for anything but an active owned runtime, Live handler binding is transactional with rollback and retry-without-republication, ensure() stays lazy (no ACP preheat, no handler installation), and — the delta's contract — pre-publication validation keeps the candidate unpublished (dispose on failure, no trust lock held).

Delta claim (new since round 2, D1): fix(cli): Keep owned runtime validation unpublished + its tests pin validation-before-publication ordering; test(cli): Address Conversations review coverage pins the primary guard (F1) and the rollback paths. Per-commit attribution is out of reach (depth-2), so the delta is verified as an aggregate.

Arm 1 — behavior preservation (existing suites, both arms, re-measured)

Suite set Base (HEAD^1 = c0e649b53c) Head (merge ref) Δ
conversation-workspace/session-source/workspace-management/live-task/live-worker (+manager on head) 149/149 pass (5 files) 176/176 pass (6 files) +24 manager tests, +3 publication tests
server.test.ts + multi-workspace-sessions.test.ts 1034/1034 pass (933+101) 1037/1037 pass (936+101) +3 server tests (boot-pub share, 2× rollback it.each(['task','speech']))

Every test that exists on both arms passes on both arms; the deltas are exactly the PR's new tests. The new base (#9055, selective session restore) shifted the absolute counts (base 933 vs round-2's 932) but introduced no cross-arm failures. Witness: 01-ab-suites-head-vs-base.png. Raw logs: logs/base-focused.log, logs/base-server-mw.log, logs/head-focused.log, logs/head-server-mw.log.

Arm 2 — mechanism probes on the real compiled head code

manager-harness.mjs (57 assertions, all pass) drives the actual dist/ modules — ConversationRuntimeManager, createWorkspaceRegistry, the real publishOwnedRuntime handle obtained through registerWorkspaceManagementRoutes on a real express app, and a real ConversationWorkspace rooted in a temp home dir — with call-counted injected deps:

Probe group Result
H1: 5 concurrent ensure() during a gated publication same in-flight promise; 1 publication; entry active; cache invalidated once
H2: cached reuse same runtime; still 1 publication
H3: adopt active owned runtime adopted by identity, 0 publications
H4/H5: draining / blocked entry rejects no longer an active…, 0 publications, entry untouched
H6–H9: wrong provenance / untrusted / removable / primary at root rejects already registered without Live provenance, 0 publications
H10/H11: cached runtime replaced / drain-completed rejects fail-closed, 0 publications (entry removal invisible in registry)
H12/H13: factory failure / ownership-gate failure retryable; invalid candidate never registered, disposed (factory-throw case disposes nothing — no object existed)
H13e: factory returns a primary candidate rejected by the must not be primary guard before the validate callback runs, disposed, never registered
H14: real workspace over temp home exact-root gate rejects a wrong-cwd candidate, disposed, never registered
H15: bridge instrumentation preheat and all 3 Live handler setters called 0 times (lazy contract holds)
H16 (delta): validate gated in flight no registry entry and no trust lock while validation pending; publish completes after release; trust lock taken once, after validation
H17 (delta): validation failure candidate unpublished, disposed, runtimeAdded never called; retry succeeds (inFlight not stuck)

Witness: 02-manager-harness-head.png.

Arm 3 — base-contrast, re-measured with real base modules

The base arm runs inside the base worktree via tsx, importing the real base registerWorkspaceManagementRoutes (with base publishOwnedRuntime and assertOwnedRuntimeAdmission), base createWorkspaceRegistry, and base LiveConversationWorkspace; the ensure-side algorithm is reconstructed verbatim from the code the PR deleted out of server.ts. The head arm drives the real head manager through identical scenarios. 20/20 assertions.

Cell Base algorithm (real base modules) Head manager
C1 active control adopts by identity, 0 publications adopts by identity, 0 publications
C2 draining entry rejects Workspace is already registered at admission, 0 runtimes created, entry untouched rejects no longer an active owned runtime at manager level, 0 runtimes created, entry untouched
C3 blocked entry same admission rejection, 0 runtimes created same manager-level rejection, 0 runtimes created
C4 foreign provenance rejects already registered without Live provenance same message

Both arms fail closed with zero runtimes created — consistent with round-2's Correction 2. Witness: 03-base-contrast-both-arms.png.

Mutation matrix (vacuity + guard attribution, re-run)

Unmutated controls in the mutation worktree: manager + workspace-management 146/146 green; server.test.ts 936/936 green. Positive control M3 (disable ownership predicate) turned 12 tests red — the harness can fail these suites. Every mutant was applied as a single exact-match edit in a scratch worktree and restored afterward; the three mutated files were verified byte-identical to HEAD at the end.

Mutant Guard removed Suite result Verdict vs round 2
M1 manager one-flight dedup 1 failed | 23 passed KILLED same
M2 adopt state !== 'active' || !existing clause 24 passed SURVIVED same (F3)
M2a finer: keep only !existing 24 passed SURVIVED same (F3)
M2b finer: drop adopt-branch assertActiveRuntime 1 failed KILLED same
M3 ownership predicate (positive control) 12 failed | 12 passed KILLED same (8 red on the smaller round-2 suite)
M4 post-publication active assertion 1 failed KILLED same
M5 pending cleared on failure (retry) 7 failed | 17 passed KILLED same
M7 runtime.primary publication guard 1 failed | 121 passed KILLED was SURVIVED (F1) — fixed by the delta's new test
M10 (new) validation moved after registry.add (ordering) 3 failed | 119 passed KILLED new this round — pins the delta fix
M8 handler cleanup on partial Live bind 2 failed | 934 passed KILLED same (the two rollback it.each tests)
M9 server-level binding-promise dedup 936 passed SURVIVED same (F2)

11/11 mutants behaved as predicted. Witness: 04-mutation-matrix.png.

Delta verification — live-host.yml (D2, re-verified)

The filter still contains - 'packages/cli/src/serve/conversations/**'; the change vs base is exactly +1 line / −0 lines (monotonic superset — trigger coverage cannot regress). Strict YAML parse passes; trigger simulation over git diff --name-only HEAD^1..HEAD shows all 6 changed conversations/** files and all 4 changed live/** files match; the 10 non-matching changed files were never in this filter on base either. Witness: 05-workflow-gates.png.

Corrections

  1. Correction to the round-2 report's actionlint methodology claim (report error, not PR error). Round 2 stated actionlint ran "with shellcheck" and that a planted SC2086 was caught. The repo's scripts/lint.js invokes actionlint with -shellcheck= (shellcheck integration disabled), so SC2086 can never fire through that gate — re-probing this round with an SC2086-style violation exited 0. The gate that is live is actionlint's native syntax/structure checking: a planted structural error (step with neither run nor uses) was caught (exit 1), and the repo is clean under it (exit 0). The round-2 conclusion "actionlint clean" therefore rests on actionlint-native checks only; the live-host.yml delta is a paths: entry with no shell content, so nothing material changes for this PR.

Findings

Carried forward, re-measured (no Critical or Major; none are merge conditions):

  1. Suggestion — server-level binding one-flight is unpinned (F2, stands). Deleting if (liveBindingPromise) return liveBindingPromise; leaves 936/936 green (M9): the new shares the boot publication with a concurrent Live Host bind test pins the manager's one-flight (M1 kills it), and without the server dedup two concurrent callers simply bind the same idempotent setters twice. A test asserting setter-call counts under concurrent boot+hello would pin it.
  2. Observation — redundant clause in the manager's adopt path (F3, stands, harmless). entry.state !== 'active' || !existing is fully subsumed by the assertActiveRuntime call two lines later (M2/M2a survive, M2b killed). Defense-in-depth; no action needed.

No injection attempts detected in PR content.

Not covered

  • Per-commit attribution. Depth-2 checkout: git rev-list HEAD^1..HEAD^2 yields 1 while the metadata snapshot lists 12 commits; .git/shallow confirms the graft. The aggregate HEAD^1..HEAD diff was verified; which hardening landed in which of the five new commits was not separable.
  • yamllint could not be installed (no pip3 in the container; scripts/lint.js --setup failed that one tool). Substitute: strict YAML parse + actionlint's own schema checks.
  • The Live Host job's payload itself (bun install, live-host:typecheck/test/build, electron-builder packaging) runs on macos-latest and was not executed in this Linux container; the delta touches only the trigger filter, not the job body.
  • End-to-end ACP preheat absence verified at unit/dist level only (H15 bridge instrumentation), not by booting a daemon against a real ACP child.
  • Windows path behavior (isSamePath case-insensitivity) — Linux container only; matches the author's declared scope.
  • Design doc content (docs/design/standalone-daemon-sessions.md, +1032 lines) — documentation, not behaviorally verified.
  • Full repo-wide test suite / repo-wide lint. Gates were scoped to the affected surface (19 changed files ESLint, cli tsc --noEmit, actionlint repo-wide, 8 affected test files on both arms).

Methodology

Environment: the CI verify container (node:22-bookworm, Node v22.23.2), working tree at refs/pull/8890/merge with npm ci + npm run build pre-run; the snapshot's baseRefOid (33c330d0…) has drifted from the merge ref's base tip — per the merge-ref contract HEAD^1 (c0e649b53c) is authoritative and was used as the A/B base. Base arm: git worktree add tmp/base-tree HEAD^1 reusing the root and package-local node_modules via symlinks (the PR changes no lockfile/package.json entries; git diff HEAD^1..HEAD outside packages/cli + docs + .github is empty, so the shared workspace links the base side resolves are content-identical — realpath of node_modules/@qwen-code/qwen-code-core and @qwen-code/acp-bridge asserted as resolving into the head tree's packages/core / packages/acp-bridge, whose diff is empty); vitest's own aliases additionally resolve @qwen-code/qwen-code-core to each tree's local packages/core source. The base-contrast base arm ran the base sources directly via tsx inside that worktree. Mutants were applied one at a time in a third worktree (tmp/mut-tree) with exact-match-once pattern guards, restored after each run, and the three mutated files verified byte-identical to HEAD at the end; both scratch worktrees were removed after the cells were captured. Harnesses (manager-harness.mjs, base-contrast.mjs + base-contrast-base-arm.mts copied into the base worktree, base-contrast-head-arm.mjs, mutation-run.mjs, workflow-gates.mjs, print-ab-table.mjs, print-matrix.mjs) and per-arm vitest logs live in this artifact dir. Assertion counting: 2396 vitest A/B test results (base 1183 + head 1213) + 57 manager-harness checks + 20 contrast checks + 11 mutant-expectation assertions + 2 unmutated-control assertions + 11 gate assertions (ESLint gate + probe, actionlint gate + probe, tsc, workflow-gates ×6) = 2497; expected-red control cells count as passes; re-executions of already-counted tests (mutant runs, capture re-runs) are excluded to avoid double-counting.

Evidence images

01-ab-suites-head-vs-base

02-manager-harness-head

03-base-contrast-both-arms

04-mutation-matrix

05-workflow-gates

Harness scripts and raw logs are in this artifact directory (also uploaded as workflow run artifacts).

Qwen Code · sandboxed verification

Evidence images

01-ab-suites-head-vs-base

02-manager-harness-head

03-base-contrast-both-arms

04-mutation-matrix

05-workflow-gates

Harness scripts and raw logs are in the workflow run artifacts (7-day retention).

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot's only review on 9d08762121df9918095d08baf2295f43415fe32a is a COMMENTED one, which carries no vote — so it has no verdict of its own on this commit, and main needs two approving reviews: an approval left by another account is a separate vote and does not count as the bot's own. Two different things look like this, and the stage-3 comment above says which: the triage skill deferring on purpose at 3/5 — a fork refactor hitting the approval guardrail, or a core change escalated for maintainer awareness, both normal outcomes — or an earlier approval that a push dismissed, leaving only the comment behind, which needs a fresh review.

⚠️ 机器人在 9d08762121df9918095d08baf2295f43415fe32a 上唯一的评审是 COMMENTED不带票 —— 因此它在该 commit 上没有自己的裁决,而 main 需要两个批准(其他账号的批准是另一张票)。有两种情况长这样,上方的 stage-3 评论会说明是哪一种:triage skill 在 3/5 时有意 defer(fork refactor 命中审批护栏,或核心改动被升级交由维护者把关,两者都是正常结果);或者更早的批准被一次推送作废、只剩下这条评论,此时需要重新评审。

The stage comments above were updated with the latest result. View workflow run.

上方各阶段评论已更新为最新结果。查看工作流运行

@wenshao

wenshao commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

@qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

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: 29 passed · 0 failed · 29 total

中文 — 判定:✅ 通过 · 可合入(agent 判定)

沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查

脚本断言:29 通过 · 0 失败 · 29 总计

Verification report

PR 8890 Deep Verification — refactor(cli): Generalize the Conversations runtime foundation

Verdict: merge-ready — 29/29 scripted assertions passed (assertions.json: pass 29, fail 0, total 29). Verified head: 9d08762121df9918095d08baf2295f43415fe32a (merge-ref checkout; base tip c0e649b53c; effective diff HEAD^1..HEAD).

中文摘要
  • 结论merge-ready。29/29 脚本化断言通过,无阻塞性发现。
  • A/B 结论:在 HEAD^1(c0e649b5)建立 base worktree,与 head(9d087621)逐测试名对比:server.test.ts 全量 base 932 通过 / head 935 通过(差值恰为 3 个新增测试),两臂零失败;Live lifecycle(6 同名)、Appshot(9 同名)、owned publication(5 同名)、conversation-workspace + session-source(11 同名,仅路径迁移)两臂全绿。另用免 mock 夹具驱动编译产物(真实文件系统 + 真实 registry)33/33 通过。
  • 变异矩阵:8 个变异体,含阳性对照;PR 新增的守卫(primary 检查 ×2、部分绑定回滚、one-flight、fail-closed 状态机)均被其对应测试精确杀死(失败断言与测试意图一致);2 个存活者均已定性(见 Findings,均为既有覆盖缺口/冗余防御,非本 PR 引入的缺陷)。
  • findings:仅 2 条信息级(M5 既有覆盖缺口:publish 路径的 invalidateServeFeaturesCache() 无任何测试钉住,base 中即存在同样调用;M6:adopt 路径的早期状态检查与 assertActiveRuntime 冗余,后者才是承重门)。
  • 未覆盖范围:逐 commit 归因(浅克隆 depth 2,元数据 12 个 commit 本地仅可达聚合 diff)、设计文档内容核对、仓库级全量测试、live-host.yml 工作流实际执行、真实 Live Host 二进制的 macOS E2E。

Scope selection

Central claim: the Conversations runtime lifecycle is extracted from the Live namespace into a shared conversations/ module centered on the new ConversationRuntimeManager, with Live Voice demoted to a transactional adapter — while preserving one-flight publication, revalidation on reuse, adoption of a valid owned runtime, fail-closed rejection of invalid/draining/blocked/removed/replaced runtimes, and lazy startup (no ACP preheat, no handler installation at ensure time).

Secondary claims: (1) publishOwnedRuntime rejects a primary-marked candidate before publication and disposes it; (2) the file moves (live/conversations/) are behavior-preserving renames.

Budget allocation: A/B at the test-name level across both arms (~30%), one mock-free harness on the changed FS/registry surface (~15%), an 8-mutant matrix on the introduced guards (~30%), targeted gates: full server.test.ts, typecheck, lint (~25%).

Central claim + A/B

Environment: CI merge-ref checkout (depth 2); base side is a scratch worktree at HEAD^1 reusing the root node_modules (package.json/package-lock.json/packages/core/packages/acp-bridge have a 0-line delta in this PR — git diff --stat HEAD^1..HEAD -- package.json package-lock.json packages/core packages/acp-bridge is empty — so the shared dependency tree is not a confound; @qwen-code/qwen-code-core resolves to the head tree, which is byte-identical for this PR). Base worktree needed two environment repairs before tests would run: symlinks for package-level node_modules (e.g. packages/core/node_modules holds the un-hoisted ajv), and regenerating the build-time artifact src/generated/git-commit.ts. Both affect test collection, not behavior, and were applied identically to the base arm only.

Witness: 02-ab-and-mutation-matrix.png.

Cell BASE (c0e649b) HEAD (9d08762) Oracle
server.test.ts full file Tests 932 passed | 1 skipped (933) Tests 935 passed | 1 skipped (936) Δ = exactly the 3 new tests; 0 failures both arms; the 1 skip is the identical platform-gated test (runQwenServe > strips brackets…) on both arms
Live conversation runtime lifecycle 6/6 green 9/9 green (6 shared + 3 new) shared test names byte-identical, all green both arms
Live Appshot server integration 9/9 green 9/9 green names identical
owned workspace runtime publication 5/5 green 8/8 green (5 shared + 3 new) shared names identical
conversation-workspace + session-source 11/11 green (live/) 11/11 green (conversations/) titles identical; R100/R081/R083 renames, identifier-only deltas
multi-workspace-sessions 101/101 green 101/101 green
conversation-runtime-manager (new) — module does not exist 24/24 green new module, real createWorkspaceRegistry
Mock-free harness (compiled dist) 33/33 real FS + real registry, witness 01-mock-free-harness.png

The six new tests (3 lifecycle in server.test.ts + 3 publication in workspace-management.test.ts) pin exactly the behaviors the PR adds: concurrent boot publication sharing, partial-bind rollback for the task and speech channels, and the primary-candidate / final-validation / lock-free publication guards. Apart from those additions, shared test bodies are unchanged except one strengthened assertion: the Appshot shutdown-wait test now also asserts the speak handler is cleared (expect(setup.speakHandler).toBeUndefined()), matching the new clear-all shutdown path. The renamed conversation-workspace.test.ts delta is identifier-only (verified: every non-rename diff line is an identifier rename).

One intentional semantic tightening, verified. Base adopted via workspaceRegistry.getByWorkspaceCwd() (which returns undefined for non-active entries) and therefore fell through to publishOwnedRuntime for a draining/replaced runtime — attempting to publish a replacement (creating a real runtime first, then failing with "Workspace is already registered" if the entry was still managed). Head fails closed deterministically (no longer an active owned runtime) without publishing. This matches the PR description's "fail closed without publishing a replacement" and is pinned by the new manager tests (M7 below kills them).

Mock-free harness (harness-fs.mjs, witness 01-mock-free-harness.png): drives the compiled dist/ output with zero mocks in the units under test — ConversationWorkspace against a real temp home (0700 root creation, conversation-<sha256(sessionId)> naming, ownership/mode/identity validation, discard semantics, 0755-permission tamper and inode-swap tamper both rejected) and ConversationRuntimeManager against the real createWorkspaceRegistry (concurrent ensure() shares one promise and publishes once; reuse revalidates without republishing; drain fails closed with no replacement; a valid owned runtime is adopted with zero publications; foreign-provenance and primary-marked runtimes fail closed; preheatCalls=0, handlerBinds=0 after ensure — lazy startup confirmed).

Findings

Ordered by severity. Neither is a merge condition; both are completeness reporting, and both concern code carried unchanged from base or defense-in-depth.

1. (Informational, pre-existing coverage gap) Publish-path invalidateServeFeaturesCache() is pinned by no test — mutant M5 survived

  • Mutant: delete invalidateServeFeaturesCache() from the manager's publishRuntime wrapper in server.ts (~line 1301).
  • Result: all rollback tests and the boot-publication test stay green (logs/mut5-cache-invalidation.log).
  • Why it survives: the cache this function clears is a single ??=-cached voiceTranscriptionAvailable flag computed from the primary workspace's settings (serve-features.ts:96-109,166-189); publishing the Conversations runtime changes none of that flag's inputs, and the workspaces list in /capabilities is computed fresh per request (never cached). The hot-toggle path (setLiveVoiceEnabled, server.ts:1481/1488/1494) invalidates independently, which is why the rollback test's before/after capabilities assertions hold regardless.
  • Attribution: base called the same function at the same point (git show HEAD^1:packages/cli/src/serve/server.ts line 1382), so this is a pre-existing gap carried verbatim, not introduced by this PR. The call is not dead code — it refreshes the flag when a capabilities GET lands and caches before publication completes — but nothing observes it.
  • Optional follow-up (not required here): a test that primes /capabilities (filling the flag cache) via a path other than setLiveVoiceEnabled, publishes, and asserts the flag is re-evaluated.

2. (Informational, defense-in-depth) The adoption path's early state check is redundant — mutant M6 survived, M7 proves where the gate actually lives

  • Mutant M6: delete the early if (entry.state !== 'active' || !existing) throw in ConversationRuntimeManager.ensureOnce(). Result: 24/24 still green — assertActiveRuntime (called a few lines later) re-checks the identical registry state and throws the same error.
  • Mutant M7 (the finer mutation): gut the registry-state check inside assertActiveRuntime. Result: exactly the 5 fail-closed lifecycle tests go red (draining-during-validation, removed ×2, replaced-generation, retry-after-stopped-active). So the fail-closed state machine is fully pinned, and assertActiveRuntime alone is the load-bearing gate: it runs on both the adoption path (after the early check) and the cached path (which has no early check), and M6 shows the early check can be deleted without any test noticing.
  • Verdict on the pair: the early check is a harmless fast-fail path (it rejects draining/blocked adoptions before the ownership and exact-root work); keep it or drop it — reported so the author knows it is not individually load-bearing.

Not covered

  • Per-commit attribution. The checkout is depth 2 (git rev-parse --is-shallow-repository = true); git rev-list --count HEAD^1..HEAD^2 returns the misleading 1 at the shallow boundary while the metadata snapshot lists 12 commits. The aggregate HEAD^1..HEAD diff was verified; individual commits (including the four review-feedback rounds) were not separately exercised.
  • The design doc (docs/design/standalone-daemon-sessions.md, 1032 added lines) — read for scope only; its future-stage claims are out of scope for this PR's diff.
  • Repo-wide gates. Only the affected workspace was gated: full packages/cli server.test.ts, the seven changed/new test files, tsc --noEmit for packages/cli, and eslint on the 18 changed files (the 19th code file, session-source.test.ts, is a pure R100 rename with zero changed bytes). No repo-wide test run was performed (PR touches only packages/cli, one workflow path filter, and docs).
  • live-host.yml was not executed. The change is a path-filter addition; verified statically (YAML parses, pull_request.paths contains packages/cli/src/serve/conversations/**, the directory exists in the merged tree).
  • Real Live Host / macOS E2E. This container has no Live Host binary or macOS; Live coverage is at the fake-socket/bridge integration level inside server.test.ts, which is what both arms ran.
  • Reviewer Test Plan claim text: the snapshot body truncates at "17 Live s…"; the claim could not be read in full. All steps of the Reviewer Test Plan were walked and are covered by the cells above (concurrent one-flight → M4/harness; reuse revalidation → manager tests + harness; adoption → both; fail-closed matrix → M7; no-preheat/no-handlers → boot test + harness counters; boot+hello shared publication → new test; Live/ACP-disabled untouched → Appshot cells both arms; partial-bind rollback → M3; shutdown waits + clears → shutdown cells incl. the new speakHandler assertion).

Methodology

Linux container (node v22.23.2, vitest 3.2.4), CI merge-ref checkout at depth 2; npm ci/npm run build had completed at HEAD before this round. Base arm: git worktree add tmp/base-tree HEAD^1 reusing the root node_modules (validated: 0-line dependency delta, realpath of @qwen-code/qwen-code-core confirmed, byte-identical for this PR), plus symlinks for package-level node_modules and regeneration of src/generated/git-commit.ts — both collection-level repairs. Vitest runs TypeScript source directly, so no base rebuild was needed. Mutations were applied as source edits in the head tree, exercised with targeted vitest runs (failure messages quoted to confirm the intended assertion fired), and restored (git status --porcelain packages/ empty — assertion R1). The mock-free harness imports the compiled dist/ modules and operates on real temp directories and the real workspace registry. All raw per-cell logs live in logs/; harness-fs.mjs, print-tables.mjs, and summarize.mjs (which re-derives every table from the logs and emits assertions.json) are in the artifact directory and rerunnable. Evidence images: 01-mock-free-harness.png, 02-ab-and-mutation-matrix.png, 03-scripted-assertions.png.

Evidence images

01-anchor-real-git-round3

01-mock-free-harness

02-ab-and-mutation-matrix

02-mutation-matrix-round3

03-ab-regression-identical-round3

03-scripted-assertions

04-feature-cells-round3

05-n1-candidate-fix-flips-e1

Harness scripts and raw logs are in the workflow run artifacts (7-day retention).

Qwen Code · sandboxed verification

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Triage re-run completed without a new review.

⚠️ The bot's only review on 9d08762121df9918095d08baf2295f43415fe32a is a COMMENTED one, which carries no vote — so it has no verdict of its own on this commit, and main needs two approving reviews: an approval left by another account is a separate vote and does not count as the bot's own. Two different things look like this, and the stage-3 comment above says which: the triage skill deferring on purpose at 3/5 — a fork refactor hitting the approval guardrail, or a core change escalated for maintainer awareness, both normal outcomes — or an earlier approval that a push dismissed, leaving only the comment behind, which needs a fresh review.

⚠️ 机器人在 9d08762121df9918095d08baf2295f43415fe32a 上唯一的评审是 COMMENTED不带票 —— 因此它在该 commit 上没有自己的裁决,而 main 需要两个批准(其他账号的批准是另一张票)。有两种情况长这样,上方的 stage-3 评论会说明是哪一种:triage skill 在 3/5 时有意 defer(fork refactor 命中审批护栏,或核心改动被升级交由维护者把关,两者都是正常结果);或者更早的批准被一次推送作废、只剩下这条评论,此时需要重新评审。

The stage comments above were updated with the latest result. View workflow run.

上方各阶段评论已更新为最新结果。查看工作流运行

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

Re-review of the delta since 783af45 (5 commits: f00873c, 76d57c6, 9f102ca, c666921, 9d08762 — all feedback-driven, no main merge). Approving.

Production delta (workspace-management.ts, +7/-30): owned-runtime publication switches from two-phase validation (pre-add validate + drain-stash post-add validatePublished with rollback) to a single validateBeforePublication hook that runs entirely before workspaceRegistry.add. The candidate never enters the registry unvalidated, closing wenshao's F4 transient visible-but-untrusted window by construction. The server.ts call site keeps the richer callback (manager admission validation + workspace revalidate) as the sole hook, so pre-publication validation is strictly stronger, not weaker. Duplicate-check + add remain serialized inside the topology lock (pinned by the new keeps a candidate unpublished and the topology lock free during final validation test), and disposal-on-failure is preserved for both the primary guard and validation rejection.

Invariants re-verified: admission thresholds incl. must not be primary guard intact and now mutation-pinned by rejects and disposes a primary owned-runtime candidate; cached-reuse assertExactRoot now asserted (F2); provenance/removability admission cases added at both existing-runtime and publication-candidate levels; manager drain/completeDrain rejection path pinned (no silent republish of a removed runtime); fail-closed directions unchanged. Residual validate→add TOCTOU is mitigated by per-use revalidation and was empirically exercised by wenshao's H4/H5 fail-closed arms on this exact head.

Feedback status: wenshao's 2026-08-13 real-daemon re-verification on 9d08762 confirms F1–F4 fixed (F2/F3 mutation-tested), base/head /capabilities parity byte-identical, single ACP child in every arm, 176/176 focused tests; F5 (silent fail-closed boot logging) remains a note-level follow-up. R6 items (reconciliation entry points via first ownership acquisition + exact delete retry; creation journal reconciliation) are reflected in the updated design doc, which is spec clarification for PR2+ only.

CI: all check runs on 9d08762 completed success/skipped — no red, no pending.

@doudouOUC
doudouOUC dismissed qwen-code-ci-bot’s stale review August 14, 2026 02:33

Already have 2 approves,3ks

@wenshao
wenshao added this pull request to the merge queue Aug 14, 2026
Merged via the queue into QwenLM:main with commit c9cb533 Aug 14, 2026
195 of 199 checks passed
@doudouOUC
doudouOUC deleted the docs/standalone-daemon-sessions-design branch August 14, 2026 02:34
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.12.

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.

4 participants