# Taglauncher WindowServer 会诊 ## 用户目标 - 作为代码审核员,基于管理员诊断说明会诊 TagLauncher 是否是 2026-07-01 大规模系统卡顿 / WindowServer watchdog 的重要原因之一。 - 按用户要求拉两位架构师和两位代码审核员共同做只读审查。 - 输出是否仍存在重大隐患,以及后续最小验证 / 缓解方向。 ## 当前起点 - 项目:`/Users/ar/Projects/Taglauncher` - 源码根目录:`/Users/ar/Projects/Taglauncher/src` - 诊断说明:`/Users/ar/Documents/技术实验室/TagLauncher-WindowServer-CursorUIViewService-诊断说明-2026-07-01.md` - 开工时分支:`codex/pro-custom-hotkeys-8.2.0` - 开工时 HEAD:`4c6f31c Remove non-source materials from source worktree` - 开工时工作区状态:已有大量未提交改动,按用户 / 其他任务既有改动处理,本轮不回滚、不改源码。 - 最终核对时 HEAD 已由外部流程推进到 `0ae3a93 Prepare TagLauncher 8.3.1 candidate`,并带 tag `v8.3.1-build20260701.2302`;这不是本轮会诊创建的 commit。 ## 核心事实 / 变更快照 - 诊断中的故障包:`TagLauncher 8.3.0 (20260701.2029)`。 - 本机 `/Applications/TagLauncher.app` 当前读到:`8.3.0 (20260701.2234)`。 - 当前源码 `src/Apptag/Info.plist` 读到:`8.3.1 (20260701.2302)`。 - 最终核对时 `src/Apptag/ContentView.swift`、`src/Apptag/ApptagApp.swift`、`src/Scripts/tag_editor_mouse_event_qa.sh` 对当前 HEAD 已无 diff,说明相关修复已经进入 `0ae3a93`。 - `20260701.2029` 是本地验收 DMG,不是正式冻结包;会话记录已明确其未冻结 commit / tag。 - 20260701 晚些时候已有一轮“编辑标签卡死”修复记录:`26.0701-Taglauncher.发布修复-编辑标签崩溃和额度刷新.md`。 - 该修复已把 `TextFieldContainer.mouseDown` 和 `DismissibleHostingView.mouseDown` 中“把同一 `NSEvent` 手动转发给 `NSTextField.mouseDown` / `TextFieldContainer.mouseDown`”改为 focus-only 路径,并新增 `tag_editor_mouse_event_qa.sh` 防回归。 ## 已完成事项 - 读取并遵守项目入口规则、`CODE_GOVERNANCE.md`、`CODEGRAPH.md`、全局 code / debugging / QA / delivery / session memory 规则。 - 读取管理员诊断说明并提取核心链路:TagLauncher CPU resource / hang -> CursorUIViewService on-behalf-of TagLauncher -> WindowServer CPU resource/watchdog。 - 派出 4 个只读子代理: - 架构师 A:窗口 / 事件系统。 - 架构师 B:文本输入 / 焦点 / IME。 - 审核员 C:事件转发 / `mouseDown` / monitor。 - 审核员 D:窗口 / 渲染 / 资源风险。 - 主线程复核关键源码:`ApptagApp.swift`、`OverlayWindowController.swift`、`QuickSearch.swift`、`ContentView.swift`、`AppGridCollectionView.swift`、`TagNavigationView.swift`、`AppGridSupport.swift`、`PreferencesView.swift`、`AppDragCoordinator.swift`。 ## 关键结论 1. `20260701.2029` 故障包很可能命中过“同一鼠标事件被手动转发到 NSTextField.mouseDown”的问题。 - 证据:当前 diff 显示旧代码曾调用 `container.mouseDown(with: event)` / `tf.mouseDown(with: event)` / `textField.mouseDown(with: event)`,而当前工作区已修成 `focusTextField()` / `makeFirstResponder + selectText`。 - 诊断栈中的 `NSControl/NSView mouseDown`、`forwardMethod`、`NSTextInputContext`、`IMKInputSession` 与这个问题高度吻合。 - 这部分在 `20260701.2234` 后已有静态 QA 防回归。 2. 不能把所有 WindowServer 问题完全定责给 TagLauncher。 - 系统是 macOS 27 beta / build 26A5368g,TextInputUI、SCIM、WindowServer 自身也可能有系统侧放大。 - 但诊断里的 `On Behalf Of` 链路足以把 TagLauncher 列为重点触发入口 / 放大因素。 3. 当前代码仍存在需要立即处理或强验证的重大隐患,尤其是 Quick Search + 中文输入法 / IME 候选窗路径。 - 当前 `QuickSearchNativeTextField` 和 delegate command path 没有 marked-text guard。 - Quick Search 打开期间 global mouse monitor 可能把 IME 候选窗点击当作外部点击并关闭文本客户端。 - Quick Search 每次更新可能重复 `NSApp.activate` / `makeKeyAndOrderFront` / `orderFrontRegardless`,并排 4 次 delayed focus。 4. 仍存在多个窗口/事件架构风险。 - `TagNavigationView.mouseDown` 里有阻塞式 `while` + `window?.nextEvent(... inMode: .eventTracking)`,缺失窗口失活 / mouseUp 丢失 / monitor 吞事件时的硬退出条件。 - `AppGridCollectionHostView` / Usage Tips 的 `hitTest` 会触发状态变更、first responder、hover 刷新,`hitTest` 不再是纯命中测试。 - Usage Tips local mouse monitor 对非 overlay 窗口事件用 `NSEvent.mouseLocation` 映射,可能吞掉同 App 其它窗口事件。 - overlay 是 `.nonactivatingPanel` 但允许 key/main,同时 AppDelegate 多处切 activation policy、activate、orderFront。 5. 当前发布判断:`20260701.2234` 比 `20260701.2029` 明显更安全,但在 macOS 27 + 简体中文输入法环境下仍不应视为彻底安全。建议进入阻塞修复 / 诊断增强,而不是直接发布。 ## 主要隐患清单 - P0:Quick Search 抢 IME 候选键。 - 路径:`src/Apptag/QuickSearch.swift` 的 `doCommandBy` 与 `QuickSearchNativeTextField.keyDown`。 - 问题:Up / Down / Return / Escape 在 marked text 状态下应优先交给 IME。 - P0:IME 候选窗鼠标点击可能被 Quick Search global mouse monitor 当作外部点击关闭。 - 路径:`src/Apptag/ApptagApp.swift` 的 `installQuickSearchExternalMouseMonitor`;`src/Apptag/ContentView.swift` 的 `closeQuickSearch`。 - 问题:候选窗属于 TextInputUI/CursorUIViewService,点击候选时撤掉文本客户端很危险。 - P1:Quick Search 输入期间重复抢焦点 / 重排窗口。 - 路径:`QuickSearchPanelPresentationView.updateNSView`、`Coordinator.apply`、`QuickSearchTextField.requestFocus`、`promoteOverlayToForegroundInput`。 - 问题:每次 query/result update 都可能触发窗口置前、first responder 切换、输入上下文 activate。 - P1:`DismissibleHostingView.mouseDown` 仍在顶层同步切文本 first responder。 - 路径:`src/Apptag/ApptagApp.swift`。 - 问题:虽已停止同事件转发,但已编辑 / marked text 状态下外层截获仍可能破坏原生光标、候选坐标和 input context。 - P1:`TagNavigationView.mouseDown` 阻塞式事件循环。 - 路径:`src/Apptag/TagNavigationView.swift`。 - 问题:`mouseUp` 丢失、窗口隐藏、App resign active 或事件被 monitor 吞掉时,主线程可能困在 `mouseDown` 栈。 - P1:Usage Tips 的 `hitTest` / local monitor 有副作用和误吞风险。 - 路径:`src/Apptag/AppGridCollectionView.swift`。 - 问题:`hitTest` 触发 hover/first responder/刷新;非本窗口事件按屏幕坐标映射后可能被吞。 - P1:App note 泡泡使用 SwiftUI `TextField` + 非激活 overlay + 主动提升焦点。 - 路径:`src/Apptag/AppGridSupport.swift`、`src/Apptag/ContentView.swift`、`src/Apptag/ApptagApp.swift`。 - 问题:中文 composition 期间 binding 截断、焦点提升和透明全屏 panel 组合风险高。 - P2:Quick Search 点击启动缺少 de-dupe guard。 - 路径:`src/Apptag/QuickSearch.swift`、`src/Apptag/ContentView.swift`。 - 问题:双击 / 抖动点击可能在 panel 关闭前多次 launch。 - P2:拖拽碎纸预览使用无限 CA 动画,依赖正常结束路径清理。 - 路径:`src/Apptag/AppDragCoordinator.swift`。 - 问题:窗口隐藏、App 失活或事件取消时需证明动画和 layer 一定清理。 ## QA / 验证结论 本轮只做只读 / 静态检查,不做源码修改,不构建。 已执行并通过: ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/tag_editor_mouse_event_qa.sh bash Scripts/quick_search_launch_contract_qa.sh ``` 结果: ```text PASS Tag editor mouse event QA: text-field clicks focus without recursive mouseDown forwarding PASS quick search launch contract ``` 已执行: ```bash cd /Users/ar/Projects/Taglauncher git diff --check -- src/Apptag/ContentView.swift src/Apptag/ApptagApp.swift src/Apptag/QuickSearch.swift src/Apptag/OverlayWindowController.swift src/Apptag/AppGridCollectionView.swift src/Scripts/tag_editor_mouse_event_qa.sh ``` 结果:无输出,表示相关 diff 无 whitespace 错误。 不作为有效证据: ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/window_logic_qa.sh ``` 该脚本会操作 Dock、defaults、LaunchAgent 和 GUI,不适合本轮只读会诊;已中断,退出码 130。脚本含 `trap cleanup EXIT`,后续检查 TagLauncher 仍在运行、`TAGLAUNCHER_QA_PRO_STATE` 为空。 ## 可复用命令 / Runbook 用途:复查 20260701 WindowServer / CursorUIViewService 会诊中的静态门禁和版本基线。 前置条件: - 项目路径:`/Users/ar/Projects/Taglauncher` - 源码目录:`/Users/ar/Projects/Taglauncher/src` - 本轮命令不替代真实 GUI/IME 复现;WindowServer/IME 问题必须在 macOS 27 + 简体中文输入法环境单独验证。 静态 QA: ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/tag_editor_mouse_event_qa.sh bash Scripts/quick_search_launch_contract_qa.sh ``` 版本基线核对: ```bash defaults read /Applications/TagLauncher.app/Contents/Info CFBundleShortVersionString defaults read /Applications/TagLauncher.app/Contents/Info CFBundleVersion plutil -p /Users/ar/Projects/Taglauncher/src/Apptag/Info.plist ``` 源码风险定位: ```bash cd /Users/ar/Projects/Taglauncher rg -n "mouseDown|mouseDragged|mouseUp|sendEvent|hitTest|NSTextInputContext|inputContext|firstResponder|makeFirstResponder|addLocalMonitor|addGlobalMonitor|orderFrontRegardless|makeKeyAndOrderFront|NSVisualEffectView|reloadData" src/Apptag --glob '*.swift' ``` 建议新增的真实复现步骤: 1. macOS 27.0 / 简体中文输入法下打开 Quick Search。 2. 输入拼音使候选窗可见。 3. 分别按 Up / Down / Return / Escape,确认候选窗优先处理而不是 Quick Search 抢键。 4. 用鼠标点击候选词,确认 Quick Search 不因 global mouse monitor 关闭。 5. 连续输入 20 个中文字符,记录 `makeFirstResponder`、`orderFront`、`inputContext` activate 次数和 WindowServer / CursorUIViewService CPU。 6. 长按 TagNavigation 并在拖拽中切换 App / Esc / 隐藏 overlay,确认 `mouseDown` 事件循环有退出。 搜索关键词:`WindowServer`、`CursorUIViewService`、`20260701.2029`、`20260701.2234`、`Quick Search IME`、`markedText`、`mouseDown forwardMethod`、`tag_editor_mouse_event_qa`、`Usage Tips hitTest`、`TagNavigation nextEvent` ## 未决问题 - 未直接读取原始 sysdiagnose `.diag` 文件;本轮基于管理员整理的诊断说明和项目源码审查。 - 未做真实中文 IME GUI 复现;这是下一轮必须补的反馈环。 - 开工时工作区脏状态很大;最终核对时大部分源码改动已进入 `0ae3a93`,仍有 6 个历史 Release 文档文件处于 modified 状态。后续修复前必须先明确是否基于 `0ae3a93 / v8.3.1-build20260701.2302` 继续。 - `window_logic_qa.sh` 是 GUI/系统状态脚本,不适合只读会诊;后续若要跑,需按 QA 场景安排并确保用户知道会操作本机 GUI/Dock。 ## 后续建议 1. 先修 Quick Search marked text / IME 候选窗两项 P0,并补静态 + 真实中文输入法 QA。 2. 给 Quick Search focus/orderFront、overlay activation、input context、mouseDown event number 增加临时 signpost/counter,建立可复现反馈环。 3. 将 `DismissibleHostingView.mouseDown` 对文本控件的外层截获收窄:已编辑或 marked text 时放行原生事件。 4. 把 `TagNavigationView.mouseDown` 改成非阻塞状态机,或至少加失活 / 超时 / mouseUp 丢失保护。 5. 清理 Usage Tips `hitTest` 副作用和 local monitor 对非 overlay 事件的误吞风险。 6. 在 P0/P1 处理并复现通过前,不建议把当前版本作为 macOS 27 + 中文输入法环境的安全发布候选。