Skip to content

chore(serve): Log session continuation admissions - #8932

Merged
doudouOUC merged 2 commits into
QwenLM:mainfrom
doudouOUC:chore/8923-continuation-admission-log
Aug 11, 2026
Merged

chore(serve): Log session continuation admissions#8932
doudouOUC merged 2 commits into
QwenLM:mainfrom
doudouOUC:chore/8923-continuation-admission-log

Conversation

@doudouOUC

@doudouOUC doudouOUC commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This PR adds a structured continuation enqueued lifecycle record after the daemon has accepted a session continuation. The record contains only sessionId, the generated promptId, and clientId when the request supplies one; rejected and failed continuation attempts are not reported as enqueued, and prompt content is never included.

It also documents the client identity contract for multi-controller integrations: each independent controller should use a distinct stable ID, WebUI-generated IDs use the webui_ prefix, and a host should share an ID with an embedded WebShell only when both intentionally act as one logical controller.

Why it's needed

Prompt submission and cancellation already have admission lifecycle records, but continuation did not. That gap made it difficult to determine whether a continuation was actually admitted and which controller initiated it while investigating session-navigation behavior under #8923. The new record closes that observability gap without changing the REST, ACP, SDK, cancellation, prompt queue, continuation, or detach contracts.

Reviewer Test Plan

How to verify

Send a continuation that the bridge accepts and confirm the daemon emits exactly one continuation enqueued record containing the session ID, generated prompt ID, and client ID, with no request content. Then return accepted: false and throw a mapped bridge error; neither path should emit the admission record. Run the focused serve route tests and confirm all four continuation cases pass, then run the repository build, typecheck, lint, and bundle checks.

Evidence (Before & After)

N/A — this is a daemon observability and documentation change with no user-interface output.

Tested on

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

Environment (optional)

macOS 26.4.1, Node.js 22.22.3, npm 10.9.8, sandbox disabled for local repository checks.

Risk & Scope

  • Main risk or tradeoff: Each accepted continuation produces one additional info-level structured log record; the fields are identifiers only and do not include prompt content.
  • Not validated / out of scope: Windows and Linux were not tested locally. This PR does not change host controllers, session navigation, public protocol fields, CORS, SDK types, or daemon mutation semantics.
  • Breaking changes / migration notes: None.

Linked Issues

Refs #8923

中文说明

本 PR 做了什么

本 PR 在 daemon 接受会话 continuation 后新增结构化的 continuation enqueued 生命周期记录。记录只包含 sessionId、生成的 promptId,以及请求提供时的 clientId;被拒绝或失败的 continuation 不会被记录为 enqueued,也绝不会记录 prompt 内容。

同时补充多控制器集成的客户端身份约定:每个独立控制器应使用不同且稳定的 ID,WebUI 生成的 ID 使用 webui_ 前缀;只有宿主与内嵌 WebShell 有意作为同一个逻辑控制器时,二者才应共享 ID。

为什么需要

Prompt 提交和取消已经有准入生命周期记录,但 continuation 没有。排查 #8923 下的会话导航行为时,这一缺口导致难以判断 continuation 是否真正被准入,以及由哪个控制器发起。新增记录在不改变 REST、ACP、SDK、取消、prompt 队列、continuation 或 detach 契约的前提下补齐了可观测性。

Reviewer 测试计划

如何验证

发送一个被 bridge 接受的 continuation,确认 daemon 只产生一条 continuation enqueued 记录,包含会话 ID、生成的 prompt ID 和客户端 ID,且不包含请求内容。随后让 bridge 返回 accepted: false,再抛出一个会被映射的错误;这两条路径都不应产生准入记录。运行定向 serve 路由测试并确认四个 continuation 场景全部通过,再运行仓库 build、typecheck、lint 和 bundle 检查。

证据(修复前后)

N/A——这是 daemon 可观测性和文档变更,没有用户界面输出。

测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

macOS 26.4.1、Node.js 22.22.3、npm 10.9.8;本地仓库检查未启用 sandbox。

