Skip to content

fix(cli): emit deferred stream-json startup warnings - #7174

Merged
wenshao merged 1 commit into
QwenLM:mainfrom
barry166:barry166/fix-stream-json-startup-warnings-7158
Jul 18, 2026
Merged

fix(cli): emit deferred stream-json startup warnings#7174
wenshao merged 1 commit into
QwenLM:mainfrom
barry166:barry166/fix-stream-json-startup-warnings-7158

Conversation

@barry166

Copy link
Copy Markdown
Contributor

Summary

  • write startup warnings generated during deferred stream-json initialization to stderr
  • preserve the existing early warning output by only emitting warnings added during initialization
  • cover the warning delta and deduplication behavior with a session regression test

Fixes #7158.

Testing

  • npm run test --workspace=packages/cli -- src/nonInteractive/session.test.ts
  • npm run typecheck --workspace=packages/cli
  • npm run lint --workspace=packages/cli -- src/nonInteractive/session.ts src/nonInteractive/session.test.ts
  • npm exec prettier -- --check packages/cli/src/nonInteractive/session.ts packages/cli/src/nonInteractive/session.test.ts
  • git diff --check

Stream-json defers configuration initialization until its session receives input, but warnings generated during that deferred step were never surfaced to automation clients. Snapshot already-emitted warnings, then write only initialization-time additions to stderr and lock the behavior with a focused regression test.

Constraint: Preserve the existing pre-initialization warning output without duplicates
Rejected: Route warning state through the Session constructor | unnecessary interface expansion for a local delta
Confidence: high
Scope-risk: narrow
Directive: Keep deferred initialization diagnostics on stderr for stream-json consumers
Tested: packages/cli session test; CLI typecheck; ESLint; Prettier check; diff check
Not-tested: End-to-end CLI invocation with a filesystem-generated startup warning
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template: the body uses ## Summary / ## Testing instead of the repository's PR template headings (## What this PR does, ## Why it's needed, ## Reviewer Test Plan, etc.). The key information is present and the linked issue is well-documented, so not blocking on this — but please use the template headings on future PRs to help reviewers navigate quickly.

Problem: observed bug with a clear reproduction in #7158. Stream-json mode silently drops startup warnings generated during deferred config.initialize(). Plain headless and interactive modes surface them correctly. The issue provides a concrete repro sketch and identifies the root cause.

Direction: aligned — startup warnings should reach users regardless of input format. SDK and automation clients consuming stream-json are exactly the audience that can't discover misconfiguration any other way. This matches the existing pattern in gemini.tsx (the non-stream-json branch already does snapshot + delta emission).

Size: 34 additions, 0 deletions across 2 files (production: ~10 lines, test: ~24 lines). Not applicable for core module checks.

Approach: minimal and focused. Snapshot pre-init warnings into a Set, emit only the delta after initialize(). Mirrors the established pattern in gemini.tsx line-for-line. No scope creep.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板: PR 正文使用了 ## Summary / ## Testing,而非仓库模板要求的 ## What this PR does## Why it's needed## Reviewer Test Plan 等标题。关键信息已提供,关联 issue 文档清晰,不因此阻塞——但未来请使用模板标题以便 reviewer 快速定位。

问题: 已在 #7158 中观测到并提供复现。Stream-json 模式下,config.initialize() 期间产生的启动警告被静默丢弃。普通 headless 和交互模式正常输出。Issue 提供了具体复现步骤和根因分析。

方向: 对齐——无论输入格式如何,启动警告都应触达用户。Stream-json 的消费者(SDK 和自动化客户端)恰恰是最需要发现配置异常的一方。与 gemini.tsx 中的已有模式一致。

规模: 34 行新增,0 行删除,涉及 2 个文件(生产代码约 10 行,测试约 24 行)。不触及核心模块保护规则。

方案: 最小且聚焦。将初始化前的警告快照到 Set 中,initialize() 后仅输出增量。与 gemini.tsx 中的既有模式逐行一致。无范围蔓延。

进入代码审查 🔍

Qwen Code · qwen3.7-max

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal (before reading the diff): snapshot config.getWarnings() into a Set before config.initialize(), then iterate post-init warnings and emit only the delta to stderr — mirroring the existing gemini.tsx pattern.

The PR's implementation matches this proposal exactly. In ensureConfigInitialized:

  1. Snapshot pre-init warnings into a Set before config.initialize()
  2. After init, iterate config.getWarnings(), skip any already in the Set, emit the rest to stderr, and add them to the Set for dedup

This is line-for-line consistent with the non-stream-json branch in gemini.tsx (line ~1061). Clean, minimal, no unnecessary abstraction.

