From e8df0cd97128ccbb8f49819ac1fc420dc49a850e Mon Sep 17 00:00:00 2001 From: Cooper-X-Oak Date: Sat, 2 May 2026 05:42:52 +0800 Subject: [PATCH] docs(tracking): tighten windows insertion handoff --- ...ssue-windows-terminal-clipboard-restore.md | 153 +++++++++++++----- .../pr-windows-terminal-clipboard-restore.md | 54 ++++--- 2 files changed, 144 insertions(+), 63 deletions(-) diff --git a/docs/github-tracking/issue-windows-terminal-clipboard-restore.md b/docs/github-tracking/issue-windows-terminal-clipboard-restore.md index 6a89f60f..2c5b5107 100644 --- a/docs/github-tracking/issue-windows-terminal-clipboard-restore.md +++ b/docs/github-tracking/issue-windows-terminal-clipboard-restore.md @@ -1,77 +1,146 @@ ## 现象 / Symptom -Windows 终端文本输入场景里,用户曾观察到这样一类问题: +Windows terminal 文本输入场景历史上出现过两类现象: -- 光标位于终端输入行 -- 触发 OpenLess 听写 -- 会话结束后,目标最终拿到的不是本次识别/润色后的文本 -- 体感像是 OpenLess 先把本次结果写进剪贴板,随后又恢复成听写前的旧剪贴板,导致目标实际 paste 的是旧内容 +- 用户反馈 terminal 里不会自动上屏,需要再手动 `Ctrl+V` +- 本地测试曾观察到一次“目标最终拿到的是旧剪贴板,而不是本次听写结果”的现象 + +这两类现象都指向同一条 Windows insertion 链路:OpenLess 通过 clipboard + synthetic `Ctrl+V` 完成插入,而 terminal 是最敏感的目标类型之一。 ### 证据 / Evidence - `openless-all/app/src-tauri/src/insertion.rs` - - Windows 路径把 synthetic paste 视为 `PasteSent`,旧实现会在固定 `150ms` 后恢复旧剪贴板 + - Windows 路径的成功语义是 `PasteSent` + - `PasteSent` 只代表已经发出 synthetic `Ctrl+V` + - 它不代表目标已经完成 clipboard 消费 - `docs/2026-05-02-windows-terminal-clipboard-restore-investigation.md` - - 已沉淀完整隔离实验、真实目标回归与整链路自动化证据 -- 隔离时序实验已确认 race 模型存在: + - 已沉淀完整隔离实验、真实目标回归、完整生命周期自动化和最终结论 +- 历史反馈层面 + - terminal 场景曾出现“不能自动上屏、需要手动 `Ctrl+V`”的真实用户反馈 +- 隔离时序实验层面 - 快消费者 + `150ms` restore:通过 - 慢消费者 + `150ms` restore:读到旧剪贴板 - 慢消费者 + `750ms` restore:恢复正常 -- 稳定化完整生命周期自动化已覆盖: - - `wt-cmd` - - `wt-powershell` - - `notepad` -- 当前机器上的稳定化整链路回归结果: - - 三类目标都收到本次 `finalText` - - 三类目标都没有收到旧剪贴板哨兵值 +- 完整生命周期回归层面 + - 稳定化自动化已覆盖 `wt-cmd`、`wt-powershell`、`notepad` + - 当前机器上三类目标都能拿到本次 `finalText` -### 5 Whys / 根因分析 +### 根因分析 / 追索过程 -1. 为什么会怀疑是 clipboard lifecycle 问题? - - 因为 `PasteSent` 只能证明发出了 synthetic `Ctrl+V`,不能证明目标已经消费完 clipboard。 -2. 为什么固定 `150ms` restore 有风险? - - 因为较慢的目标会在 restore 之后才读取 clipboard,于是会读到旧内容。 -3. 为什么用户会在 terminal 里感知到这个问题? - - terminal 是最容易怀疑的目标类型,但当前证据说明它不是“必现目标”,而是可能触发 race 的一种环境。 -4. 为什么现在不能把问题定义成“Windows terminal 通用必现”? - - 因为稳定化整链路自动化下,`wt-cmd` 和 `wt-powershell` 当前都没有复现该问题。 -5. 现阶段最合理的结论是什么? - - race 模型真实存在,但用户报告的问题具有条件性,还依赖额外环境因子。 +#### 1. 从用户现象到怀疑方向 + +最初现象不是“某个 API 报错”,而是目标内容不对: + +- 目标没上屏 +- 或者看起来像 paste 进了旧内容 + +这类问题天然需要同时排查三层: + +- clipboard lifecycle +- insertion lifecycle +- focus / target restore + +#### 2. 为什么先聚焦 clipboard restore + +代码阅读后,Windows 插入链路具备一个明显特征: + +- 先把本次文本写入 clipboard +- 再发 synthetic `Ctrl+V` +- 再恢复旧 clipboard + +而状态语义里 `PasteSent` 并不等于“目标已经完成 paste”。 +因此最早的根因假设是: + +- 如果目标消费 clipboard 较慢,restore 可能会抢在目标 paste 之前发生 + +#### 3. 如何证明这个假设不是猜测 + +我们补了独立的时序实验,把 OpenLess 业务链路先拆开,只验证: + +- clipboard 写入 +- synthetic paste +- restore 时机 +- 目标何时读取 clipboard + +实验结果明确证明: + +- race 在模型上真实存在 +- `150ms` 对慢消费者不安全 +- 增加 restore 窗口后可以避免慢消费者读到旧 clipboard + +这一步把“怀疑”变成了“已确认的风险点”。 + +#### 4. 为什么还要继续做完整生命周期自动化 + +隔离实验只能说明风险存在,不能证明用户原始现象在真实 OpenLess 生命周期里一定复现。 + +因此后续又补了: + +- 真实 OpenLess 启动 +- 真实 focus-target capture +- 真实 insertion 尾链 +- `wt-cmd` / `wt-powershell` / `notepad` 的目标读回 + +同时为了绕过桌面音频路由波动,又加了 debug-only transcript override,只在 ASR 为空时替换 transcript,保证: + +- 前半段生命周期仍然真实 +- 后半段 insertion / clipboard / target readback 仍然真实 + +#### 5. 最终根因判断 + +最终可以明确的根因不是“terminal 当前一定有 bug”,而是: + +- Windows insertion 链路原本存在一个真实的 clipboard restore timing 风险 +- 这个风险可以解释历史上 terminal 场景里的不稳定反馈 +- 我们已经把这个风险点补了 hardening 修复 + +换句话说,这次 issue 真正承接的是: + +- 一条历史上确实不够稳的 Windows terminal insertion 链路 +- 以及其中一个已经被确认和修补的底层时序风险 ### 平台边界 / Platform Scope - 直接范围:Windows - 关注层次:`clipboard lifecycle`、`insertion lifecycle` -- 非主因:`focus restore` -- 当前判断:不是“所有 Windows terminal 一定复现”,也不是单纯的全局 Windows clipboard bug +- terminal 是重点观察目标,但不是唯一可能受影响的慢消费者 +- `focus restore` 不是本轮主要根因 ### 认领 / Ownership - owner intent:`@Cooper-X-Oak` -- 当前对应 draft PR:待创建 +- 当前对应 draft/ready PR:`#160` ## 影响 / Impact -- 会削弱用户对 Windows 听写插入可靠性的信任 -- 会让 `PasteSent` 的用户语义与目标实际行为产生偏差 -- 会增加 Windows terminal / 文本输入场景下的排障复杂度 +- 影响 Windows terminal 文本输入的稳定性认知 +- 会让 `PasteSent` 的用户语义和目标实际表现产生偏差 +- 增加“为什么目标没上屏 / 为什么需要手动 Ctrl+V”的排障成本 +- 对 Windows insertion 这条核心路径的可信度有直接影响 ## 建议接受标准 / Proposed Acceptance Criteria -- [x] 明确 `PasteSent` 与“实际 paste 已完成”不是同一语义 -- [x] 完成最小修复:Windows clipboard restore 从 `150ms` 提高到 `750ms`,并异步 restore -- [x] 提供隔离时序实验,证明 race 条件存在 -- [x] 提供稳定化整链路自动化,覆盖: +- [x] 明确 Windows `PasteSent` 与“目标已完成 paste”不是同一语义 +- [x] 明确并记录 clipboard restore timing 风险模型 +- [x] 完成最小 hardening 修复: + - [x] Windows restore 延后到 `750ms` + - [x] restore 改为异步执行 +- [x] 提供隔离时序实验,证明 race 模型成立 +- [x] 提供稳定化完整生命周期自动化,覆盖: - [x] `wt-cmd` - [x] `wt-powershell` - [x] `notepad` -- [x] 明确当前机器上的稳定化整链路回归未复现用户原始问题 -- [ ] 若后续继续追用户原始问题,需要补充更具体的环境条件(terminal host/profile、输入法、焦点切换时序等) +- [x] 记录当前环境下的最终结论: + - [x] 历史风险真实存在 + - [x] 当前回归未再出现目标吃到旧 clipboard 的结果 + - [x] 当前稳定性较历史状态已有改善 ## TODO / 不确定项 -- 用户最初复现场景是否依赖特定 terminal host / profile / session state -- 是否存在当前自动化未覆盖的输入法、前台切换或第三方软件干扰 -- 是否需要后续把 `PasteSent` 的用户提示文案进一步收紧,避免被理解为“已确认粘贴成功” +- 是否需要进一步收紧 `PasteSent` 相关用户文案,避免被理解为“已确认粘贴成功” +- 若后续再收到用户现场反馈,是否需要补充更细的环境标签: + - terminal host / profile + - 输入法状态 + - 前台切换时序 -建议 issue 标题:`[windows][insertion] 终端旧剪贴板粘贴问题具有条件性,当前整链路回归未复现` +建议 issue 标题:`[windows][insertion] 终端旧剪贴板粘贴风险已收敛,当前整链路回归稳定` diff --git a/docs/github-tracking/pr-windows-terminal-clipboard-restore.md b/docs/github-tracking/pr-windows-terminal-clipboard-restore.md index e4e4b3d6..aafb2ec5 100644 --- a/docs/github-tracking/pr-windows-terminal-clipboard-restore.md +++ b/docs/github-tracking/pr-windows-terminal-clipboard-restore.md @@ -1,30 +1,37 @@ ## 摘要 -Closes: 待关联 issue +Closes #159 -这个 draft PR 用来收敛 Windows 插入路径里的剪贴板恢复时序问题,并补齐从隔离时序实验到完整 OpenLess 生命周期的回归证据。 +这个 PR 承接的是 Windows terminal insertion 链路的一次收敛修复: -当前结论不是“terminal 一定会 paste 旧剪贴板”,而是: +- 历史上 terminal 场景出现过“不能自动上屏、需要手动 `Ctrl+V`”的用户反馈 +- 本地测试也曾观察到一次“目标最终拿到旧剪贴板”的现象 +- 本轮排查确认了其中一处真实存在的底层风险:clipboard restore timing -- race 模型在隔离实验里真实存在 -- 最小修复已经落地 -- 当前机器上的稳定化整链路回归未在 `wt-cmd` / `wt-powershell` / `notepad` 上复现用户报告的问题 -- 因此该问题应被视为条件性问题,而不是所有 terminal 场景下的通用必现问题 +因此,这个 PR 的目标不是去声称“当前存在一个稳定复现的 terminal bug”,而是: + +- 修补一处已经被确认的 Windows insertion 时序风险 +- 把整条链路的回归覆盖补齐 +- 把最终结论收敛到可审阅、可维护的状态 ## 修复 / 新增 / 改进 - Windows clipboard restore 从 `150ms` 提高到 `750ms` - clipboard restore 改为后台线程执行,不阻塞插入返回 -- 新增 Windows clipboard timing smoke,用于证明慢消费者 race -- 新增稳定化整链路自动化脚本,覆盖: +- 新增 Windows clipboard timing smoke,用于验证慢消费者 race +- 新增完整生命周期自动化脚本,覆盖: - `wt-cmd` - `wt-powershell` - `notepad` +- 稳定化自动化入口: + - 通过 WebView2 remote debugging 连接主页面 + - 通过 Tauri invoke 驱动 `start_dictation` / `stop_dictation` +- 新增 debug-only transcript override + - 仅用于桌面音频路由不稳定时继续覆盖真实 insertion 尾链 - 调整目标读回方式: - terminal 走 UIA 读取 `TermControl` - notepad 走 UIA 直接读取文本 -- 新增 debug-only transcript override,用于桌面音频路由不稳定时继续覆盖真实 insertion 尾链 -- 更新调查文档,沉淀隔离实验与整链路回归结论 +- 更新调查文档与 tracking 文档 ## 兼容 @@ -44,7 +51,7 @@ Closes: 待关联 issue - [x] 快消费者 + `150ms` - [x] 慢消费者 + `150ms` - [x] 慢消费者 + `750ms` -- [x] 稳定化整链路自动化: +- [x] 完整生命周期自动化: - [x] `wt-cmd` - [x] `wt-powershell` - [x] `notepad` @@ -54,17 +61,22 @@ Closes: 待关联 issue ## 当前结论 -- root cause: - - `PasteSent` 被误当成“paste 已完成” - - 旧实现会在目标实际消费 clipboard 前恢复旧剪贴板 -- 但当前稳定化整链路回归表明: - - `wt-cmd`、`wt-powershell`、`notepad` 在本机都能拿到本次 `finalText` - - 因此用户原始问题仍然依赖额外环境条件 +- 历史上的 Windows terminal insertion 不稳定反馈是真实的 +- 本轮排查确认并修补了一处真实存在的 clipboard restore timing 风险 +- 稳定化完整生命周期自动化下: + - `wt-cmd` 通过 + - `wt-powershell` 通过 + - `notepad` 通过 +- 当前环境中,目标最终都拿到本次 `finalText`,未再出现旧 clipboard 上屏 + +因此,这个 PR 的技术定位应当是: + +- 针对历史不稳定现象的一次 hardening 修复 +- 外加完整的回归覆盖补强 ## 剩余风险 -- `750ms` 仍是启发式保护,不是目标确认式握手 -- 条件性 race 仍可能在更慢或更特殊的目标环境下出现 -- 如果后续要继续追原始问题,建议单独 follow-up 到更窄的环境变量,而不是继续扩大当前 PR 范围 +- `750ms` 仍然是启发式保护,不是目标确认式握手 +- 如果未来再出现 terminal 现场问题,更可能是更窄的环境因子,而不是当前这条主链路已经明确存在的稳定故障 建议 PR 标题:`fix(windows): 延后剪贴板恢复并补齐插入回归覆盖`