风险与范围

  • 主要风险或取舍:每个被接受的 continuation 会新增一条 info 级结构化日志;字段仅为标识符,不包含 prompt 内容。
  • 未验证 / 范围外:未在本地测试 Windows 和 Linux。本 PR 不修改宿主控制器、会话导航、公共协议字段、CORS、SDK 类型或 daemon mutation 语义。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

Refs #8923

doudouOUC and others added 2 commits August 11, 2026 19:43
Refs QwenLM#8923

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Refs QwenLM#8923

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC doudouOUC self-assigned this Aug 11, 2026
@doudouOUC
doudouOUC requested a review from wenshao August 11, 2026 12:12
@doudouOUC
doudouOUC marked this pull request as ready for review August 11, 2026 12:13
@doudouOUC
doudouOUC enabled auto-merge August 11, 2026 12:13
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 11, 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

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

  • Template: complete ✓
  • Problem: real and verified. POST /session/:id/prompt emits prompt enqueued and POST /session/:id/cancel emits cancel sent, but POST /session/:id/continue has no admission record — I confirmed the gap in the route code. The motivation is observed, not theoretical: while investigating bug(web-shell): Session navigation should never cancel or replay the source prompt #8923 (unexpected cancel/replay during session navigation) there was no way to tell from daemon logs whether a continuation was actually admitted, or by which controller.
  • Direction: aligned. Daemon lifecycle logging is an established area (the observability doc already catalogs the prompt/cancel records), and this closes one row of that table without touching REST, ACP, or SDK contracts. The client-ID contract doc addition is directly tied to the new record's clientId field.
  • Size: not applicable — no core module paths touched (packages/cli/src/serve/** only). ~16 production lines, ~56 test lines, 3 doc lines.
  • Approach: scope feels right and minimal — hoist the bridge result, log continuation enqueued only when accepted, mirroring the prompt enqueued precedent (rejected and error paths stay silent, exactly as prompt admission does). One genuine question, not a blocker: should a rejected continuation also get a record (e.g. continuation rejected)? The PR deliberately matches the prompt-route precedent of logging successful admission only — I'm fine with that symmetry, but worth saying so if the bug(web-shell): Session navigation should never cancel or replay the source prompt #8923 investigation needs the negative side too.
  • Risk: no elevated risk signals — no high-risk paths matched; response shape and status codes are unchanged.

Moving on to code review. 🔍

中文说明

感谢贡献!

  • 模板:完整 ✓
  • 问题:真实且已核实。POST /session/:id/prompt 会产生 prompt enqueuedPOST /session/:id/cancel 会产生 cancel sent,但 POST /session/:id/continue 没有任何准入记录——我在路由代码中确认了这一缺口。动机来自实际观测而非理论假设:排查 bug(web-shell): Session navigation should never cancel or replay the source prompt #8923(会话导航时意外 cancel/replay)时,daemon 日志无法判断 continuation 是否真的被准入、由哪个控制器发起。
  • 方向:对齐。Daemon 生命周期日志是既有建设方向(可观测性文档已收录 prompt/cancel 记录),本 PR 补齐其中一行,且不触碰 REST、ACP、SDK 契约。客户端 ID 约定的文档补充与新记录的 clientId 字段直接相关。
  • 规模:不适用——未触及核心模块路径(仅 packages/cli/src/serve/**)。约 16 行生产代码、56 行测试、3 行文档。
  • 方案:范围合理且最小化——提取 bridge 返回值,仅在 accepted 时记录 continuation enqueued,与 prompt enqueued 先例一致(拒绝/错误路径保持静默,与 prompt 准入行为相同)。一个非阻塞的真问题:被拒绝的 continuation 是否也应有记录(如 continuation rejected)?PR 刻意对齐 prompt 路由只记录成功准入的先例,我认可这种对称性;如果 bug(web-shell): Session navigation should never cancel or replay the source prompt #8923 的排查需要负向记录,也值得提出。
  • 风险:无升级风险信号——未命中高风险路径;响应体与状态码均未变化。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at 86b72763b7cc9b7e4e0caf5a5885eb3f4793c2b1 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

Built the PR base vs this PR head 86b7276, 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

@doudouOUC
doudouOUC requested review from yiliang114 and ytahdn August 11, 2026 12:24
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review

The implementation is exactly the minimal change this needs: capture the bridge result, and when accepted, emit daemonLog.info('continuation enqueued', {sessionId, promptId, clientId}) — the same field shape and guard as the existing prompt enqueued record in the prompt route. No blockers found.

Things I checked specifically:

  • No contract change. promptId was already forwarded to the bridge before this PR; the response body and 200 status are unchanged, and a throwing bridge still propagates through the same error mapping.
  • result.accepted is type-safeAcpSessionBridge.continueSession declares accepted: boolean, so the guard can't misfire on a missing field.
  • No content leakage — the route never reads the request body, the record carries identifiers only, and the test asserts a sent prompt string never appears in any log call.
  • Negative paths stay silentaccepted: false and mapped bridge errors (404) both assert no admission record, matching the prompt-route precedent of logging successful admission only.
  • Docs are accurate — the webui_ prefix claim matches the WebShell client ID generator, and the observability caveat ("promptId when applicable") correctly reflects that cancel sent carries no promptId.

Reuse is good: existing daemonLog wiring, existing fakeDaemonLog test helper, no new utilities. The new tests pin the change — they assert on the exact log calls through the real route handler (supertest against createServeApp, only the bridge is faked), so they fail without the route edit; a green suite is meaningful evidence here, and the change has no user-visible surface, so no sandboxed verification lane is needed.

Test evidence (PR's own CI, read via API — no PR code executed)

Check Conclusion
Test (ubuntu-latest, Node 22.x) ❌ failure
Test (macos-latest, Node 22.x) ⏭️ skipped
Test (windows-latest, Node 22.x) ⏭️ skipped
Serve A/B (ubuntu-latest, Node 22.x) ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Real daemon E2E / Java 11 ✅ success
precheck-pr / precheck ✅ success
web-shell E2E Smoke (ubuntu-latest, Node 22.x) ⏳ in progress

The one red check is not caused by this PR — it's a heap OOM in an unrelated suite:

  • The failure is FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory in a vitest worker, with the last output coming from the web-shell client suite (App.test.tsx > App session callbacks). This PR touches no web-shell files.
  • The suite that covers this PR passed cleanly before the OOM: ✓ src/serve/server.test.ts (922 tests) 21410ms, cli package total Test Files 574 passed | 1 skipped (575).
  • Same signature on an unrelated commit: PR commit 79d98dc5 failed the same Test (ubuntu-latest, Node 22.x) job in the same hour with FATAL ERROR: Ineffective mark-compacts near heap limit at the same point in the same suite. This is a pre-existing flaky OOM on the ubuntu runner, and the macOS/Windows matrix legs were skipped as a consequence of the ubuntu failure.

Not verified: live daemon output against a real bridge (unattended run — PR code is never executed here). The tests cover the real route handler with only the bridge faked, which is the layer this PR does not change, so the CI signal above substantiates the claim. The finalize pass will update the table once CI settles on this commit.

中文说明

代码审查

实现恰好是所需的最小改动:接住 bridge 返回值,当 accepted 时输出 daemonLog.info('continuation enqueued', {sessionId, promptId, clientId})——字段形状与守卫方式与 prompt 路由既有的 prompt enqueued 记录完全一致。未发现阻塞问题。

具体核对过:

  • 契约未变promptId 在本 PR 之前就已转发给 bridge;响应体与 200 状态码不变,bridge 抛错仍走原有错误映射。
  • result.accepted 类型安全AcpSessionBridge.continueSession 声明了 accepted: boolean,守卫不会因字段缺失而误判。
  • 无内容泄漏:路由根本不读取请求体,记录只含标识符,且测试断言发送的 prompt 字符串不会出现在任何日志调用中。
  • 负向路径保持静默accepted: false 与映射后的 bridge 错误(404)都断言无准入记录,与 prompt 路由"只记录成功准入"的先例一致。
  • 文档准确webui_ 前缀的说法与 WebShell 客户端 ID 生成器一致;可观测性注意事项中"promptId when applicable"正确反映了 cancel sent 不带 promptId 的事实。

复用良好:沿用既有 daemonLog 接线与 fakeDaemonLog 测试辅助,无新增工具。新测试钉住了改动——经由真实路由处理器(对 createServeApp 的 supertest 请求,仅 bridge 为假)断言具体日志调用,去掉路由改动即失败;绿色套件在这里是有效证据,且改动没有用户可见界面,因此无需沙箱验证通道。

测试证据(来自 PR 自身 CI,经 API 读取——未执行任何 PR 代码)

CI 结果见上表。唯一的红色检查并非本 PR 导致——是一个无关测试套件的堆内存 OOM:

  • 失败为 vitest worker 的 FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory,崩溃前最后输出来自 web-shell 客户端套件(App.test.tsx > App session callbacks)。本 PR 未触碰任何 web-shell 文件。
  • 覆盖本 PR 的套件在 OOM 之前已干净通过:✓ src/serve/server.test.ts (922 tests) 21410ms,cli 包总计 Test Files 574 passed | 1 skipped (575)
  • 无关提交上出现相同签名:PR 提交 79d98dc5 在同一小时内的同一个 Test (ubuntu-latest, Node 22.x) 任务中以 Ineffective mark-compacts near heap limit 在同一套件的同一位置失败。这是 ubuntu runner 上既有的偶发 OOM;macOS/Windows 矩阵项是因 ubuntu 失败被连带跳过。

未验证:真实 bridge 下的 daemon 实际输出(无人值守运行——此处从不执行 PR 代码)。测试覆盖了真实路由处理器、仅 bridge 为假,而 bridge 正是本 PR 未改动的层,因此上述 CI 信号即为该结论的证据。finalize 流程会在该提交的 CI 落定后更新表格。

Qwen Code · qwen3.8-max

Reviewed at 86b72763b7cc9b7e4e0caf5a5885eb3f4793c2b1 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean, minimal, well-tested observability change; the only reservations are flaky-CI aftermath and one open design question, neither blocking.

Thinking it through before deciding:

  • I sketched my own solution before reading the diff: capture the bridge result and emit an accepted-gated continuation enqueued record mirroring prompt enqueued. The PR is exactly that — no simpler path was missed, and nothing in the diff goes beyond the stated goal.
  • The gap is real, not theoretical: I confirmed in code that prompt submission and cancellation have admission records while continuation had none, and it visibly hampered the live bug(web-shell): Session navigation should never cancel or replay the source prompt #8923 investigation.
  • The tests pin the change on all three paths (accepted → exactly one identifiers-only record; rejected → silent; bridge error → silent), including an assertion that prompt content never reaches the logs. A suite passing with and without the diff is not a risk here — these assertions fail without the route edit.
  • The single red check is the pre-existing ubuntu heap OOM in the web-shell suite, with the evidence laid out in my review above; the serve suite covering this change passed cleanly (922 tests). All PR CI runs on this commit have completed, so I'm approving now rather than leaving a deferred marker — merge stays gated on required checks, and a re-run of the flaky ubuntu job should green the full matrix.

Non-blocking notes for the maintainer:

  1. Consider re-running the failed Test (ubuntu-latest, Node 22.x) job so the macOS/Windows legs (skipped as a consequence) also get a turn.
  2. The Stage 1 question still stands for someday: whether a rejected continuation deserves its own record. The current symmetry with the prompt route (log successful admission only) is defensible as-is.

LGTM, approving pinned to the reviewed commit. ✅

中文说明

置信度:4/5 —— 干净、最小化、测试充分的可观测性改动;仅有的保留意见来自 flaky CI 的后续影响和一个未决设计问题,均不阻塞。

决定前的思考:

  • 我在读 diff 之前先给出了自己的方案:接住 bridge 返回值,在 accepted 时输出与 prompt enqueued 对称的 continuation enqueued 记录。PR 正是这么做的——没有更简路径被遗漏,diff 中也没有超出既定目标的改动。
  • 缺口真实存在而非理论假设:我在代码中确认 prompt 提交与取消都有准入记录而 continuation 没有,且这一缺口确实妨碍了 bug(web-shell): Session navigation should never cancel or replay the source prompt #8923 的排查。
  • 测试在三条路径上都钉住了改动(接受 → 恰好一条仅含标识符的记录;拒绝 → 静默;bridge 错误 → 静默),并断言 prompt 内容绝不会进入日志。"有无 diff 套件都一样绿"在这里不构成风险——去掉路由改动这些断言即失败。
  • 唯一的红色检查是 web-shell 套件上既有的 ubuntu 堆内存 OOM,证据见上一条审查;覆盖本改动的 serve 套件干净通过(922 tests)。该提交的所有 PR CI 运行均已完成,因此现在直接批准而不留延迟标记——合并仍受必需检查约束,重跑 flaky 的 ubuntu 任务即可让整个矩阵变绿。

给维护者的非阻塞建议:

  1. 建议重跑失败的 Test (ubuntu-latest, Node 22.x) 任务,让被连带跳过的 macOS/Windows 矩阵项也得到执行。
  2. Stage 1 的问题留待日后:被拒绝的 continuation 是否值得拥有自己的记录。当前与 prompt 路由的对称性(只记录成功准入)是站得住脚的。

LGTM,批准已固定在所审查的提交上。✅

Qwen Code · qwen3.8-max

Reviewed at 86b72763b7cc9b7e4e0caf5a5885eb3f4793c2b1 · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@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 reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

Not explored to full depth (tool budget reached): Change summary: This PR adds a structured continuation e...: none — I completed every check I wanted. Tool calls ~12.; Change summary: This PR adds a structured continuation e...: none — everything I planned to check, I checked. What I did not do: run the test suite or build (not required by my methodology; static verification only). This….

中文说明

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

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

未探索到全部深度(达到工具调用预算):Change summary: This PR adds a structured continuation e...:none — I completed every check I wanted. Tool calls ~12.;Change summary: This PR adds a structured continuation e...:none — everything I planned to check, I checked. What I did not do: run the test suite or build (not required by my methodology; static verification only). This…

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

Comment on lines +3258 to +3259
if (daemonLog && result.accepted) {
daemonLog.info('continuation enqueued', {

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.

[Suggestion] Rejected continuations are silently unlogged. When the bridge returns accepted: false, this route responds 200 and emits no lifecycle record — the log is gated on result.accepted and the bridge returns the rejection without logging — so the interruption reason exists only in the HTTP response body. The sibling prompt route already logs admission rejections as WARN records (prompt admission rejected: queue full / invalid client id), while the continuation route leaves rejections invisible in the lifecycle family this PR documents (the per-request access log records the 200, but carries no reason and is subject to burst suppression). — Failure scenario: a controller keeps POSTing /session/:id/continue while a turn is in flight or after a turn ended cleanly; every attempt returns 200 with the reason only in the body, and an oncall investigating "continuations never start" finds an empty lifecycle log and no server-side trace of the rejection reason.

Suggested fix — emit a record on the not-accepted branch, mirroring the prompt route's admission-rejection records:

if (daemonLog && result.accepted) {
  daemonLog.info('continuation enqueued', { sessionId, promptId, clientId });
} else if (daemonLog) {
  daemonLog.info('continuation rejected', {
    sessionId,
    promptId,
    clientId,
    interruption: result.interruption,
  });
}
中文说明

建议:被拒绝的 continuation 不会被记录。当 bridge 返回 accepted: false 时,该路由返回 200 但不产生任何生命周期记录——日志以 result.accepted 为条件,而 bridge 返回拒绝时也不会记录——因此 interruption 原因只存在于 HTTP 响应体中。同文件中的 prompt 路由已经将准入拒绝记录为 WARN(prompt admission rejected: queue full / invalid client id),而 continuation 路由让拒绝在本 PR 所文档化的生命周期日志族中完全不可见(按请求的 access log 会记录该 200,但不包含原因,且受突发抑制)。— 失败场景:控制器在 turn 进行中或 turn 正常结束后反复 POST /session/:id/continue;每次尝试都返回 200,原因仅在响应体中。排查"continuation 一直不启动"的值班人员只会看到空的生命周期日志,服务端没有拒绝原因的任何痕迹。

建议修复——在未接受分支也输出一条记录,与 prompt 路由的准入拒绝记录保持一致(见上方代码示例)。

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

promptId,
});
if (daemonLog && result.accepted) {
daemonLog.info('continuation enqueued', {

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.

[Suggestion] continuation enqueued has no structured terminal counterpart. An accepted continuation that fails mid-turn leaves this record permanently unterminated in the structured log family: the async turn's only failure path is .catchteeServeDebugLine — unstructured, gated on QWEN_SERVE_DEBUG, and even with the flag on it reaches the daemon log only as a raw line, never a structured record. Prompt turns, by contrast, get structured prompt turn completed / prompt turn failed records. This diff creates the first half of that unterminated pair, and the new observability bullet enrolls it in the lifecycle-log family beside prompts. — Failure scenario: an accepted continuation fails after admission (model/tool error, ACP child dies); with QWEN_SERVE_DEBUG off (typical production) the daemon file logs show continuation enqueued and nothing after it, so the oncall cannot tell from the structured family whether the turn completed or died — clients are covered by SSE terminal events, but the file-based audit trail is not.

Suggested fix — add a structured terminal record for continuation turns (mirroring prompt turn completed / prompt turn failed, keyed by sessionId + promptId). If that is out of scope here, extend the new 19-observability.md bullet to state that continuation-turn outcomes are only visible via SSE terminal events and QWEN_SERVE_DEBUG output, not the structured file logs.

中文说明

建议continuation enqueued 没有对应的结构化终态记录。被接受后在 turn 中途失败的 continuation 会让这条记录在结构化日志族中永远没有终态:异步 turn 唯一的失败路径是 .catchteeServeDebugLine——非结构化、受 QWEN_SERVE_DEBUG 开关控制,即使开关打开也只会以原始文本行进入 daemon 日志,永远不会成为结构化记录。相比之下,prompt turn 有结构化的 prompt turn completed / prompt turn failed 记录。本 diff 创建了这对未闭合记录的前一半,且新增的可观测性条目又把它与 prompt 一起归入生命周期日志族。— 失败场景:被接受的 continuation 在准入后失败(模型/工具错误、ACP 子进程退出);在 QWEN_SERVE_DEBUG 关闭(典型生产环境)时,daemon 文件日志只显示 continuation enqueued,其后什么都没有,值班人员无法从结构化日志族判断 turn 是完成了还是失败了——客户端有 SSE 终态事件覆盖,但基于文件的审计轨迹没有。

建议修复——为 continuation turn 增加结构化终态记录(与 prompt turn completed / prompt turn failed 对应,以 sessionId + promptId 为键)。若超出本 PR 范围,可在新增的 19-observability.md 条目中说明:continuation turn 的结果仅可通过 SSE 终态事件和 QWEN_SERVE_DEBUG 输出可见,结构化文件日志中不可见。

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

@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. Verified at head: the continuation enqueued record is emitted exactly once per accepted continuation (the bridge calls sendPrompt synchronously before returning accepted:true, so truthy accepted genuinely means enqueued; queue-full/pre-abort throw synchronously), never on reject/fail, carries only sessionId/promptId/clientId (the route never reads the body; a test asserts the body string never reaches any log call), clientId absent renders as dropped per the logger's undefined-drop, and the charset+128-cap bound cardinality and log injection. The client-identity doc matches code (webui_ prefix verified in clientLifecycle.ts). Tests cover accept/reject/error branches plus the leak guard and passed in CI (cli 798/798 files).

Non-blocking: the two outstanding bot suggestions (a rejection record mirroring the prompt route's WARN, and a structured terminal counterpart for accepted continuations) are legitimate observability follow-ups the PR explicitly scopes out. CI on head is red only on the pre-existing web-shell App.test.tsx worker heap OOM — this PR touches zero web-shell files and everything relevant passed; a re-run should clear it. Ship it.

@doudouOUC
doudouOUC added this pull request to the merge queue Aug 11, 2026
Merged via the queue into QwenLM:main with commit 542ef73 Aug 11, 2026
113 of 114 checks passed
@doudouOUC
doudouOUC deleted the chore/8923-continuation-admission-log branch August 11, 2026 14:51

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

No blockers. The change is minimal and well-tested: the continuation enqueued record mirrors the existing prompt enqueued pattern (gated on result.accepted, identifiers-only, no content leakage). Tests cover accept/reject/error branches plus a leak guard. Documentation is accurate. LGTM.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants