Skip to content

fix: restore ACP-related main CI checks - #11033

Merged
yiliang114 merged 1 commit into
mainfrom
codex/fix-e2e-daemon-init-timeout
Sep 4, 2026
Merged

fix: restore ACP-related main CI checks#11033
yiliang114 merged 1 commit into
mainfrom
codex/fix-e2e-daemon-init-timeout

Conversation

@yiliang114

@yiliang114 yiliang114 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Raises the ACP initialization budget from 10 seconds to 60 seconds only for daemons launched by the shared E2E harness. It also routes the concurrently added session turn-index reader through the existing per-request runtime-root helper. The production qwen serve default and turn-index behavior remain unchanged.

Why it's needed

Main E2E run 33884903785 failed in two macOS shards before either affected test body ran. Both failures were ACP initialization timeouts at roughly 10 seconds, while the same run recorded successful handshakes taking 10.43 and 13.12 seconds. This gives process-heavy hosted-runner tests the same CI-sized handshake budget already used by the serve-routes E2E suite in #10846.

The first PR CI run then exposed a deterministic main-branch integration gap: #10751 added the turn-index reader after #10988's branch point, while #10988 later introduced the invariant that every caller-supplied-cwd runtime-root pin must use the shared helper. Because required checks were not strict against the latest base, each PR passed independently and their merged result did not. This PR completes the behavior-equivalent delegation intended by #10988 rather than weakening its AST guard.

Reviewer Test Plan

How to verify

Confirm that the baseline session-creation paths and qwen-live prewarm path can complete when ACP initialization takes more than 10 seconds but less than 60 seconds on a loaded macOS runner. Confirm that qwen serve outside the E2E harness still uses its 10-second default. Confirm that the turn-index reader resolves the request cwd through the shared runtime-root helper and preserves its existing flush, read, and error behavior.

Evidence (Before & After)

Before: the linked main run failed at 9.7–10.0 seconds in the ACP initialize phase before the affected assertions ran.

After: static tracing confirms both failed E2E paths use the shared harness and that its explicit value reaches the ACP bridge. Replaying the failed unit test's TypeScript AST check leaves exactly the one permitted helper delegation. git diff --check and Prettier both pass. Manual E2E run 33897680630 provides the hosted-runner verification.

Tested on

OS Status
🍏 macOS ⚠️
🪟 Windows N/A
🐧 Linux ⚠️

Environment (optional)

N/A — the failure depends on hosted-runner contention.

Risk & Scope

  • Main risk or tradeoff: A genuinely stuck ACP operation in shared-harness E2E tests can take up to 50 seconds longer to fail. The runtime-root change delegates the same cwd, settings, callback, and Promise through the existing helper.
  • Not validated / out of scope: No local E2E or build was run; PR CI and the manual E2E run provide the relevant validation.
  • Breaking changes / migration notes: None.

Linked Issues

Fixes #11030

中文说明

本 PR 做了什么

仅将共享 E2E harness 启动的 daemon 的 ACP 初始化预算从 10 秒提高到 60 秒,同时让并发新增的 session turn-index reader 经过现有的 per-request runtime-root helper。生产环境中的 qwen serve 默认值和 turn-index 行为都保持不变。

为什么需要

main E2E run 33884903785 的两个 macOS 分片都在受影响测试的正文运行前失败。两处都是约 10 秒触发 ACP 初始化超时,而同一次运行中也记录到了耗时 10.43 秒和 13.12 秒但成功的握手。本修复让进程负载较重的托管 runner 测试使用与 #10846 中 serve-routes E2E 套件相同的 CI 级握手预算。

第一次 PR CI 随后暴露了一个确定性的 main 分支集成缺口:#10751#10988 的分支基线之后新增了 turn-index reader,而 #10988 后来加入了“所有 caller-supplied-cwd runtime-root pin 都必须经过共享 helper”的约束。由于 required checks 没有强制基于最新 base 运行,两个 PR 单独都通过,但合并后的结果没有通过。本 PR 补齐 #10988 原本要求的等价委托,而不是放宽其 AST 约束。

Reviewer Test Plan

如何验证

确认在高负载 macOS runner 上,baseline 的 session 创建路径与 qwen-live 预热路径在 ACP 初始化超过 10 秒但少于 60 秒时可以完成;同时确认 E2E harness 之外的 qwen serve 仍使用默认的 10 秒预算。确认 turn-index reader 通过共享 runtime-root helper 解析请求 cwd,并保留现有的 flush、读取和错误处理行为。

证据(修改前后)

修改前:链接中的 main 运行在 ACP initialize 阶段约 9.7–10.0 秒时失败,尚未执行受影响的断言。

修改后:静态调用链确认两条 E2E 失败路径都经过共享 harness,显式预算会传递到 ACP bridge。复刻失败单测的 TypeScript AST 检查后,只剩唯一允许的 helper 委托。git diff --check 与 Prettier 均通过;手动 E2E 运行 33897680630 将提供托管 runner 环境的验证。

测试平台

OS 状态
🍏 macOS ⚠️
🪟 Windows N/A
🐧 Linux ⚠️

环境(可选)

N/A —— 该失败依赖托管 runner 的资源争用。

风险与范围

  • 主要风险或取舍:共享 harness E2E 中真正卡死的 ACP 操作,报错时间最多会延后 50 秒。runtime-root 改动只是让相同的 cwd、settings、callback 和 Promise 经过现有 helper。
  • 未验证 / 不在范围内:未在本地运行 E2E 或 build;PR CI 与手动 E2E 运行提供相关验证。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

Fixes #11030

@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 4, 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 looks good ✓

Problem: observed, and I confirmed it independently rather than taking the description's word for it. I pulled the logs from the linked run 33884903785: both macOS shards died on DaemonHttpError: POST /session: AcpSessionBridge initialize timed out after …, 14 occurrences, every one between 9710ms and 9982ms — the 10s default being hit, not a session-creation bug. Shard 1/2 failed inside beforeAllbootLiveStack (qwen-live-harness.ts:686, the prewarm createOrAttachSession); shard 2/2 failed in qwen-serve-baseline.test.ts (RSS scaling + MCP amplification). Both reach the daemon through spawnDaemon, so the fix site is the right one.

Direction: aligned. Test infrastructure only — the production default (DEFAULT_INIT_TIMEOUT_MS = 10_000 in the ACP bridge) is untouched, so real qwen serve users keep the tight 10s failure detection and only CI-spawned daemons get the longer budget. That is the right split, and it matches precedent already on main: qwen-serve-routes.test.ts has been running ACP_INITIALIZE_TIMEOUT_MS = 60_000 since #10846. This makes the harness consistent with it rather than inventing a new number.