One minor note: gemini.tsx uses writeStderrLine(warning) while this PR uses process.stderr.write(\${warning}\n`). Functionally identical, but the helper exists. Not blocking — the inline write is clearer in context and the \n` matches the helper's behavior.

No correctness bugs, security holes, or regressions found. Test covers both legs of the dedup: pre-existing warning NOT re-emitted, new warning IS emitted.

Real-Scenario Testing

Ran stream-json mode end-to-end in tmux. No startup warnings were triggered in this CI environment (no legacy plan files or team-memory config present), so the before/after comparison shows clean stream-json output on both sides. The fix targets a code path that the unit test directly exercises.

Before (installed build, v0.19.11)

$ echo '{"type":"user","session_id":"test","message":{"role":"user","content":"say hello"}}' | qwen --input-format stream-json --output-format stream-json 2>before-stderr.log
{"type":"system","subtype":"init","uuid":"3b29f8d5-...","session_id":"3b29f8d5-...","model":"qwen3.7-max",...}
{"type":"assistant","uuid":"2677c7d3-...","message":{"content":[{"type":"text","text":"Hello! How can I help you today?"}],...}}
{"type":"result","subtype":"success","result":"Hello! How can I help you today?","duration_ms":8238,...}
---STDERR---
(empty — no warnings triggered)

After (PR code via npm run dev)

$ echo '{"type":"user","session_id":"test","message":{"role":"user","content":"say hi"}}' | npm run dev -- --input-format stream-json --output-format stream-json 2>after-stderr.log
{"type":"system","subtype":"init","uuid":"51753308-...","session_id":"51753308-...","model":"qwen3.7-max",...}
---STDERR---
DEV is set to true, but the React DevTools server is not running. Start it with:
$ npx react-devtools

Both runs complete successfully. Stderr is clean (the DevTools message is a dev-environment notice, not related to this fix). The unit test (36/36 passing) directly verifies the warning-delta behavior.

中文说明

代码审查

独立方案(阅读 diff 前):在 config.initialize() 之前将 config.getWarnings() 快照到 Set 中,初始化后遍历警告集合,仅将增量输出到 stderr——与 gemini.tsx 中的既有模式一致。

PR 的实现与此方案完全一致。在 ensureConfigInitialized 中:

  1. config.initialize() 前将已有警告快照到 Set
  2. 初始化后遍历 config.getWarnings(),跳过已在 Set 中的,输出新增的,并加入 Set 去重

gemini.tsx(约第 1061 行)的非 stream-json 分支逐行一致。干净、最小化、无不必要的抽象。

一个细节: gemini.tsx 使用 writeStderrLine(warning) 而本 PR 使用 process.stderr.write(\${warning}\n`)`。功能等价,内联写入在此上下文中更清晰。不阻塞。

无正确性缺陷、安全漏洞或回归。测试覆盖了去重的两个分支:已有警告不被重复输出,新增警告被正确输出。

真实场景测试

在 tmux 中端到端运行了 stream-json 模式。该 CI 环境未触发启动警告(无遗留 plan 文件或团队记忆配置),因此 before/after 对比显示两边均为干净的 stream-json 输出。单元测试直接覆盖了修复目标代码路径。

两次运行均成功完成,stderr 无异常输出。单元测试 36/36 通过,直接验证了警告增量行为。

Qwen Code · qwen3.7-max

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

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — Clean across every stage; a textbook bugfix.

This is what a good external contribution looks like: a real bug with a filed issue (#7158, P2), a minimal fix that mirrors the established pattern in gemini.tsx, and a test that actually verifies the behavior rather than just exercising the code path.

The fix is 10 lines of production code that snapshot pre-init warnings and emit only the delta after config.initialize() — exactly the right approach, and exactly what the non-stream-json branch already does. No scope creep, no unnecessary abstraction, no drive-by refactors.

The test is well-designed: it sets up pre-existing warnings, mocks initialize() to add a new one, and asserts both legs (old warning NOT re-emitted, new warning IS emitted). All 36 session tests pass.

Stream-json mode runs cleanly end-to-end in both the installed build and the PR code.

Approving. ✅

中文说明

信心度:5/5 — 各阶段均通过;教科书级别的 bugfix。

这是一个优秀外部贡献的典范:真实 bug 已有 P2 issue(#7158),最小化修复与 gemini.tsx 中的既有模式一致,测试实际验证了行为而非仅仅跑通代码路径。

修复仅 10 行生产代码:在 config.initialize() 前快照已有警告,初始化后仅输出增量——正是正确的做法,也是非 stream-json 分支已有的做法。无范围蔓延、无不必要的抽象、无顺手重构。

测试设计良好:预设已有警告,mock initialize() 新增一条,断言两个分支(旧警告不重复输出,新警告正确输出)。36 个 session 测试全部通过。

Stream-json 模式在安装版本和 PR 代码中均端到端正常运行。

已批准 ✅

Qwen Code · qwen3.7-max

Reviewed at 947c91f794969a6c6035ec07904675a21f6a0755 · 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.

No issues found. LGTM! ✅

— qwen3.7-max via Qwen Code /review

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅

— qwen3.7-max via Qwen Code /review

@wenshao
wenshao added this pull request to the merge queue Jul 18, 2026
Merged via the queue into QwenLM:main with commit 50fd4d4 Jul 18, 2026
55 checks passed
tanzhenxin added a commit that referenced this pull request Jul 19, 2026
Resolves the ACP bootstrap conflict (keep #7145 profiling wrapper + warning
emission), drops the session.ts warnings block superseded by #7174, and
guards the ACP getWarnings call against stubbed configs.

Claude-Session: https://claude.ai/code/session_01KwsYFzWZ6VLCxVN8MbeFXb
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.

stream-json mode silently drops startup warnings generated during initialization

4 participants