mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 12:11:09 +00:00
6.1 KiB
6.1 KiB
PR-1 实操清单:主屏闪烁基础修复
本文档把 10-issue-oriented-flicker-plan.md 里的
PR-1落成可以直接照着做的执行清单。目标是让下一步进入编码时,不需要再重新讨论 scope、文件边界和测试顺序。
1. 目标
PR-1 只做主屏主路径的基础修复,覆盖两类问题:
- 普通 assistant 流式输出时的高频抖动
refreshStatic()导致的整屏 clear + redraw
这条 PR 允许顺带加入观测与回归基线,因为它们与主屏主路径共用同一组验证场景。
1.1 实施校准
fix/main-screen-flicker 实施后需要把本文的原始设想校准成源码事实:
- 已安全落地:stdout redraw counters、content/thought stream throttle、
/clear与 slash clear 的重复清屏削减。 - 未在
PR-1中落地:compact merge、active view switch、settings toggle、resize 的 remount-only 改道。 - 原因:Ink
<Static>是永久追加输出模型,remount 本身不会删除旧 static output。对这些已经打印过历史内容的路径,如果不先 clear 就 remount,可能引入重复历史或旧 view 残留。
因此,PR-1 的 closure 口径应是“主屏流式高频闪烁 + 已清屏路径的重复 clear”,而不是“彻底拆完所有 refreshStatic() 触发源”。后续 PR 不应继续在当前 <Static> 架构下把这些路径简单替换成 remount-only。
2. 非目标
以下内容不在 PR-1 中实现:
- synchronized output / DECSET 2026
- 窄屏 / interactive shell 修复
- 大工具输出 pre-slicing
- stable height / bounded detail panel
- tool budgeting /
llmContent语义变更 - Markdown parser / token cache 重构
3. 文件边界
3.1 预计会修改的文件
packages/cli/src/ui/utils/terminalRedrawOptimizer.tspackages/cli/src/ui/hooks/useGeminiStream.tspackages/cli/src/ui/AppContainer.tsxpackages/cli/src/ui/components/MainContent.tsxpackages/cli/src/ui/layouts/DefaultAppLayout.tsx
3.2 可能波及的文件
packages/cli/src/ui/components/SettingsDialog.tsxpackages/cli/src/ui/hooks/slashCommandProcessor.tspackages/cli/src/ui/contexts/UIActionsContext.tsxpackages/cli/src/ui/contexts/UIStateContext.tsx
3.3 预计要补或更新的测试
packages/cli/src/ui/utils/terminalRedrawOptimizer.test.tspackages/cli/src/ui/hooks/useGeminiStream.test.tsxpackages/cli/src/ui/AppContainer.test.tsxpackages/cli/src/ui/components/SettingsDialog.test.tsx
如果没有合适的 MainContent 独立测试,再决定是否新增:
packages/cli/src/ui/components/MainContent.test.tsx
4. 建议的实现顺序
Step 1:补最小观测能力
先在不改行为的前提下补这些 counters:
stdout_write_countstdout_bytesclear_terminal_counterase_lines_optimized_count
要求:
- 不改变现有
stdout.write()语义 - screen reader 路径不误装
- 先只做数据采集,不引入 DECSET 2026
Step 2:实现 content / thought 流式节流
在 useGeminiStream.ts 中:
- 为 content stream 增加 buffer + timer flush
- thought stream 共用同一 flush 模型
- 在这些节点强制 flush:
- stream end
- cancel
- tool call start
- confirm dialog render 前
要求:
- 保持
findLastSafeSplitPoint()逻辑继续生效 - 不引入 split/promote 双重渲染
Step 3:拆分 refreshStatic() 语义
从当前单一 refreshStatic() 拆成:
remountStaticHistory()clearTerminalAndRemount()
然后逐个清点触发源,优先改这些:
MainContent的 compact mergeDefaultAppLayout的 active view switchSettingsDialog的局部设置切换AppContainer的 resize 处理
要求:
/clear仍保留旧语义- 仅已先执行清屏的路径可以直接改成 remount-only
- compact merge、active view switch、settings toggle、resize 需要新的 static replacement 策略后再改,不能在当前
<Static>追加模型下直接移除 clear
Step 4:把回归场景补齐
最少要补这 3 类测试:
useGeminiStream的 flush / cancel / final flushrefreshStatic()新旧语义与调用路径- 输出 counters 的不退化 smoke test
5. 建议的 commit 切分
为了让 reviewer 更容易看,建议一个 PR 里至少拆成 3 个 commit:
test/obs(cli): add redraw counters and baseline assertionsfix(cli): throttle gemini stream updates on main screenfix(cli): split refreshStatic remount from clear terminal
如果测试改动很多,可以再单独加一个:
test(cli): cover refreshStatic and stream flush regressions
6. 复现与验收清单
6.1 固定复现场景
- 冷启动(无 MCP)
- 冷启动(含 1 个慢 MCP server)
- 长 assistant 回答(至少 500 token)
- thought + content 混合流
/settings上下切换- compact mode merge
- active view switch
- 终端宽高 resize
/clear
6.2 通过标准
stdout.write频率下降clear_terminal_count下降- 结束 / cancel 不丢尾部内容
/clear/ slash clear 不再出现console.clear()后紧接额外clearTerminal的重复清屏/clear保持当前用户语义
7. issue 归属提醒
PR-1 可以声称解决或显著缓解:
#1184#1491#3007#938#1861#2924
#2748 在这条 PR 中只应作为 flicker 子问题样本 引用,不建议直接在 PR-1 里声明完全关闭。
8. 提交前命令
建议按这个顺序跑:
cd /Users/gawain/Documents/codebase/opensource/qwen-code/.claude/worktrees/tui-optimization/packages/cli
npx vitest run src/ui/utils/terminalRedrawOptimizer.test.ts
npx vitest run src/ui/hooks/useGeminiStream.test.tsx
npx vitest run src/ui/AppContainer.test.tsx
npx vitest run src/ui/components/SettingsDialog.test.tsx
如果新增了 MainContent 独立测试,再补跑对应文件。
9. 实施后的下一步
PR-1 合并后,优先进入:
PR-2:大输出与详情展开稳定性PR-3:窄屏 / interactive shell 专项
只有在 PR-1 ~ PR-3 主路径收敛后,才推进 PR-4 的 synchronized output 灰度。