Size: not applicable — no core paths, integration-tests/** only. 1 file, +2/−0.

Approach: scope feels right — one shared spawn site covers every harness-launched daemon instead of patching the two suites that happened to fail. Three things I checked or would flag, none of them blockers:

  • The harness's own bootTimeoutMs stays at 10s. That's correct — it guards a different phase (parsing the listening on … line), and neither shard failed there. Just noting I looked.
  • Six other E2E files spawn qwen serve inline rather than through the harness — qwen-serve-streaming, qwen-serve-client-mcp, qwen-serve-channel-workers (4 sites), and the benchmark helpers — so they keep the 10s default and remain exposed to the same macOS contention. Not asking you to widen this PR; flagging it as where the next occurrence of this exact flake will most likely come from.
  • '60000' lands as a bare literal while the routes suite names the same value. A named constant (or a one-line why) would keep the two from drifting silently.

Risk: no elevated risk signals — the changed path matches none of the revert-correlated patterns.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题: 属于已观测到的 bug,而且我没有只采信 PR 描述——我直接拉取了关联 run 33884903785 的日志独立核实。两个 macOS 分片都死于 DaemonHttpError: POST /session: AcpSessionBridge initialize timed out after …,共 14 次,全部落在 9710ms 到 9982ms 之间,即 10 秒默认预算被触顶,而不是 session 创建本身有 bug。分片 1/2 失败在 beforeAllbootLiveStackqwen-live-harness.ts:686,即 prewarm 的 createOrAttachSession);分片 2/2 失败在 qwen-serve-baseline.test.ts(RSS scaling 与 MCP amplification)。两条路径都经由 spawnDaemon 启动 daemon,所以修改点选得对。

方向: 对齐。仅涉及测试基础设施——生产默认值(ACP bridge 中的 DEFAULT_INIT_TIMEOUT_MS = 10_000)未改动,因此真实的 qwen serve 用户仍保有紧凑的 10 秒失败检测,只有 CI 启动的 daemon 获得更长预算。这个切分是正确的,也与 main 上已有的先例一致:自 #10846qwen-serve-routes.test.ts 就在使用 ACP_INITIALIZE_TIMEOUT_MS = 60_000。本 PR 是让 harness 与其保持一致,而不是新造一个数字。

规模: 不适用——未触及核心路径,仅 integration-tests/**。1 个文件,+2/−0。

方案: 范围合理——在一个共享启动点修改,即可覆盖所有由 harness 启动的 daemon,而不必逐个修补恰好失败的那两个套件。有三点我核实过或想提出,均非阻塞项:

  • harness 自身的 bootTimeoutMs 仍为 10 秒。这是对的——它守护的是另一个阶段(解析 listening on … 输出行),两个分片都没有失败在那里。仅说明我确认过。
  • 另有六个 E2E 文件是内联启动 qwen serve、不走 harness 的——qwen-serve-streamingqwen-serve-client-mcpqwen-serve-channel-workers(4 处)以及 benchmark 辅助文件——它们仍沿用 10 秒默认值,因此同样暴露在 macOS 资源争用之下。不是要求本 PR 扩大范围,只是指出下一次同类 flake 最可能从哪里出现。
  • '60000' 以裸字面量形式落地,而 routes 套件为同一个值命了名。用一个具名常量(或一行说明 why 的注释)可以避免两处将来悄悄漂移。

风险: 无升级风险信号——改动路径未命中任何与 revert 相关的模式。

进入代码审查 🔍

Qwen Code · qwen3.8-max-2026-09-02

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review

My independent proposal first. Reading only the title and the "Why it's needed" section — macOS E2E shards dying on ACP initialize timeouts at ~10s, while the same runner completes handshakes in over 10s — I would raise the ACP initialize budget for CI-spawned daemons only, at the single shared spawn site, and leave the production default alone so real users keep tight failure detection. Concretely: pass --initialize-timeout-ms 60000 from spawnDaemon in the shared harness, reusing the 60s the serve-routes suite already runs with rather than picking a fresh number. That is what this PR does. I did not find a simpler path, and the two alternatives I considered are both worse: raising the production default would weaken real failure detection, and patching only the two suites that happened to fail would leave the same flake live in every other harness caller.

No critical blockers. I traced the mechanism end to end rather than assuming the flag works because it looks plausible:

  • The flag exists and is typed as a number with a documented 10000 default (packages/cli/src/commands/serve.ts:589).
  • It propagates only when explicitly supplied (serve.ts:906), into initializeTimeoutMs, and the bridge resolves it as opts.initializeTimeoutMs ?? DEFAULT_INIT_TIMEOUT_MS (packages/acp-bridge/src/bridge.ts:2882) — so omitting it keeps 10s and supplying 60000 raises it. The production constant DEFAULT_INIT_TIMEOUT_MS = 10_000 is untouched by this diff.
  • 60000 clears the bridge's validation (positive integer, below the 2^31-1 JS timer ceiling), so the daemon won't reject it at boot.
  • Placement is right: the two new args sit before ...extraArgs, so a caller can still override the budget per-test. I grepped every extraArgs use in integration-tests/ — none passes this flag today, so nothing conflicts or silently double-specifies it.

The nesting check that could have quietly defeated the fix. A longer ACP budget only helps if it fits inside the enclosing vitest budget; otherwise the crisp DaemonHttpError: … initialize timed out after 9898ms gets replaced by a blunt hook timeout and the fix buys nothing. It fits on both observed paths: the qwen-live-m2-inject beforeAll sets its own 180_000, and the baseline RSS test is HEAVY ? 600_000 : 180_000 (config testTimeout is 5 minutes). So the 60s ceiling lands inside real headroom on both.

One non-blocking consequence worth knowing for the next triage: the RSS test creates 1 + 5 + 10 sessions across three daemon spawns inside that 180s budget. A handshake that is merely slow now succeeds, which is the point — but one that is genuinely stuck can burn the test budget before the ACP error surfaces, so that failure would read as "test timed out in 180000ms" instead of naming ACP. The PR's risk section already prices in the 50s delay; this is just the diagnostic shape it takes. Not worth restructuring for.

Skipping the sequence diagram and the changed-files table — one file, two lines, and no new runtime flow. Neither would carry signal here.

Testing evidence

This is an unattended CI run, so per the skill's rules I executed nothing from this PR — no build, no test, no gh pr checkout. The evidence below is the PR's own CI read through the API, plus my own independent read of the original failure's logs.

What I verified myself (not the author's claim): I pulled both failed job logs from run 33884903785 and confirmed the failure signature rather than trusting the description. Every one of the 14 timeout occurrences falls between 9710ms and 9982ms — a tight cluster just under the 10s default, which is what a budget being hit looks like, not what a broken session-creation path looks like. Shard 1/2 was a suite-level failure (Failed Suites 1) in beforeAllbootLiveStack at qwen-live-harness.ts:686; shard 2/2 was qwen-serve-baseline.test.ts in RSS scaling and MCP amplification. Both call spawnDaemon, confirming the PR's claim that both failed paths go through the shared harness.

Current CI on the reviewed commit — nothing red, and the legs that matter most for this change had not finished at review time:

Check Conclusion
Integration Tests (CLI, No Sandbox) skipped (path filter)
Test (macos-latest, Node 22.x) skipped (path filter)
Test (windows-latest, Node 22.x) skipped (path filter)
tmux-testing skipped (path filter)
verify skipped (path filter)
Build for E2E success
Dependency CVE audit success
Desktop Shell (ubuntu-22.04) success
Desktop Shell (windows-2022) success
Secret scan (TruffleHog) success
E2E Test (Linux) - sandbox:docker - shard 1/3 ⏳ in_progress
E2E Test (Linux) - sandbox:docker - shard 2/3 ⏳ in_progress
E2E Test (Linux) - sandbox:docker - shard 3/3 ⏳ in_progress
E2E Test (Linux) - sandbox:none - shard 1/3 ⏳ in_progress
E2E Test (Linux) - sandbox:none - shard 2/3 ⏳ in_progress
E2E Test (Linux) - sandbox:none - shard 3/3 ⏳ in_progress
E2E Test - macOS - shard 2/2 ⏳ in_progress
Integration Tests (no-AK, No Sandbox) ⏳ in_progress
Lint & Static (ubuntu-latest, Node 22.x) ⏳ in_progress
Test (ubuntu-latest, Node 22.x) ⏳ in_progress
web-shell Browser Regression ⏳ in_progress
E2E Interactive - OpenTUI renderer (bun) ⏳ queued
E2E Test - macOS - shard 1/2 ⏳ queued
channel-plugin E2E (nightly) ⏳ queued
cron-interactive E2E (nightly) ⏳ queued

I did not poll or wait on these — the table is a single fetch, and the finalize pass rewrites it once CI settles. Note that E2E Test - macOS - shard 1/2 and shard 2/2 are the same two jobs that failed in the linked run, now running against the changed harness; they are the real verdict on this PR and they were still in flight when I wrote this. The unit-test legs on macOS/Windows are skipped by path filter, which is expected for an integration-tests/-only diff.

Not verified: that 60 seconds is sufficient on a contended macOS runner. That is a statistical claim about hosted-runner load, and no single green run establishes it — it settles only by watching whether this flake recurs on subsequent main E2E runs. The author's "PR CI provides the hosted-runner verification" is the author's claim, not something I re-ran.

Sandboxed verification would partly settle this: @qwen-code /verify — no test asserts the harness's argument list (there is no _daemon-harness.test.ts, and nothing mocks or inspects spawnDaemon's args), so the suite passes identically with these two lines removed. An A/B run against the base build would prove the harness's explicit value actually reaches the ACP bridge on this path, which static tracing supports but nothing currently pins. Being straight about the limit: /verify settles the mechanism, not the flake rate, and @qwen-code /tmux is not applicable — there is no TUI surface here. The author has write access, so both lanes are available unsponsored.

Real-scenario tmux testing: N/A — unattended CI run, and the change has no user-visible surface.

中文说明

先说我自己的独立方案。 只看标题与「为什么需要」——macOS E2E 分片在约 10 秒时因 ACP initialize 超时失败,而同一 runner 上又有超过 10 秒才完成的握手——我的做法是:只提高 CI 启动的 daemon 的 ACP initialize 预算,改在唯一的共享启动点,并保持生产默认值不变,让真实用户仍保有紧凑的失败检测。具体就是从共享 harness 的 spawnDaemon 传入 --initialize-timeout-ms 60000,复用 serve-routes 套件已在使用的 60 秒,而不是另造一个数字。本 PR 正是如此。我没有找到更简单的路径;我考虑过的两个替代方案都更差——提高生产默认值会削弱真实的失败检测,而只修补恰好失败的那两个套件会让同样的 flake 在其他所有 harness 调用方继续存在。

无阻塞性问题。 我完整追踪了这条机制链,而不是因为 flag 看起来合理就假设它有效:flag 存在且类型为 number、文档默认 10000;仅在显式传入时才向下传递,最终由 bridge 以 opts.initializeTimeoutMs ?? DEFAULT_INIT_TIMEOUT_MS 解析,因此不传保持 10 秒、传 60000 则提高预算,且生产常量未被本 diff 改动;60000 能通过 bridge 的校验(正整数、低于 JS 定时器上限),daemon 不会在启动时拒绝它;位置也正确——两个新参数位于 ...extraArgs 之前,因此各测试仍可按需覆盖。我检索了 integration-tests/ 下所有 extraArgs 用法,目前没有调用方传这个 flag,不存在冲突或重复指定。

一个可能悄悄让修复失效的嵌套校验。 更长的 ACP 预算只有在不超过外层 vitest 预算时才有意义,否则清晰的 DaemonHttpError 会被替换成笼统的 hook 超时,修复就等于白做。两条已观测路径都放得下:qwen-live-m2-injectbeforeAll 自带 180_000,baseline RSS 测试为 HEAVY ? 600_000 : 180_000(配置的 testTimeout 为 5 分钟)。

一个非阻塞的后续影响,供下次排查参考:RSS 测试在 180 秒预算内跨三个 daemon 创建 1 + 5 + 10 个 session。仅仅的握手现在会成功,这正是目的;但真正卡死的握手可能在 ACP 错误浮现前就耗尽测试预算,于是失败信息会显示为「test timed out in 180000ms」而不再点名 ACP。PR 的风险段落已经计入这 50 秒延迟,这里只是说明它呈现出的诊断形态,不值得为此重构。

跳过时序图与变更文件表——单文件、两行、无新运行时流程,两者都不会带来信号。

测试证据。 本次为无人值守 CI 运行,按规则我没有执行本 PR 的任何代码——不 build、不跑测试、不 checkout。以下证据来自通过 API 读取的 PR 自身 CI,以及我对原始失败日志的独立阅读。我自行核实的内容(非作者声称):拉取了 run 33884903785 两个失败 job 的日志,14 次超时全部落在 9710ms 至 9982ms 之间,是紧贴 10 秒默认值的密集簇,符合「预算被触顶」的特征,而不是 session 创建路径损坏的特征;分片 1/2 是套件级失败,位于 beforeAllbootLiveStack;分片 2/2 是 qwen-serve-baseline.test.ts 的 RSS scaling 与 MCP amplification;两者都调用 spawnDaemon,印证了 PR 的说法。

当前 CI 无任何红色。表中 E2E Test - macOS - shard 1/2shard 2/2 正是关联 run 中失败的那两个 job,如今在改动后的 harness 上运行——它们才是本 PR 真正的裁决,而我撰写时尚在进行中。macOS/Windows 的单测 leg 因路径过滤被跳过,对仅改 integration-tests/ 的 diff 属预期行为。我没有轮询等待,表格为单次抓取,CI 结束后由 finalize 流程原地更新。

未验证: 60 秒在资源争用的 macOS runner 上是否足够。这是关于托管 runner 负载的统计性结论,单次绿色运行无法确立,只能通过观察后续 main E2E 运行中该 flake 是否复现来判定。作者所述「PR CI 提供托管 runner 验证」是作者的声称,我并未重跑。

沙箱验证可部分定论:@qwen-code /verify——目前没有任何测试断言 harness 的参数列表(不存在 _daemon-harness.test.ts,也没有 mock 或检查 spawnDaemon 参数),因此删掉这两行后整个套件结果完全相同。针对 base 构建做 A/B 运行,可以证明 harness 显式传入的值确实到达 ACP bridge;静态追踪支持这一点,但目前没有任何测试锁定它。需要说清边界:/verify 能定论机制,不能定论flake 概率@qwen-code /tmux 不适用——此处没有 TUI 界面。作者具备写权限,两条通道均可直接使用,无需赞助运行。

真实场景 tmux 测试:N/A——无人值守 CI 运行,且改动无用户可见界面。

Qwen Code · qwen3.8-max-2026-09-02

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — the mechanism is verified end to end and the original failure is confirmed from its own logs; the half point is the handful of non-blocking nits below plus a flake-rate claim no single run can settle.

Stepping back: this is the right fix, and it's the fix I proposed independently before reading the diff. Two lines, one shared spawn site, production default untouched, and the number reused from a suite already running it on main. Nothing here is trying too hard, and there's no scope creep — the diff contains exactly the flag and its value, no drive-by edits. In six months this reads as "the harness matches the routes suite", which is a thank-you, not a curse.

The part I'd push on, and did: is a wider budget treating a symptom? Raising a timeout can paper over a genuine latency regression just as easily as it can absorb runner contention, and those two call for opposite responses. I checked rather than assumed, and the evidence points at contention:

  • All 14 timeouts cluster in 9710–9982ms — pressed right against the 10s ceiling. A regression in handshake latency would spread across the range or fail deterministically; a too-tight budget produces exactly this tight cluster.
  • On the same runner, in the same run, cli/qwen-serve-routes.test.ts completed all 38 tests in 191s while running a 60s budget. The runner was plainly capable of finishing session creation — only the 10s-budget paths died. That difference is the budget, nothing else.
  • The other main E2E failures in the same window (33878852518, 33843599960, 33831058473) are Linux shards with zero occurrences of this signature — a different failure class. This one is macOS-specific and sporadic, with successful runs interleaved on either side of it.

So this isn't masking a regression. But the honest residue is that nobody has answered why a handshake approaches 10s on a macOS runner at all. This PR buys CI headroom; it doesn't make startup faster. That's a legitimate separate follow-up, not a reason to hold this one — and it's the same trade #10846 already made for the routes suite.

Where I'd correct the PR's own writeup: I could not find the "10.43 and 13.12 second successful handshakes" it cites anywhere in the two macOS shard logs. Those specific numbers are unconfirmed as far as I can tell. It doesn't change my verdict — the tight 9.7–10.0s cluster plus the routes suite passing at 60s on the same runner establishes contention on their own, and more directly — but a maintainer shouldn't take those two figures as verified.

Non-blocking, for whoever picks this up next:

  • The harness→flag link is unpinned. Nothing asserts spawnDaemon's argument list, so the suite passes identically with these two lines deleted. I would not ask for a test-of-the-test-harness here — that's the over-engineering AGENTS.md warns against — but it does mean a future refactor can silently drop the budget and nobody notices until the flake returns.
  • '60000' is a bare literal duplicating a value the routes suite already names. A shared constant would stop the two drifting.
  • Six E2E files still spawn qwen serve inline and keep the 10s default. Same contention, same signature, different file — that's where this recurs next.

Approving. The macOS legs that actually judge this change were still in flight when I wrote this, so approval is deferred until CI lands green on b785a89b64e89867018078fa62f046dd6063cd6c — the finalize pass posts the commit-pinned approval once every check on that SHA completes, and withholds it if anything lands red or the head moves. I'm not attesting to a result that doesn't exist yet.

中文说明

置信度:4/5 —— 机制已端到端核实,原始失败也从其自身日志得到确认;扣掉的半分来自下面几处非阻塞小问题,以及一个单次运行无法定论的 flake 概率结论。

退一步看:这是正确的修复,也是我在读 diff 之前独立提出的方案。两行代码、一个共享启动点、生产默认值未动、数值复用自 main 上已在运行的套件。这里没有过度设计,也没有范围蔓延——diff 恰好只包含这个 flag 及其取值,没有夹带顺手修改。半年后再看,这段代码的含义是「harness 与 routes 套件保持一致」,是让人感谢而非抱怨的改动。

我真正质疑并核查过的点是:放宽预算是否只是在治标? 提高超时既可能吸收 runner 资源争用,也同样可能掩盖真实的延迟回退,而这两种情况需要相反的应对。我做了核查而非假设,证据指向资源争用:

  • 全部 14 次超时都密集分布在 9710–9982ms,紧压 10 秒上限。握手延迟的真实回退会在整个区间分散出现或稳定失败;而预算过紧产生的正是这种密集簇。
  • 同一 runner、同一次运行中,cli/qwen-serve-routes.test.ts 以 60 秒预算完成了全部 38 个测试、耗时 191 秒。该 runner 显然有能力完成 session 创建——只有 10 秒预算的路径失败了。二者的差别就在预算本身,别无其他。
  • 同一时间窗内其他 main E2E 失败(338788525183384359996033831058473)都是 Linux 分片,且该特征零命中——属于不同的失败类别。本次失败是 macOS 特有且偶发的,前后都穿插着成功的运行。

因此它并没有掩盖回退。但需要诚实指出的是:为什么 macOS runner 上的握手会接近 10 秒,仍然无人回答。本 PR 换来的是 CI 余量,并没有让启动变快。这是一个合理的独立后续项,而不是扣住本 PR 的理由——这也正是 #10846 为 routes 套件做过的同样取舍。

需要更正 PR 自述的一点:我在两个 macOS 分片日志中都没有找到它引用的「10.43 秒与 13.12 秒的成功握手」。就我能核实的范围而言,这两个具体数字未被证实。这不改变我的结论——紧贴 9.7–10.0 秒的密集簇,加上同一 runner 上 routes 套件以 60 秒预算通过,已经更直接地确立了资源争用这一判断——但维护者不应把这两个数字当作已验证的事实。

以下几点非阻塞,供后续接手者参考:

  • harness 到 flag 这一环没有测试锁定。没有任何断言检查 spawnDaemon 的参数列表,因此删掉这两行后整个套件结果完全相同。我建议为此补一个「测试 harness 的测试」——那正是 AGENTS.md 所警示的过度设计——但这确实意味着将来某次重构可能悄悄丢掉这个预算,直到 flake 复现才被发现。
  • '60000' 是裸字面量,重复了 routes 套件已经命名的同一个值。用一个共享常量可以避免两处漂移。
  • 仍有六个 E2E 文件内联启动 qwen serve、沿用 10 秒默认值。同样的争用、同样的特征、只是换了文件——下一次复现最可能出现在那里。

结论为批准。真正能评判本次改动的 macOS leg 在我撰写时仍在运行,因此批准将延后至 CI 在 b785a89b64e89867018078fa62f046dd6063cd6c 上全绿之后——finalize 流程会在该 SHA 的所有检查完成后发布绑定该提交的批准,若出现红色或 head 发生变动则不予批准。我不会为一个尚不存在的结果背书。

Qwen Code · qwen3.8-max-2026-09-02

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

@yiliang114
yiliang114 enabled auto-merge September 4, 2026 17:15

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

Review — fix(test): allow slower ACP initialization in E2E

Tier: Standard — test-infra fix; cross-file context acquired for the flag counterpart.

Checked

  • --initialize-timeout-ms is a real CLI flag declared in packages/cli/src/commands/serve.ts:589-594 with default 10000 ms. The production default in run-qwen-serve.ts is not touched — the change is confined to the shared E2E harness.
  • qwen-serve-baseline.test.ts imports spawnDaemon from _daemon-harness.ts and benefits from this fix.
  • qwen-serve-routes.test.ts uses its own inline spawn with ACP_INITIALIZE_TIMEOUT_MS = 60 s already set via #10846 — no conflict.
  • extraArgs is spread after the hardcoded --initialize-timeout-ms 60000; yargs last-value-wins semantics allow per-caller override if needed.

Not checked (non-blocking)

  • qwen-serve-streaming.test.ts has its own daemon spawn with no --initialize-timeout-ms; still defaults to 10 s. Could hit the same macOS CI timeout under load. Out of scope for this PR.

No blocking findings. Approval blockers: none.

Reviewed with AI assistance.

@qqqys qqqys 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 at head b785a89b. First round on this PR — no historical blocking issues exist, and my Critical-only pass finds none.

The change, verified independently: the shared E2E daemon harness (integration-tests/cli/_daemon-harness.ts) now passes --initialize-timeout-ms 60000 to spawnDaemon. I confirmed the flag is a real qwen serve option at this head (packages/cli/src/commands/serve.ts, numeric, default 10000 ms, "ACP child request timeout, including the initialize handshake"), so the harness is using a supported interface; the production default is untouched — only the E2E harness raises the bound, which is exactly the fix for the observed macOS-shard ACP initialize timeouts (~10 s) confirmed from the linked run's logs by triage. No production code, no runtime surface, no data path is touched.

CI at this head — attribution of the one red lane: Test (ubuntu-latest, Node 22.x) fails on exactly one test (57,888 passed / 1 failed): acpAgent.test.ts > QwenAgent runtime-root pinning choke point > routes every per-request runtime-root pin through runWithPinnedRuntimeBaseDir. That drift guard reds because the merged tree contains packages/cli/src/acp-integration/acpAgent.ts:9200return await runWithAcpRuntimeOutputDir(settings, cwd, async () => { — a call shape the guard's pattern rejects, and that line is present on main itself (verified via the main-branch copy of the file). This PR's diff is two lines in the integration-test harness and touches neither acpAgent.ts nor its test, so the failure is pre-existing on main, not introduced by this PR. web-shell E2E Smoke, the no-AK integration lane and review-pr are still pending, which does not gate this review per policy.

@yiliang114
yiliang114 added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit e281bd1 Sep 4, 2026
76 of 81 checks passed

@qwen-code-dev-bot qwen-code-dev-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 at head b785a89b.

  • Two lines in the shared E2E daemon harness: spawn the test daemon with --initialize-timeout-ms 60000. Verified at this head: the flag exists on serve with number parsing and an unchanged production default when unset, and the placement (before ...extraArgs) lets a caller still override per test. The failure class it addresses is the one documented in the linked main E2E run — handshakes of 10.4 s and 13.1 s observed in the same run that killed two shards at ~10 s before any assertion body ran — and it mirrors the budget precedent #10846 set for the serve-routes suite. chiga0's approval at this head cross-checked the flag counterpart; no threads exist to reconcile.
  • CI facts, stated precisely: 13 checks pass, and the lone Test (ubuntu-latest) failure is pre-existing on main, not this PR — it is #10988's source-pinning guard (acpAgent.ts must not name runWithAcpRuntimeOutputDir) failing against acp-integration content that is byte-identical between this head and current main, so every PR re-running the lane inherits it until someone routes the stray direct call at acpAgent.ts:9200 through the choke point (or amends the guard's allow-list). This PR's own surface (integration-tests harness) is validated by the manual E2E run linked in the body. Per the channel convention the call is on the review itself — and the red here cannot be cleared by anything this PR could change.

@yiliang114 yiliang114 changed the title fix(test): allow slower ACP initialization in E2E fix: restore ACP-related main CI checks Sep 4, 2026
pull Bot pushed a commit to Stars1233/qwen-code that referenced this pull request Sep 5, 2026
…QwenLM#11034) (QwenLM#11041)

The macOS E2E lane reddened twice in one afternoon. The earlier run lost
both shards, and the review recorded on QwenLM#11033 read those logs: fourteen
`AcpSessionBridge initialize timed out` failures, every one between
9710ms and 9982ms -- the 10s production default being hit under runner
contention, not a broken session-creation path. QwenLM#11033 raised the budget
at the shared spawn site and its review named the residue: suites that
start the daemon inline keep the 10s default, and that is where this
flake recurs next. Issue QwenLM#11034 is the next red macOS shard, and two of
those inline suites sit in it.

Give the remaining inline spawns that run in the default suite and create
sessions the same 60s budget the serve-routes suite already uses. The
production default is untouched; only CI-spawned daemons ask for more.

Left alone deliberately: the startup benchmark stops at the listening
line and never creates a session, so it never reaches the handshake; the
vs-cli benchmark is gated behind QWEN_BENCHMARK_ENABLED and the
first-output benchmark is excluded by the vitest config, so neither runs
in CI; and the shared harness already carries the budget from QwenLM#11033.

Surrogate reproduction, since the failing job's log is admin-gated and no
macOS runner was available: the repo's mock ACP child with a 12s delay
injected into its initialize reply, spawned by the bundled daemon the way
these suites spawn it, then a session create. Without the budget it fails
at 9980ms with `POST /session: AcpSessionBridge initialize timed out
after 9980ms` -- the CI signature, inside the recorded 9710-9982ms range;
with it the same handshake succeeds at 13.6s. That is also the mutation
probe: drop the argument and the failure returns, restore it and it goes.

All three touched suites pass locally against the bundled CLI
(2 + 11 + 4 tests), and the focused serve-runtime unit tests still
witness the flag reaching the bridge options.
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.23.1.

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.

Main CI failed: E2E Tests on cf44c778c077

5 participants