fix(cli): replace emoji thinking/summary icons with Unicode text symbols - #5788
Conversation
The TUI uses a consistent vocabulary of width-1 Unicode text glyphs (✦ ● ○ ◐ ✓ ↓ ↑ + ink-spinner). Two status indicators broke this with emoji, which render at width=2 and drift column alignment across the CI/LANG fallback branches. - THINKING_ICON: replace the three-way fallback (💡 / ⟡ / empty) with a single ∴ (U+2234 THEREFORE) constant. The math "therefore" sign matches the thinking block's "deriving a conclusion" semantics and sits on a stable wide base. Drops the isUtf8/CI branch entirely. - SummaryMessage success: replace ✅ with ✓ to match ToolMessage's existing success glyph — same "operation succeeded" meaning, no redundant emoji variant. Both replacements are width=1 and render identically across terminals/CI, removing the column drift the old fallback caused. Refs #5787
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Thanks for the PR, @pomelo-nwu! The change itself looks reasonable — replacing width-2 emoji with width-1 Unicode symbols for consistent column alignment is a clean fix.
However, the PR body is missing a few required sections from the PR template:
- Risk & Scope — even for a two-line change, the template asks for risk/tradeoff and scope notes. For this PR it could be as simple as "Risk:
∴may render differently across fonts; out of scope: remaining 30+ emoji tracked in #5787." - Tested on table — the OS checklist lets reviewers know which platforms were verified. Since this is a TUI rendering change, cross-platform confirmation matters.
- Evidence (Before & After) — the body says "Before/after TUI screenshots to be appended" but they haven't been added yet. For a TUI change, this is the main thing reviewers need to see.
Could you fill in those sections? Once the template is complete, happy to continue the review.
中文说明
感谢贡献 @pomelo-nwu!改动本身合理——用 width-1 的 Unicode 符号替换 width-2 的 emoji 来保证列对齐齐,是个干净的修复。
但 PR 正文缺少 PR 模板 中的几个必填部分:
- Risk & Scope — 即使只改了两行,模板也要求填写风险/权衡和范围说明。这个 PR 可以简单写:"风险:
∴在不同字体下渲染可能不同;不在本次范围:#5787 中跟踪的其余 30+ emoji。" - Tested on 表格——OS 清单让 reviewer 知道在哪些平台验证过。TUI 渲染改动尤其需要跨平台确认。
- Evidence (Before & After)——正文写了"Before/after TUI screenshots to be appended"但还没有补上。TUI 改动最重要的就是让 reviewer 看到前后对比。
请补充这些部分,模板齐全后继续 review。
— Qwen Code · qwen3.7-max
Before / After TUI evidenceRendered the real BEFORE —
|
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No review findings. Downgraded from Approve to Comment: CI still running. — qwen3.7-max via Qwen Code /review
wenshao
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
Clean simplification — replacing width-2 emoji with width-1 Unicode symbols eliminates the isUtf8/CI branching and makes the thinking icon consistent across all environments. Build and tests pass (19/19).
— qwen3.7-max via Qwen Code /review
✅ Local build + real-render verification — PR #5788Verified at commit What the PR changes
Results
Real rendered output (actual Ink frames)The harness asserts each frame contains Regression / scope analysis
Notes for the maintainer (not defects)
VerdictBuild, typecheck, the affected test suites, and the real rendered TUI output all check out at 🇨🇳 中文版(完整对应)✅ 本地构建 + 真实渲染验证 — PR #5788验证 commit: PR 改了什么
结果
真实渲染输出(实际 Ink 帧)harness 断言每一帧包含 回归 / 范围分析
给维护者的说明(非缺陷)
结论在 — verified with |
|
One forward-looking note on the thinking icon: the Both states currently render the same glyph: The streaming state is semantically "gathering reasons" — that's I verified Not asking to reopen this PR — it's merged, correctly scoped, and the emoji→text swap is the right baseline. This is a small semantic refinement, could be a tiny follow-up or folded into batch 2 of #5787. Thoughts? 中文说明关于 thinking 图标的一个前瞻性建议: 当前两个状态共用同一个符号: 流式态在语义上是"正在收集理由"——这是 我用 不是要重开这个 PR——它已合并、范围界定正确,emoji→文本符号的替换是正确基线。这只是一个小的语义优化,可以做成一个微型 follow-up PR,或并入 #5787 的第二批。怎么看? — Qwen Code |
Comprehensive cleanup of emoji in TUI rendering paths (follow-up to #5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated
Comprehensive cleanup of emoji in TUI rendering paths (follow-up to #5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated
Comprehensive cleanup of emoji in TUI rendering paths (follow-up to #5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated
Comprehensive cleanup of emoji in TUI rendering paths (follow-up to #5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated
Comprehensive cleanup of emoji in TUI rendering paths (follow-up to #5787 / #5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated
QwenLM#5999) * fix(cli): replace all emoji status icons with Unicode text symbols Comprehensive cleanup of emoji in TUI rendering paths (follow-up to QwenLM#5787 / QwenLM#5788). Replaces width-2 emoji with width-1 Unicode text symbols from the project's existing glyph vocabulary. ## Source changes (25 source files) Status indicators: - McpStatus: 🟢→● 🔄→◐ 🔴→● (colors preserved via Text color prop) - ideCommand: 🟢→● 🟡→◐ 🔴→● (both getIdeStatusMessage functions) - Footer: 🔒 removed (sandbox text label is self-explanatory) - Footer: ⚙→▷ (workflow active indicator) - ToolMessage: ⏳→◌ (progress + queued approval) - McpStatus: ⏳→◌ (server startup message) - LiveAgentPanel: ⏸→‖ (pause glyph) Text prefixes and labels: - StatusMessages: 🔎→◎ (vision bridge gutter prefix) - Session: 🚫→✗ (blocked notifications) - useGeminiStream: 🔎→◎ 🚫→✗ 💡→★ (prefixes and headers) - useContextualTips: 💡→★ (tip prefix) - WelcomeBackDialog: 👋🎯📋 removed (text labels are self-explanatory) - CreationSummary: ✅→✓ ❌→✗ - summaryCommand: ❌→✗ - AppContainer: ❌→✗ - AgentEditStep: ❌→✗ - useAutoAcceptIndicator: ℹ️→i - McpStatus Tips: 💡→★ Core package: - agent-statistics: 📋→▸ 🔧→● ⏱️→(stripped) 🔁→● 🔢→● ✅→✓ 🚀→● 💡→★ - shell: 🤖 removed from PR attribution footer - artifact-tool: 📄 removed from publish display - coreToolScheduler:⚠️ →⚠ (strip VS16) Standardized⚠️ (U+26A0+VS16, width-2) → ⚠ (U+26A0, width-1): - CommandFormatMigrationNudge, command-migration-tool, useGeminiStream i18n: all 9 locale files updated for changed keys. ## Test changes (5 test files) - ideCommand.test.ts: 5 emoji assertions updated - McpStatus.test.tsx: 13 snapshots updated - HistoryItemDisplay.test.tsx: 🔎→◎ assertions - useGeminiStream.test.tsx: VS16 + 🔄 assertions - agent-statistics.test.ts: all emoji assertions updated * fix(cli): address review feedback — fix docs, tests, and glyph issues - Fix McpStatus test snapshots to actually exercise connecting/disconnected states via serverStatus prop instead of ineffective vi.spyOn mock - Update user docs (status-line.md, ide-integration.md) to match new symbols - Change Footer workflow indicator from ⚙ to ▷ for consistency - Fix Duration line leading space in agent-statistics formatCompact/formatDetailed - Revert ‖ (U+2016, EAW=Ambiguous) back to ⏸ (EAW=Narrow) for CJK terminals - Restore 🤖 in PR attribution (GitHub web UI, not TUI) - Add old emoji to lspCommand.test.ts negative assertion - Tighten Footer test to assert full ▷ glyph text * fix(cli): sync JSDoc with code for shell attribution and regenerate McpStatus snapshot * fix(cli): distinct IDE status glyphs + mark LLM-facing retry directives - ideCommand: Connected and Disconnected both rendered an identical bullet differing only by color, indistinguishable under deuteranopia/protanopia, in NO_COLOR terminals, or when copy-pasted. Use the PR's established ✓/✗ vocabulary (✓ Connected, ✗ Disconnected); Connecting keeps ◐. - coreToolScheduler: note that the ⚠ in the two RETRY_LOOP directives is an LLM-facing prompt string, not a TUI glyph, so it isn't 'fixed' for width later. Co-Authored-By: Qwen-Coder <noreply@qwen.ai> --------- Co-authored-by: pomelo.lcw <pomelo.lcw@alibaba-inc.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> Co-authored-by: Qwen-Coder <noreply@qwen.ai>
What this PR does
The Qwen Code TUI is built on a consistent vocabulary of width-1 Unicode text glyphs —
>for user messages,✦for assistant replies,●/○/◐for todo and selection states,✓for success,↓/↑for token flow, and braille⠋⠙⠹frames for the spinner. Every one of these is a narrow text symbol that renders predictably across terminals, fonts, and CI logs. Two status indicators broke this consistency with emoji, and this PR replaces them with text symbols from the same family: the thinking block icon💡→∴(U+2234 THEREFORE), and the summary success icon✅→✓(matchingToolMessage's existing success glyph).Why it's needed
Emoji are not just a style mismatch — they have real technical downsides in a TUI. They render at width=2 (e.g.
💡= 2 columns) while every other glyph is width=1, so indented blocks drift depending on which code path rendered them. The thinking icon already encoded this pain: it branched into three different outputs (💡/⟡/ empty) based onCIandLANG, so the same thinking line occupied a different number of columns depending on where it ran. The∴replacement is width=1 and renders identically everywhere, which lets us delete the entireisUtf8/CIbranch and collapseTHINKING_ICONto a single constant. The✅→✓change removes a redundant emoji variant of a glyph the project already standardized on —ToolMessageuses✓in success color for the exact same "operation succeeded" meaning.Reviewer Test Plan
How to verify
npm run dev, send any prompt that triggers model reasoning → the thinking block header should read∴ Thinking…(and∴ Thought for Nswhen collapsed), replacing the old💡./chat summary→ on success the checkmark should be✓(green), matchingToolMessage's success state, instead of✅.CI/LANGbranch is gone.Evidence (Before & After)
Rendered the real
ThinkMessageandSummaryMessagecomponents viaink-testing-library, captured withtmux capture-pane(120×40 viewport). Same props on both sides — only the icon constant differs.BEFORE —
mainAFTER — this branch
Note
💡is width=2 — the thinking header and the wrapped streaming text sit one column to the right of∴(width=1). Onmainthis drift varied by environment (CI/LANG); after this PR the thinking line is width=1 everywhere.Tested on
Windows/Linux not tested locally, but the change is pure glyph replacement (
∴U+2234 and✓U+2713 are common math/check symbols present in all mainstream monospace fonts). No platform-specific rendering logic.Environment
npm run dev(tsx, direct source) on macOS. Component render verified viaink-testing-library. Related unit tests:ConversationMessages.test.tsx(10),SessionPreview.test.tsx(7),HistoryItemDisplay.test.tsx(25) — all passing.Risk & Scope
∴(U+2234) verified width=1 viastring-width; renders in SF Mono / Menlo / JetBrains Mono / Fira Code.THINKING_ICONis still an exported string constant; consumers (ThinkingViewer.tsx) import it unchanged. The only behavioral difference is the glyph and the removal of the environment-dependent width drift.Linked Issues
Closes #5787 (first batch).
中文说明
本 PR 做了什么
Qwen Code 的 TUI 建立在一套统一的 width-1 Unicode 文本符号体系上——
>用户消息、✦助手回复、●/○/◐todo 与选择态、✓成功、↓/↑token 流向、盲文⠋⠙⠹spinner 帧。这些符号宽度都是 1,在各终端、字体、CI 日志里渲染一致。两处状态指示器用 emoji 破坏了这一致性,本 PR 用同族文本符号替换:thinking 图标💡→∴(U+2234 数学"所以"),summary 成功图标✅→✓(对齐 ToolMessage 已有的成功符号)。为什么需要
emoji 不仅是风格不匹配,在 TUI 里有真实技术缺陷:渲染宽度为 2(如
💡占 2 列),而其他符号都是 1,导致缩进块在不同代码路径下漂移。thinking 图标已经反映了这个痛点——它根据CI/LANG分支成三套输出(💡/⟡/空),同一条 thinking 行在不同环境占不同列宽。∴替换是 width=1,各环境渲染一致,因此可以删除整个isUtf8/CI分支,把THINKING_ICON收敛成单常量。✅→✓移除了一个多余的 emoji 变体——项目已有✓(ToolMessage 成功态用),✅是重复。验证方法
npm run dev,发任意触发模型推理的 prompt → thinking 标题应显示∴ Thinking…(折叠态∴ Thought for Ns),替代旧的💡。/chat summary→ 成功后勾选符应为✓(绿色),与 ToolMessage 成功态一致,替代✅。CI/LANG分支已删除。证据(Before & After)
用 ink-testing-library 渲染真实的 ThinkMessage / SummaryMessage 组件,tmux capture-pane 截取(120×40 视口)。两侧 props 一致,只有 icon 常量不同。
改动前(main):
💡 Thinking…/💡 Thought for 12s/✅ Project summary...改动后(本分支):
∴ Thinking…/∴ Thought for 12s/✓ Project summary...注意
💡占 width=2,thinking 标题及换行文本比∴(width=1)多偏移一列。main 上这个偏移随环境变化(CI/LANG);本 PR 后 thinking 行在所有环境都是 width=1。测试环境
macOS 本地验证(npm run dev + ink-testing-library)。Windows/Linux 未本地测试,但改动是纯字符替换(
∴U+2234、✓U+2713 是主流等宽字体均含的常见数学/勾选符号),无平台特定渲染逻辑。相关单元测试全过(ConversationMessages 10 + SessionPreview 7 + HistoryItemDisplay 25)。风险与范围
∴(U+2234)已验证 width=1。THINKING_ICON仍是导出的字符串常量,消费方(ThinkingViewer.tsx)import 不变。唯一行为差异是字符本身及环境相关的宽度漂移被消除。关联 Issue
Closes #5787(第一批)。