Slate v2 与 Yjs 协作编辑核心就绪性评审计划Core Readiness Ralplan深度解析【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate导读本文基于仓库中的 docs/plans/2026-05-13-slate-v2-yjs-core-readiness-ralplan.md 展开剖析 Slate v2 在正式发布前为一等公民slate-yjs协作包所做的核心就绪性评审为什么当前架构已经具备正确的协作基座、为何不能直接移植旧版slate-yjs的 monkey-patch 适配器形状、以及以测试先行为纪律的 P0 就绪契约队列与协作专用基准collab-readiness benchmark如何落地。读完本文你将掌握 Slate v2 面向 Yjs 的扩展点editor.extend、commit listener、editor.update、tx.operations.replay、tx.value.replace、协作提交元数据与标签约定、远程选择压力的验证方法以及一套可复用的先证明核心、再开包的工程决策框架。阅读提示本文所述计划撰写于 2026-05-13基于当时本仓库维护者本地 checkout文档中记作.tmp/slate-v2。该计划的最终结论是核心就绪性证明完成、可执行而包级package工作后续由更新的计划接棒见文末文档状态与后续演进。文中所有引用到的.tmp/slate-v2源码路径在本仓库中以 packages/slate、packages/slate-history 等形态存在Plate 层的 Yjs 插件现状则位于 packages/yjs。一、核心裁决现在不创建slate-yjs包该计划最关键的结论写在Verdict一节Do not createslate-yjsyet.暂不创建slate-yjs包。这是一个典型的先打地基、再盖楼的决策。理由分两层Slate v2 核心不需要为 Yjs 重写。当前架构已经走在正确方向上commits提交、metadata元数据、tags标签、operation replay操作重放、extension runtime state扩展运行时状态、commit listeners提交监听器、operation middleware操作中间件、local runtime ids本地运行时 id以及 bookmark rebasing书签重定位共同构成了正确的协作基座。硬切点是旧版适配器形状。未来的协作包绝不能移植旧slate-yjs的以下实现方式monkey-patch 掉editor.applymonkey-patch 掉editor.onChange直接修改editor.children隐式依赖Transforms.select恢复选择让 Yjs 存储泄漏进原始 Slate 值。一句话概括旧版适配器形状恰恰是 v2 要消灭的那类脏 hack移植它等于把旧版 Slate 的插件模型和通过副作用调试同步的噩梦重新带回 v2。包创建前必须完成的五件事编号就绪证明点目标1一等公民协作适配器可以完全通过editor.extend(...)、commit listeners、extension runtime state 与editor.update(...)写出证明新包可以干净挂载/卸载2高频远程更新不能破坏或困住本地折叠选择与书签覆盖 #5771 类风险3必须支持规范式远程对账canonical remote reconcile而不只是增量操作重放提供增量翻译不可靠时的逃生舱4远程导入必须跳过历史、焦点、DOM 选择导出与滚动定义副作用策略5暂停/断开/重连语义不依赖编辑器对象变异定义生命周期契约二、意图、范围与决策边界Intent 与 OutcomeIntent让 Slate v2 核心在发布前 100% 就绪以支撑一个干净的、一等公民的slate-yjs包。Outcome产出一份被接受的核心就绪性检查清单 执行队列队列全绿之后才开始创建包。In scope原始 Slate v2 的操作、事务、提交、历史、选择、书签、扩展与元数据契约来自../slate-yjs、../lexical/packages/lexical-yjs、../y-prosemirror与../yjs的适配器架构压力与协作相关的 Slate issue 的账本issue-ledger核算启动slate-yjs前必须存在的测试与基准。Non-goals明确不做本计划内不产出新的slate-yjs包不做 provider、awareness、光标 UI、协作评论等产品级 API不在原始 Slate 内做 Plate 兼容 API不承诺兼容旧slate-yjs公开 API不允许 Yjs 对象出现在原始 Slate 文档值中除非某个 issue 的确切主张发生变化否则不做线上 issue 的重新挖掘。三方决策边界层拥有者原始 Slate值、操作、事务、提交、元数据、锚点/书签、历史行为、扩展槽位未来slate-yjs包Yjs schema、provider 集成、awareness、相对位置转换、规范式 Y 对账、适配器专属映射Plate协作评论、建议、光标、权限与 UI 策略产品级、有观点这个原始核心保持无倾向unopinionated的边界是整个计划的灵魂Plate 或其他适配器即使使用非 Yjs 的协作层也不需要为 Yjs 买单。三、Slate v2 现有核心基座哪些已好、哪些不足计划作者审读了以下核心文件对应本仓库中的 packages/slate/src/interfaces/editor、packages/slate/src/create-editor.ts 等packages/slate/src/interfaces/editor.tspackages/slate/src/core/public-state.tspackages/slate/src/core/editor-extension.tspackages/slate/src/core/extension-registry.tspackages/slate-history/src/with-history.tspackages/slate/test/collab-history-runtime-contract.ts已经做对的What is already goodBaseEditor暴露read、subscribe、update、extend四个入口事务写入统一走editor.update(...)tx.operations.replay(...)可以重放已知操作类型、拒绝未知操作形状commit listeners 在快照订阅者之前收到一份冻结的提交真相frozen commit truth提交元数据包含collab、history、origin、selection字段规范标签canonical tags包括collaboration、skip-collab、skip-dom-selection、skip-scroll-into-view、skip-selection-focus历史层已能通过元数据跳过远程协作导入三选一即可history.mode skip、collab.saveToHistory false、collab.origin remote现有契约测试已证明三端three-peer确定性重放文本、marks、删除、移动、replace_children、远程历史跳过、本地 undo/redo 重定位、书签重定位、运行时 id 保持本地性。尚未充分证明的What is not proven enough高 QPS 远程插入打在本地折叠选择上即 #5771 类场景覆盖 split、merge、move、remove、range delete 的穷尽式书签/相对位置行为真实适配器扩展的回环抑制loop suppression而非手工编写的重放暂停/切换/重连的适配器目标语义增量 Y 事件翻译不安全时的规范式 Y 到 Slate 对账provider/awareness 与核心历史、选择行为的隔离。四、生态综合向三个成熟项目偷师什么、拒绝什么计划从三个已存在的协作实现中提炼机制再转化为 Slate 专属机制而不是复制粘贴适配器形状。4.1 来自../slate-yjs偷师Steal拒绝Reject导出变更的本地来源分组local-origin groupingmonkey-patcheditor.apply用于光标/选择持久化的相对位置monkey-patcheditor.onChangeY UndoManager 的选择恢复概念connect 时直接赋值editor.childrenawareness 状态属于适配器自有的关注点把 normalize/connect 副作用当同步语义依赖旧版可变编辑器对象形状的适配器代码对应的 Slate v2 目标形态本地导出从 commit listener 读取EditorCommit.operations、元数据、标签、脏运行时 id仅在需要时读取快照远程导入editor.update(tx tx.operations.replay(...), { metadata, tag })规范对账当 Y 事件增量不完整或歧义时走tx.value.replace(...)。4.2 来自../lexical/packages/lexical-yjs偷师拒绝用显式协作标签抑制回环把 Lexical 的 node-key/node-class 耦合当作原始 Slate 模型需求脏元素/叶子样式作用域要求原始 Slate 认识 Yjs 类的包架构远程同步打上跳过滚动/焦点的标签适配器自有映射层而非让原始编辑器懂 Y序列化状态的属性/默认值/排除策略Slate v2 对应物提交脏度commit dirtiness等价于脏节点集适配器扩展状态可以持有 Y 映射缓存远程更新必须携带collaboration、skip-scroll-into-view、skip-selection-focus标签。4.3 来自../y-prosemirror偷师拒绝规范渲染/差异/对账回退不只增量事件 delta把 ProseMirror 事务/插件机制当作原始 Slate API 目标相对位置书签映射把全文档 diff 当作默认本地导出路径插件顺序/来源纪律暂停/切换同步目标语义远程变更排除出本地 undo 历史awareness 身份基于 awareness doc 的 client id而非假设的编辑器 idSlate v2 对应物适配器可维护一份规范化的 Y 渲染 Slate 快照仅在增量导入不可信时对账核心测试必须证明远程规范替换能保持历史与选择策略。五、架构决策三种被否决的方案采纳方案保持原始 Slate 核心无倾向先加就绪契约再开包否决方案 1原样移植旧版slate-yjs理由它依赖的正是 v2 正在移除的可变/编辑器对象钩子会把旧版 Slate 插件模型走私回 v2并迫使未来代码通过副作用调试同步。否决方案 2把 Yjs schema、awareness 或光标策略搬进原始 Slate理由会让原始 Slate 变得有观点让 Plate 和其他使用非 Yjs 协作层的适配器为 Yjs 买单。否决方案 3现在就给move_node增加 moved-node payloads理由现有证明显示远程move_node重放与运行时 id 重定位已经可用在适配器证明自己无法干净重建状态之前给操作形状加 payload 只是为一个传输风格膨胀所有移动操作。六、核心就绪队列P0 / P1逐项拆解P0.1 适配器扩展契约Adapter extension contract目标新增一个聚焦的核心测试内嵌一个假协作扩展fake collaboration extension。验收标准扩展通过editor.extend(...)注册扩展使用运行时状态、commit listener且零编辑器 monkey-patch本地提交只导出一次远程导入提交不会再次导出skip-collab抑制导出清理cleanup能分离监听器与运行时状态。这一项直接证明未来的slate-yjs包可以被干净地挂载与卸载。P0.2 远程选择压力证明Remote selection stress proof目标在包工作开始前补上 #5771 类测试——这是当前要么现在做、要么永远不做的最大风险。验收标准远程插入高频命中同一文本节点时本地折叠选择保持有效远程插入后本地键入落在预期变换后的位置远程操作携带 collaboration/history/selection 元数据不出现选择锚点异常、陈旧路径异常或无效点覆盖同块前缀插入、同偏移竞争、后缀插入、split、merge、remove 六类场景。P0.3 书签与相对位置基座矩阵Bookmark and relative-position substrate matrix目标仿照y-prosemirror的位置测试新增核心矩阵。验收标准代表性文档中的每一个有效 Slate 点都能经历本地书签捕获 → 远程操作重放 → 解析覆盖段落、嵌套块、inline/文本边界、void 相邻点、split、merge、move、remove、replace_children当锚点目标被删除时显式置空null。未来 Yjs 适配器可以自持真正的Y.RelativePosition但核心必须先证明 Slate 侧的锚点基座是稳定的。P0.4 规范式远程对账Canonical remote reconcile目标证明远程同步可以在不污染本地历史的前提下替换规范快照。验收标准editor.update(tx tx.value.replace(...), remoteCollabOptions)只产生一次提交该提交带collaboration标签本地 undo 栈不被污染选择/焦点/滚动策略被保留替换后书签/运行时 id 行为确定。这是 Y 事件路径无法安全翻译时的逃生舱。P1.5 暂停、断开、重连Pause, disconnect, reconnect验收标准暂停的适配器不接收本地导出重连可以导入规范远程状态断开清理防止后续监听器调用不直接改动editor.children、editor.apply、editor.onChange。P1.6 远程更新副作用策略Remote update side-effect policy仅在核心测试全绿后再做 React/浏览器面证明。验收标准远程导入携带跳过 scroll-into-view 与 selection focus 的标签请求时保留当前本地选择纯远程同步不能从活动编辑器/输入偷走焦点。该项阻断的是 provider/光标 UI 工作不阻断原始核心包就绪。P1.7 性能与内存预算Performance and memory budget在包工作前新增一条collab-readiness 基准不散落多个单用途基准文件。CohortBlocksRemote opsBookmarks用途normal1005025常见小编辑器 协作突发large1,000100100带活跃锚点的真实应用文档stress10,000250250开包前的大文档导入/重放压力pathological11,000 次同节点插入50#5771 式热文本节点压力测量项commit/export 时间、远程导入时间、书签更新时间、操作重放计数、connect/disconnect 循环后的堆增长。预算红线即使尚未强制数值阈值以下情况也直接阻断建包normal/large cohort 中远程批量重放持续慢于分离重放同一文档形状下 p95 延迟随操作数增长快于近似线性规范替换留下本地 undo 条目书签解析把幸存锚点变成陈旧路径而不是重定位范围或nullconnect/disconnect 堆增量在重复循环中单调增长假适配器在 unextend 后仍收到提交。七、五个契约测试的源码级设计计划明确现有测试已经覆盖足够多的通用扩展机制P0 执行不应浪费时间重测并给出已覆盖清单extension-methods-contract.ts注册输出、运行时状态、清理信号、peer 依赖、冲突、对旧版methods与公开commands扩展形状的硬拒绝extension-namespaces-contract.ts扩展 state/tx 组不变异编辑器对象即可安装、可干净 unextendtransaction-contract.ts操作中间件能看到事务应用与tx.operations.replay清理后扩展 commit listener 不再收提交commit-metadata-contract.ts协作标签、origin 元数据、历史/选择元数据、冻结元数据、分组更新、全文档替换脏度write-boundary-contract.ts无直接原始写入器、无公开editor.apply、导入操作只能经tx.operations.replay重放collab-history-runtime-contract.ts确定性 peer 重放、远程历史跳过、undo/redo 重定位、书签重定位、运行时 id 本地性、replace_children导入。因此执行队列只需新增四个聚焦测试外加一个可选的 React/浏览器跟进。如果某个测试因公开表面不足而失败该失败本身就是 API 变更提案——这是全文反复强调的失败策略。Test 1适配器回环抑制Adapter loop suppression目标文件packages/slate/test/collab-adapter-extension-contract.ts仅用公开 APIcreateEditor、defineEditorExtension、editor.extend、editor.update、tx.operations.replay、Editor.getLastCommit、Editor.getSnapshot。假适配器形状扩展本地运行时状态保存connected、paused、exports: Operation[][]、remoteImports: number、originClientId: stringcommit listener 仅在以下条件全部为真时导出本地提交已连接、未暂停、提交不带skip-collab标签、元数据不是collab.origin remote、提交标签不含collaboration。假远程导入调用editor.update(tx tx.operations.replay(remoteOps), remoteOptions)。必备断言本地文本编辑恰好导出一次远程导入改变文档但导出零个新本地批次显式skip-collab本地更新导出零批次暂停时本地更新导出零批次重连恢复本地导出unextend 后不再有导出/监听器调用任何断言都不依赖私有运行时内部。这就是旧版slate-yjs打补丁editor.apply/editor.onChange的干净 v2 替代品。Test 2高 QPS 远程选择压力目标文件可扩展collab-history-runtime-contract.ts或新建collab-selection-stress-contract.ts场景多了就单开文件。五个场景同块远程前缀插入本地选择在one末尾应用 50 次 offset0的远程insert_text本地键入!断言!落在原本地光标内容之后而非陈旧偏移3同偏移竞争本地选择在 offset1多次远程在 offset1插入断言选择亲和力确定、本地键入稳定远程后缀插入本地选择之后的远程编辑不应移动本地选择本地选择周围的远程 split/merge在本地点前后 split 文本节点再 merge 回来断言本地键入仍落在解析后的点包含本地选择的远程 remove远程删掉选中节点断言选择按当前核心策略置空或解析但绝不抛异常、绝不指向缺失路径。必备元数据{ metadata: { collab: { origin: remote, saveToHistory: false }, history: { mode: skip }, selection: { dom: preserve, focus: false, scroll: false }, }, tag: [collaboration, remote-import], }必备断言无异常Editor.getSnapshot(editor).selection有效或为null本地后续键入成功历史只有本地 undo 条目最后一个远程提交携带协作元数据。Test 3相对位置基座的书签矩阵目标文件packages/slate/test/collab-bookmark-position-contract.ts文档形状段落文本、嵌套块/list 类元素、安全表达时的 inline 类元素、有既有 fixture 时的 void 相邻点、多块范围。矩阵行文本插入前的点、文本插入后的点、被删除文本节点内部的点、跨 split 节点的范围、跨 merge 节点的范围、被移动块内部的范围、跨replace_children的范围。必备断言远程重放后书签解析到预期范围被删目标解析为null而非陈旧路径目标幸存时 move 保留运行时 id 支撑的路径每一行都调用unref()清理。Test 4规范式远程对账目标文件packages/slate/test/collab-canonical-reconcile-contract.ts核心操作editor.update((tx) { tx.value.replace({ children: remoteCanonicalChildren, selection: currentSelectionOrNull, marks: null, }); }, remoteOptions);必备断言发布一次提交提交类为replace提交带collaboration标签与远程协作元数据withHistoryundo 栈不被污染选择策略显式规范状态使其失效时保留或置空且元数据不含 DOM/focus/scroll 副作用旧节点幸存处运行时 id 确定性重播种既有书签干净重定位或置空。Test 5远程副作用策略P1P0 之后目标若slate-react运行时已消费skip-scroll-into-view/skip-selection-focus则写一个slate-react契约测试否则先在浏览器/React 执行队列加计划注记。必备断言远程导入不偷焦点远程导入不强制滚动本地后续键入仍正常。八、API 硬化裁定保持现状不提前加宽结论P0 测试之前不需要任何公开 API 硬切。保持Keepeditor.extend(...)、defineEditorExtension(...)、扩展运行时状态、commit listeners、操作中间件、editor.update(...)、tx.operations.replay(...)、tx.value.replace(...)、类型化更新元数据与标签。不添加Do not add公开editor.apply、公开editor.onChange、编辑器对象上的适配器专属协作方法、原始slate中的 Yjs schema 或Y.Doc句柄、适配器证明其必要之前的move_nodemoved-node payloads。值得盯着的潜在 API 缺口操作中间件目前接收 operation 和 editor不直接接收 update 元数据。计划判定这可以接受——因为导出回环控制属于 commit listener在那里元数据与标签都可用。除非 P0 适配器测试证明它无法表达真实用例否则不改中间件。Steelman 决策表节选决策最强公平反对意见可行替代为何当前决策胜出所需证明不添加公开editor.apply协作适配器需要拦截每个 opcommit listener 可能太迟恢复editor.apply加适配器专属 op 拦截器用操作中间件公开editor.apply正是 v2 切掉的遗留逃生舱中间件已路由tx.operations.replaycommit listener 能看到类型化元数据与标签collab-adapter-extension-contract.ts证明无editor.apply也能实现本地导出与远程导入回环抑制不添加公开editor.onChange适配器作者熟悉旧 flush 模型恢复onChange加onCommit保留扩展 commit listener扩展 commit listener 已是onCommit形状带清理、排序、冻结提交数据与可选快照第二个公开回调面会分裂真相适配器测试证明每本地提交恰好导出一次、清理后停止导出不添加编辑器对象上的适配器专属方法一等包可能想要editor.connectYjs()编辑器对象方法扩展 editor 组独立适配器控制器原始 Slate 不应长出 Yjs 名词需要时由包暴露控制器或扩展组P0 适配器生命周期测试用扩展运行时状态与清理完成暂不把 update 元数据传入操作中间件逐操作中间件无法得知当前 op 是否来自远程导入现在就给中间件上下文加元数据用 commit listener 做导出门控加 tx 作用域元数据 getter导出门控应在 commit 级因为 Yjs 批处理与历史决策是 commit 级的在失败测试出现前加宽中间件是在为投机拓宽热路径P0 测试证明远程导入经提交元数据不再导出不给核心加原始Y.Doc/provider/awareness 句柄一等包若核心懂 Yjs 生命周期会更干净核心 Yjs 句柄扩展能力包内控制器核心必须保持协作后端无关slate-yjs通过扩展选项、运行时状态、清理信号与包导出自持 Yjs 生命周期适配器生命周期测试证明无核心 Yjs 名词也能 connect/pause/reconnect/cleanup暂不加move_nodemoved-node payloadsOT/Yjs 传输常受益于移动节点 payload#3741 直接提出加 payload规范对账回退适配器从 Y 状态重建v2 已证明远程move_node重放与运行时 id 重定位一个传输理论的 payload 会在适配器证明需求前膨胀每个 move opP0 规范对账 书签矩阵若适配器无法重建 move再提出聚焦的操作形状提案不把光标/awareness 做成原始 Slate API无光标的协作显得不完整原始光标存储slate-react 包 hookPlate/产品光标 UI光标渲染是 UI 策略核心只提供稳定锚点/书签与副作用元数据P0 书签矩阵 P1 远程副作用证明本次评审接受的修订Test 1 必须断言假适配器的任何人体工学ergonomics都通过适配器自有的控制器或扩展组暴露而非新的原始编辑器方法Test 4 必须断言规范远程对账能通过显式快照输入有意识地保留或置空模型选择不存在隐藏的选择魔法P0 失败策略显式化只有在公开 API 测试失败、证明当前表面无法表达真实适配器需求时才新增公开 API。被丢弃的选项开包前就给原始 Slate 加collaborationtx/state 组预防性地给操作中间件加元数据给原始 Slate 加 Yjs 专属能力。九、Issue-Ledger 记账最强的诚实主张是已排队就绪工作计划坚持仅凭规划阶段不得提升任何 issue 主张只有 Ralph 执行落地并验证 P0 协作选择证明后#5771才能从Related提升到Improves没有真实适配器/浏览器复现不允许任何Fixes主张。Issue当前账本状态本计划决策#5771Related/cluster-syncedP0 证明落地后提升为Improves精确关闭仍等待 provider/浏览器证明#5533Related保持。v2 操作重放是协作基座不是一等公民 OT 或非 Yjs 协作协议#3741Related保持。适配器证明当前重放/规范对账不足前不加move_node.nodepayloads#4477Improves保持。注解/书签基座有帮助但协作评论仍是产品/Plate/包策略#3715not-claimed保持。文档/示例压力属于后期slate-yjs包/文档通道#3482cluster-synced保持。void children/协作压力由核心模型/选择架构覆盖仅当 P0 书签矩阵暴露 void 相邻缺口时才提升计划同时划定了更新边界P0 落地后应更新docs/slate-v2/ledgers/issue-coverage-matrix.md、docs/slate-v2/ledgers/fork-issue-dossier.md、docs/slate-v2/references/pr-description.md、docs/slate-issues/gitcrawl-v2-sync-ledger.md不得触碰docs/slate-issues/gitcrawl-live-open-ledger.md它是生成的实时输入。十、维护者异议账本Maintainer objection ledger异议回答裁定为什么不直接移植 slate-yjs因为它依赖 v2 有意移除的可变编辑器钩子移植该形状会重新引入遗留耦合reject为什么 #3741 不加move_node.nodepayloadv2 已有证据覆盖远程 move 重放与运行时 id 重定位payload 扩张需要适配器证明先行keep current op为什么不把 Yjs 放进原始 Slate原始 Slate 应保持无倾向Yjs 属于包扩展reject包还不存在这是不是过度建设不是。P0 测试是包能写干净而非 monkey-patch 包装的最低证明keep光标 UI 能等吗能。核心就绪需要稳定锚点与副作用策略光标 UI 属于 React/Plate/包工作defer UI十一、执行结果Ralph 执行账本与最终验证计划文档同时是执行账本记录了 2026-05-13 当天的完整落地过程全部通过P0 执行明细任务测试文件结果P0 适配器扩展契约collab-adapter-extension-contract.ts1 pass, 0 failP0 远程选择压力collab-selection-stress-contract.ts5 pass, 0 failP0 书签位置矩阵collab-bookmark-position-contract.ts6 pass, 0 failP0 规范远程对账collab-canonical-reconcile-contract.ts2 pass, 0 failP1 远程副作用策略slate-reactapp-owned-customization.test.tsx、selection-side-effect-policy-contract.test.ts2 files, 8 tests passedCollab-readiness 基准collab-readiness.mjsbench:core:collab-readiness:local通过并写出 JSON 工件几个值得注意的执行结论选择压力测试的结果比计划回退方案更强当前核心在被选中节点被远程删除时策略是重定位到前一个幸存的文本结尾而非直接置空规范对账发布一个带协作元数据且跳过历史的replace提交显式模型选择可被快照输入保留或清除同位置运行时 id 与书签在规范替换后幸存P1 副作用策略使远程协作选择元数据抑制滚动与焦点副作用模型选择同步仍运行应用自有的scrollSelectionIntoView在正常本地选择更新时仍被调用基准覆盖normal / large / stress / pathological 四个 cohort七条 lane本地导出、远程批量重放、远程分离重放、书签重定位、规范替换、历史跳过、connect/disconnect 堆增量工件含 calibration-only 阈值策略且在计时前先验证批量与分离远程重放收敛到同一快照。最终验证汇总bun test ./packages/slate/test/extension-methods-contract.ts \ ./packages/slate/test/extension-namespaces-contract.ts \ ./packages/slate/test/transaction-contract.ts \ ./packages/slate/test/commit-metadata-contract.ts \ ./packages/slate/test/write-boundary-contract.ts \ ./packages/slate/test/collab-history-runtime-contract.ts \ ./packages/slate/test/collab-adapter-extension-contract.ts \ ./packages/slate/test/collab-selection-stress-contract.ts \ ./packages/slate/test/collab-bookmark-position-contract.ts \ ./packages/slate/test/collab-canonical-reconcile-contract.ts # 71 pass, 0 failbun run bench:core:collab-readiness:local # passed; wrote tmp/slate-collab-readiness-benchmark.json bun run bench:core:transaction:local # passed; updateReplayMeanMs 0.08, separateUpdateMeanMs 0.22上下文基准transaction、refs-projection、query-ref-observation、history-retained-memory全部通过lint检查 1616 个文件与slate、slate-react的 typecheck 均为 0 退出码。基准预算政策thresholdPolicy: { mode: calibration-only, releaseGate: false, repeatRunsRequiredBeforeEnforcement: 3, }即初始阶段仅校准不设发布门禁需三次干净的基线运行后才启用强制阈值。文档明确写道基准的目标不是比 Yjs 快而是 Slate 侧开销有界。计划文档自评分数轨迹计划在正文中记录了多轮评审打分的收敛过程性能与基准通过后 0.92 → P0 证明设计通过后 0.84 → API steelman 通过后 0.89 → issue-ledger 预同步后 0.88 → 最终就绪性评分 0.94。打分的目的不是炫耀而是把规划是否充分量化为可追踪的评审产物意图/边界、基座证据、生态转换、P0/P1 行、API 裁定、账本保守性、性能工件七项全部显式化后才允许关闭规划。十二、本仓库中的对照实现计划基于当时的.tmp/slate-v2checkout其结论在当前仓库中可以找到对应落点核心扩展与编辑器工厂packages/slate/src/create-editor.ts 展示了createEditor如何把apply、onChange等绑定为 first-class 方法并把api、tf/transforms、历史入口history、undo、redo、writeHistory装配到编辑器上——这印证了计划中写操作应走editor.update/ 事务路径、公开editor.apply属于遗留逃生舱的判断背景编辑器接口与类型packages/slate/src/interfaces/editor 与 packages/slate/src/interfaces/operation.ts 定义了操作形状与编辑器 API 面历史层packages/slate/src/slate-history/with-history.ts 是history.mode skip、collab.saveToHistory false等远程跳过机制的实现载体Plate 层 Yjs 插件现状packages/yjs/README.md 说明当前platejs/yjs通过YjsPlugin把 Plate 编辑器绑定到共享 Yjs 文档内置 IndexedDB、Hocuspocus、WebRTC provider 包装器并接受实现UnifiedProvider接口的自定义 provider——这正对应计划中Yjs 生命周期属于包/适配器层、原始核心保持无倾向的边界三端协作测试脚手架packages/yjs/src/lib/tests/collaboration/harness.ts 中的CollaborationConnector以内存队列模拟 peer 间的 update 传递与 FIFO/逆序冲刷并复用slate-yjs/core的slateNodesToInsertDelta/yTextToSlateElement——是理解本地导出 → 传输 → 远程导入闭环的直观参考。需要强调本仓库当前并没有packages/slate-yjs包计划的目标是先证明核心就绪、再创建包这一顺序至今仍是文档的主线。十三、文档状态与后续演进计划开头附有三条同步注记sync notes如实记录了该文档在项目推进中的定位变化2026-05-18包级时序上已被 docs/plans/2026-05-18-slate-yjs-package-readiness-ralplan.md 取代核心基座注意事项仍有用但包工作必须使用实时setup(...)/onCommit(...)API而非较旧的register/commitListeners示例2026-05-24不要再把本文当包计划最新包目标仍是 2026-05-18 计划核心就绪测试与collab-readiness基准当时已通过但packages/slate-yjs源码、完整仿真示例、包测试与 Playwright 选择证明当时尚不存在2026-05-28实时slate-v2已拥有packages/slate-yjs源码、测试、示例与 Playwright 行当前工作位于docs/plans/2026-05-28-slate-yjs-current-architecture-operation-matrix.md。这份文档的真正价值不在包做完了没有而在于它把要不要为 Yjs 建包这一个二值问题转化为一组可执行、可验证、可争议的工程事实旧适配器形状monkey-patch、直接改 children、隐式选择恢复、Yjs 泄漏进原始值被逐条列为硬性拒绝项无 monkey-patch 的一等适配器被翻译成一份公开 API 清单 一份假适配器形状 一组无私有内部依赖的断言远程选择会不会坏被翻译成五个高 QPS 场景与五条元数据/断言契约增量翻译不可靠怎么办被翻译成tx.value.replace规范对账契约性能会不会失控被翻译成四个 cohort、七条 lane、一条校准政策与六条红线issue 主张会不会被夸大被翻译成严格的账本提升规则没有证明就没有Fixes最强诚实主张只是就绪工作已排队。对于任何正在设计编辑器核心 协作适配器分层架构的团队这套先契约、后实现、再开包的路线图都是可直接借鉴的范本把最难的风险远程选择、历史污染、回环、副作用、内存提前压到核心层的失败测试里用公开 API 的失败测试作为唯一的 API 变更提案入口从而让未来的协作包从诞生第一天起就是干净扩展而不是补丁集合。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考