2026/9/16 17:41:15

Plate Slate v2 验证计划:为 iOS Safari 组合输入与焦点恢复收集真机外部证据

Plate Slate v2 验证计划:为 iOS Safari 组合输入与焦点恢复收集真机外部证据 Plate Slate v2 验证计划为 iOS Safari 组合输入与焦点恢复收集真机外部证据【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate本篇围绕 Plate 仓库中的 iOS Safari 外部证据计划 2026-04-12-ios-safari-broader-composition-focus-external-evidence-plan.md 展开当本地自动化测试栈Playwright、Appium/XCUITest、模拟器对富文本编辑器的 IME 组合输入composition行为“测不出可信结论”时如何诚实地界定本地证据边界、按优先级选择外部证据来源并设计三条可执行的验证 Lane含通过判据、每次运行必须产出的工件包Artifact Bundle与设备元数据规范。读完本篇你可以掌握一套“工具链能力分级 外部真机证据收集 账本闭环”的平台兼容性验证方法论可直接迁移到任何需要跨浏览器/跨设备证明 contenteditable 输入行为的编辑器项目中。一、背景这个计划要解决什么问题Plate 仓库正在推进 Slate v2 的“零回归”替换验证。其中“IME / 移动端 / 浏览器”平台一致性parity账本把每个行为行behavior row映射到具体的证明 Lane而iOS Safari 的组合输入与焦点恢复是本地自动化栈最后一块“无法诚实证明”的拼图。计划的原始目标是原文 Purpose 一节Close the remaining iOS Safari parity slice that the local automation stack still cannot prove honestly.关闭本地自动化栈仍无法诚实证明的剩余 iOS Safari 一致性切片。这里的关键词是honestly诚实地整个计划的基调不是“想办法把测试跑绿”而是区分“工具链已经证明的”“工具链证明不了的”和“必须靠外部真机证据补上的”三类结论禁止把“测试没测到”伪装成“行为已通过”。与之配套的权威账本是 2026-04-11-slate-v2-ime-mobile-browser-file-ledger.mdIME/移动/浏览器文件账本它维护了一张双轴行为/一致性表格其中“iOS Safari / WebKit composition / focus”行的状态被标为tooling-blocked / non-RC并把剩余工作明确指向本计划文件。二、本地证据天花板本地栈能证明什么、不能证明什么计划文档用“Current Local Ceiling当前本地天花板”一节把本地自动化栈的能力切分成两张清单。这是全文最有方法论价值的一部分任何平台兼容性的验证计划第一步都应先写清楚“我的工具能证明什么上限”。2.1 本地栈已经能诚实证明的部分桌面 WebKit 的焦点focus与零宽度zero-width选择行桌面 WebKit 的直接输入天花板direct-input ceiling浏览器级代理组合输入browser-level proxy compositionLane通过直连 Appium 获得的本地 Safari 表面的路由/搭建route/setup事实iOS 模拟器 Safari 上部分目标表面的直接绿色direct greenLane。2.2 本地栈仍然无法干净证明的部分在占位符类placeholder-like行上的更广 Safari contenteditable 输入所依赖的那些 iOS/Safari 怪输入weird-input用例上的更广组合/焦点行为。2.3 两个已知的本地阻塞点计划列出了两个具体的本地阻塞Known local blockers它们解释了“为什么本地测不了”Appium/XCUITest 的value写入不是占位符 Lane 上可信的 contenteditable 输入证明——即通过 WebDriver 标准元素value路径往 Safari contenteditable 里“打字”无法真正驱动 DOM 输入事件链agent-browser的 iOS provider 在这些本地路由上仍然不可靠——页面经常只渲染出 Next.js 外壳编辑器节点根本没出现自然谈不上输入证明。第一条阻塞在 2026-04-12-appium-ios-safari-loads-local-slate-routes-but-xcuitest-value-does-not-drive-contenteditable.md 中有完整的失败细节值得展开因为它是理解整个外部证据计划动机的钥匙。2.4 为什么 XCUITestvalue写不进 Safari 的 contenteditable该 issue 文档记录的观测事实是直连 Appium XCUITest 访问 iOS 模拟器 Safari 时路由能打开、页面 HTML 能读到/examples/placeholder?debug1与/examples/placeholder-no-feff?debug1两条占位符路由都能加载并读取真实编辑器 HTML 与正文文本但标准 WebDriver 的element/value输入路径始终红反复出现input:undefined:[null]输入事件是空的blockTexts始终为空编辑器文本块没有收到任何字符slateSelection始终停在0.0:0|0.0:0Slate 模型层的选择完全没有移动。FEFF 占位符与 no-FEFF 占位符两条路由上现象完全一致。后续的补充探测也没有解锁更好的原始能力primitive对聚焦的 Safari 页面发 W3C Actions 键盘事件——无效果XCUITest 的mobile: keys//wda/keys——无效果切换到NATIVE_APP上下文后能看到真实原生上下文但没有出现XCUIElementTypeKeyboard或XCUIElementTypeKey节点键盘根本没被唤起通过mobile: calibrateWebToRealCoordinatesTranslation把 web 元素 rect 换算成原生坐标做 tap——依然唤不起 iOS 键盘。该文档由此沉淀出一条可复用规则Reusable rule直接支撑了外部证据计划的设计需要可信的路由/搭建事实时用直连 Appium iOS它是比agent-browseriOS 路径更好的 setup 传输层不要把 XCUITest 的element/value当作可信的 contenteditable 输入证明不要假设NATIVE_APP上下文存在就一定能 tap 出键盘先验证键盘节点树当 Appium setup 绿但 typing 红时把 Lane 记录为setup-green / behavior-red搭建绿/行为红——这种诚实分级正是本计划所有 Lane 的状态语言。2.5 另一层失败agent-browser iOS provider 的可靠性另一个相关 issue 是 2026-04-11-agent-browser-ios-simulator-is-good-enough-for-slate-local-open-plus-initial-snapshot-but-not-yet-post-input-proof.mdagent-browser的 iOS provider 打开本地路由后页面常常只暴露 Next 外壳占位符 IME 编辑器节点#placeholder-ime不出现。也就是说它连“编辑器渲染出来了”这一层都经常证不到更不用说输入后的行为。这解释了为什么计划把agent-browseriOS provider 排除在证据链之外。把两个 issue 合起来看本地栈的失败被清晰地拆成了两层、彼此独立的问题agent-browseriOS 的路由/渲染可靠性问题Appium/XCUITest 的 contenteditable 输入语义问题。两者不是同一个失败——这种“故障归因分层”是后面设计外部证据顺序的前提既然两条本地自动化通道各自卡在渲染或输入层那么“真实的 iOS 键盘打出真实的字符”这一层本地栈在原理上就测不到必须引入外部证据。三、证据获取顺序先真机、再设备农场、最后才换自动化底座计划给出的 Evidence Order证据获取顺序是一个严格降级的三级策略真实 iPhone Safari 的手工真机工件manual-device artifacts——最高优先级真机浏览器农场browser farm带录屏视频与 Safari 版本元数据——规模化收集替代的 iOS 自动化底座alternate automation substrate——只有当它能证明“真实 contenteditable 输入 键盘存在”时才考虑引入。第三条的约束值得注意更换自动化工具链比如换一套驱动或协议不被禁止但准入标准是它必须能证明真键盘驱动真输入否则就只是把同一个测不到的问题换个壳再测一次。这体现了一个原则证据的价值由“它能证明的物理事实”决定而不是由工具的新鲜程度决定。四、三条必测 Lane流程、通过判据计划定义了 Required Lanes必测 Lane三条。每条 Lane 都由“操作步骤 通过判据Pass rule”构成判据写的是编辑器模型层可观察的状态而不是像素或视觉断言——这保证了结果可机读、可复核。Lane 1占位符 / 空起点输入Placeholder / Empty-Start Typing操作流程打开/examples/placeholder?debug1在 Safari 中聚焦编辑器通过真实 iOS 键盘打字捕获最终文本、选择状态selection与事件追踪event trace。通过判据三条必须同时满足输入的文本提交commit进编辑器选择落在插入文本之后selection lands after the inserted text不存在“死输入路径”dead input path或只剩空事件的 tracenull-event-only trace——也就是事件链必须真实产生过事件而不是输入后毫无事件记录。注意?debug1参数IME 表面的调试叠层在该参数下会输出 Slate 选择、DOM 选择、占位符结构、事件流与 HTML 快照这正是“捕获最终文本、选择与事件 trace”这一步能落地的原因。Lane 2无 FEFF 的占位符输入No-FEFF Placeholder Typing操作流程打开/examples/placeholder-no-feff?debug1聚焦编辑器通过真实 iOS 键盘打字捕获最终文本、选择与事件 trace。通过判据输入的文本提交进 no-FEFF 路径提交后选择保持“健全”sane状态。为什么单独测“无 FEFF”路径FEFFUFEFF零宽 BOM是编辑器占位符实现中常见的承载字符占位符提示文本挂在不可见的 BOM 字符上输入时需要把这层“隐形锚点”处理掉。两条占位符路由对应两种实现形态在 iOS Safari 这种组合输入事件时序与标准有微妙差异的浏览器上两条路径的行为不能互相推定所以账本里它们也是两个独立的行为行FEFF 占位符 IME 行与 no-FEFF 占位符 IME 行在 Appium 上同为setup-green / behavior-red。Lane 3更广的焦点 / 选择恢复Broader Focus / Selection Recovery操作流程打开相关的焦点敏感路由focus-sensitive route;以与历史遗留关注点legacy concern一致的方式对 Safari 做失焦blur再重新聚焦refocus捕获最终选择状态与 DOM 状态。通过判据选择恢复到健全位置没有过期的隐藏选择范围stale hidden selection range残留。这条 Lane 对应的正是 Safari/WebKit 的一类经典遗留行为Safari 在失焦后可能在 editable 已经失去焦点的情况下残留选择范围组合输入事件时序也可能与标准不一致例如beforeinput(insertFromComposition)先于compositionend派发要求组合状态必须尽早清除。这些历史行为模式在账本文档的“Exact Legacy Compat Behaviors Still Unproved”一节的 Safari/WebKit 小节中有完整列举是 Lane 3 判定“选择健全与否”时的参照基线。五、工件规范每次运行必须产出的 Bundle计划对每次真机运行的产物Artifact Root 与 Required Bundle Per Run做了硬性规定。证据的“可复核性”来自工件而不是来自结论描述。5.1 工件根目录所有工件统一归档到ios-safari-composition-focus工件根目录在账本中记录为.omx/artifacts/ime-mobile-browser/ios-safari-composition-focus/该路径属于维护者本地工作区未随本仓库提交。5.2 一键捕获命令计划提供了一条 one-command capture 脚本同样是维护者本地工作区路径bash repo/.omx/artifacts/ime-mobile-browser/capture-bundle-assets.sh \ ios-sim \ ios-safari-composition-focus \ placeholder三个位置参数分别表示设备类别iOS 模拟器、工件集名称、本次针对的示例表面placeholder。5.3 每次运行必交的 7 项工件工件作用notes.md人工操作笔记做了什么、看到什么、异常点selection.txt捕获到的最终选择状态Slate 路径形式如0.0:0|0.0:0dom.txt编辑器 DOM/HTML 快照用于核对文本是否真实提交actions.md操作序列记录保证流程可复现screenshot-01.png第一张现场截图通常为输入前screenshot-02.png第二张现场截图通常为输入后video.mp4全程录屏保留键盘出现、预测文本、组合下划线等瞬时视觉证据从结构上可以看出这套工件的分工notes.md/actions.md记录“人做了什么”selection.txt/dom.txt记录“编辑器状态是什么”两张截图加一段视频记录“过程长什么样”。三类信息互为冗余校验——比如dom.txt显示文本已提交但selection.txt显示选择没有跟随插入点移动就说明 Lane 的通过判据没有全部满足。5.4 设备元数据每次运行必须记录设备型号device modeliOS 版本Safari 版本键盘类型与地区locale预测文本predictive text是否开启。最后两项容易被忽略但对组合输入尤其关键不同布局键盘的候选条行为不同预测文本开启与否会直接改变 iOS 键盘如何提交组合词候选词点选 vs 空格确认进而影响compositionupdate/compositionend的触发形态。不记录这些元数据一次“绿色运行”就无法在其他设备上被解释或复现。六、退出条件什么才算“关单”计划的 Exit 一节给出唯一的关闭条件This lane closes only when the remaining iOS Safari rows are backed by real device artifacts and the ledgers are updated from those artifacts.该 Lane 只有在剩余的 iOS Safari 行被真机工件背书、且账本基于这些工件更新后才算关闭。两个关键词backed by real device artifacts——结论必须由第五节的工件包支撑不能只有一句“我在手机上试过没问题”ledgers are updated from those artifacts——账本条目如 IME/移动/浏览器文件账本中“iOS Safari / WebKit composition / focus”行的 Actual outcome 列必须从工件反写更新形成“工件 → 账本”的单向事实流避免账本描述与实际证据脱钩。这与此前账本中 Android 行采用的同款纪律一致Android 键盘特性自动纠错 / 滑行输入 / 语音输入在本地 Appium Chrome 栈上只能证明键盘可见、无法暴露 Gboard 候选节点见 2026-04-12-appium-android-chrome-can-show-keyboard-state-without-exposing-gboard-candidates.md因此被明确记为tooling-blocked / external等待外部证据而非被强行标绿。七、这套计划可复用的方法论要点把计划与配套的 issue 文档、账本放在一起看可以提炼出对“平台兼容性验证”普遍适用的五条规则先写本地证据天花板再谈外部收集。计划开篇的 Current Local Ceiling 两张清单能证明 / 不能证明决定了后面一切证据动作的边界。跳过这一步的验证计划往往会在“工具链测不到”与“产品行为坏了”之间反复混淆。给 Lane 做诚实分级green / red / tooling-blocked / setup-green / behavior-red。“setup 绿但 behavior 红”这种中间状态必须被显式表达否则账本会高估覆盖度。通过判据写在模型层状态上而不是像素上。三条 Lane 的 pass rule 全部是可机读的状态断言文本已提交、选择位置、事件 trace 非空、无残留隐藏范围截图和视频作为补充证据而非判定依据。工件包 设备元数据让结论可复核。7 项工件 5 项元数据构成最小证据单元没有工件的“通过”不计入账本。故障归因分层避免把两个失败当成一个。agent-browser渲染可靠性与 XCUITest 输入语义是两层独立问题分开归因之后才可能得出“换真机”这个正确的证据决策而不是在错误的层面上反复调参。八、延伸阅读仓库内相关文档计划本体2026-04-12-ios-safari-broader-composition-focus-external-evidence-plan.md行为/一致性权威账本2026-04-11-slate-v2-ime-mobile-browser-file-ledger.mdXCUITestvalue无法驱动 contenteditable 的 issue 记录2026-04-12-appium-ios-safari-loads-local-slate-routes-but-xcuitest-value-does-not-drive-contenteditable.mdagent-browser iOS provider 可靠性边界2026-04-11-agent-browser-ios-simulator-is-good-enough-for-slate-local-open-plus-initial-snapshot-but-not-yet-post-input-proof.mdAndroid 侧对照键盘可见但候选不可达2026-04-12-appium-android-chrome-can-show-keyboard-state-without-exposing-gboard-candidates.md当前 rc 证明账本true-slate-rc-proof-ledger.md需要说明的适用前提/examples/placeholder?debug1、/examples/placeholder-no-feff?debug1等路由及capture-bundle-assets.sh、.omx/artifacts/...路径来自 Plate 维护者本地工作区的 Slate v2 测试站点与本地工件目录本仓库未包含对应源码本仓库 www 应用中的占位符注册示例如 placeholder-value.tsx、block-placeholder-kit.tsx可帮助理解占位符编辑器的一般形态。本文所有结论以仓库文档所记录的事实为准外部真机证据的最终结果以账本后续更新为准。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考