Slate v2 Exact Ledgers:为编辑器框架迁移建立逐文件精确映射台账的实战方案
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
导读
本文基于 Slate v2 Exact Ledgers Plan 这一计划文档,结合其在仓库中实际落地的台账产物,完整讲解一套面向大型编辑器框架迁移的"精确台账(exact ledger)"方法论:如何按作用域为每一个历史遗留文件建立 1:1 映射记录、如何用显式状态机标注每个文件的迁移去向、以及如何让主发布台账从"声称详尽"退回到"指向证据、不再过度宣称"。读完本文,你将掌握一套可直接复用到自己项目的、可审计、可机器检索的迁移追踪体系。
一、背景:为什么需要一个"精确台账"而不是"人工控制台账"
在 Slate v2 的迁移工程中,仓库长期维护着一份"人工控制台账(human control ledger)",用于追踪旧版 Slate(legacy)测试与源码向新架构迁移的进度。这份台账的致命问题在于:它对外表现得像是穷尽的(exhaustive),实际上却并非如此——人工维护的条目覆盖不到每一个历史文件,而读者(包括维护者本人和自动化 Agent)无从判断台账之外是否还有遗漏。
Exact Ledgers Plan 的目标非常直白:
Add 1:1 exact legacy-file ledgers per scope so the repo stops pretending the human control ledger is exhaustive.
即:按作用域(scope)为每一个历史遗留文件建立 1:1 的精确台账,让仓库停止假装人工控制台账是穷尽的。这是一次"诚实化"工程治理改造——用机械生成的、逐行的账本取代人工印象,让"哪些文件已被映射、哪些被显式跳过、哪些仍待裁决"成为可验证的事实,而不是维护者的记忆。
该计划归属于整个 Slate v2 迁移程序(fresh-branch 迁移)的文档体系,程序总览见 Slate v2 Overview:tranche 1(Bun 工具链)与 tranche 2(React 19.2.5 / Next 16.2.4 / TypeScript 6.0.3 基线)已经完成,tranche 3 正在对packages/slate核心进行面向原生事务引擎的重设计。精确台账正是这个"重设计 + 兼容性瘦身"过程中的关键治理工具:只有先精确知道每个旧文件去了哪里,才敢对兼容性包袱做硬切割(hard cut)。
二、范围界定:四个需要精确台账的作用域
计划为台账划定了四个明确的扫描范围,全部集中在测试与示例领域:
| 作用域 | 含义 |
|---|---|
packages/slate/test/** | Slate 核心包的遗留测试文件 |
packages/slate-react/test/** | React 绑定包的遗留测试文件 |
packages/slate-history/test/** | 历史记录(undo/redo)包的遗留测试文件 |
playwright/integration/examples/** | Playwright 端到端示例测试 |
范围选择很有讲究:这四个目录恰好覆盖了"核心逻辑测试、React 渲染测试、历史状态测试、浏览器端到端测试"四个层次,是迁移中最容易"悄悄删文件"或"悄悄漏文件"的区域。精确台账的第一个作用就是让"删除"和"遗漏"变得可见。
从当前仓库实际落地的台账来看,这四个作用域对应的文件体量差异巨大(数据来自各台账的统计行):
- 核心包 legacy-slate-test-files.md 记录了1069个遗留文件,是绝对大头;
- React 包 legacy-slate-react-test-files.md 记录了8个文件;
- 历史包 legacy-slate-history-test-files.md 记录了20个文件;
- Playwright 示例 legacy-playwright-example-tests.md 记录了23个文件。
这种体量差异本身就说明问题:1069 个核心测试文件如果不靠机械生成的精确台账,仅凭人工记忆根本无法保证穷尽性。
三、台账规则:四条铁律保证账本可信
计划定义了四条必须遵守的台账规则,这是整个方法论的灵魂:
- one exact row per legacy file——每个遗留文件且仅占一行,不允许一个条目合并描述多个文件;
- exact relative path keys——以精确的相对路径作为账本主键,路径即身份,杜绝模糊描述;
- explicit mapping status——每个文件必须有显式的映射状态,状态分为三类:
mapped(已映射)、explicit skip(显式跳过)、needs-triage(待裁决); - no silent aggregation——禁止静默聚合,任何"这批文件都……"式的笼统归类都不被允许。
这四条规则本质上是在对抗台账腐化的三种典型路径:漏行(文件未被记录)、模糊(路径或状态不精确,无法裁决)、假穷尽(用一个汇总数字假装覆盖了所有情况)。
值得注意的细节是:计划中定义的状态是mapped / explicit skip / needs-triage三态,而在实际落地时,台账在mapped之下进一步细化了语义。例如 legacy-slate-test-files.md 中出现了:
mapped-mirrored(映射-镜像:旧行为在新证明文件中被直接复现,共979条);mapped-recovered(映射-恢复:旧行为通过新的契约测试间接恢复,共49条);mapped-mixed(映射-混合:旧行为被拆分到多个新证明文件或部分退役,共5条);explicit-skip(显式跳过,共36条)。
而 Playwright 示例台账 legacy-playwright-example-tests.md 则使用了same-path-current(同路径在当前分支继续存在,共 21 条)这一状态,表示旧测试文件在相同相对路径上被直接沿用。这印证了计划的一个设计意图:状态词汇表允许在落地时扩展,但"显式"这一约束不可妥协——每个文件必须有一个确定的状态归属。
四、账本格式与真实示例:TSV 三列结构
从实际落地产物看,每个精确台账的核心是一张 TSV(Tab 分隔)表,固定为三列:
legacy_file mapping_status current_owner notelegacy_file:遗留文件的精确相对路径(账本主键);mapping_status:上文的映射状态;current_owner:该文件迁移去向的证明文件(新架构中的 owner,可能为空);note:一行说明,解释为什么是这个状态。
下面从 legacy-slate-history-test-files.md 摘录三行有代表性的真实记录,展示三种典型裁决:
legacy_file mapping_status current_owner note packages/slate-history/test/history-editor-flags.js mapped-mirrored packages/slate-history/test/history-contract.ts direct legacy history parity is proved in history-contract packages/slate-history/test/index.js explicit-skip none fixture harness entrypoint is retired packages/slate-history/test/undo/insert_text/non-contiguous.tsx explicit-skip none timing-based auto-merge heuristics are not the live contract这三行分别代表了台账中最有价值的三种信息:
- 迁移去向可追溯:
history-editor-flags.js的行为被镜像到新契约测试history-contract.ts中,读者可以顺着current_owner直接找到它的"新家"; - 删除有明确理由:
index.js(旧的 fixture 测试入口)被显式跳过,理由是"旧夹具入口已退役"——注意状态是explicit-skip而非直接消失,删除因此可审计; - 行为放弃是决策而非疏漏:
non-contiguous.tsx被跳过的原因是"基于时序的自动合并启发式不再是活契约"——这是产品决策层面的主动放弃,被显式记录,避免后人误以为漏测。
再看 legacy-playwright-example-tests.md 中的一个same-path-current示例:
legacy_file mapping_status current_owner note playwright/integration/examples/richtext.test.ts same-path-current playwright/integration/examples/richtext.test.ts same relative test path exists in slate-v2这里current_owner与legacy_file路径完全相同,表示该测试在迁移后的仓库中以相同相对路径继续存活——这是最轻量的一种迁移结果。而该台账中唯一一条mapped-recovered记录(select.test.ts)则展示了另一种情况:旧测试的"三击选中段落"意图被恢复到了richtext.test.ts这一现行接缝上,路径虽然变了,但测试意图被显式登记,不会在迁移中无声丢失。
五、精确台账的统计汇总:一屏即可审计迁移健康度
每个台账开头都有一组统计行,相当于账本的"审计摘要"。例如核心包台账 legacy-slate-test-files.md 顶部:
- Total legacy files:
1069 - mapped-mixed:
5 - mapped-mirrored:
979 - mapped-recovered:
49 - explicit-skip:
36
这组数字本身就能回答迁移负责人最关心的三个问题:
- 覆盖率:
(979 + 49 + 5) / 1069 ≈ 96.6%的遗留文件已有明确去向; - 风险面:36 个显式跳过项必须逐一确认跳过理由成立;
- 可疑缺口:如果
mapped与explicit-skip之和小于总数,就意味着存在needs-triage悬置项,需要优先裁决。
各台账汇总对比(均来自各 ledger 文件的统计行):
| 台账 | 总数 | 已映射/沿用 | 显式跳过 | 其他 |
|---|---|---|---|---|
| legacy-slate-test-files.md | 1069 | 1033(mirrored 979 + recovered 49 + mixed 5) | 36 | — |
| legacy-slate-react-test-files.md | 8 | 6(mirrored 5 + mixed 1) | 2 | — |
| legacy-slate-history-test-files.md | 20 | 17(mirrored) | 3 | — |
| legacy-playwright-example-tests.md | 23 | 22(same-path-current 21 + recovered 1) | 1 | — |
六、与主发布台账的联动:停止过度宣称
计划的退出条件(Exit)有两条,缺一不可:
- 精确台账必须存在于
docs/slate-v2/ledgers/下——即上面讨论的四个 ledger 文件,它们统一登记在 ledgers/README.md 这个索引中,并附有状态词汇表(recovered / extended / mixed / open / post RC / cut); - 主发布文件台账必须指向这些精确台账,并停止过度宣称穷尽性。
第二点是整份计划的关键治理动作。"主发布台账"即 release-file-review-ledger.md,它服务于整个 fresh-branch 程序的逐文件迁移真相(per-file migration truth)。该台账的"Remaining-Work Rule"一节明确写了三条纪律:
- 剩余工作由合并语料驱动、按行作用域推进;
- 本台账不授权对剩余包做无差别的同路径重写;
- 也不把"避免重写"本身当作价值。
随后给出了诚实的下一步顺序:先围绕原生事务/快照存储 API 敲定packages/slate核心,再显式分类兼容性包袱(而不是凭反射保留),最后才重开支持包的迁移。这正是精确台账体系的闭环:精确账本让"剩余工作"可以被按行认领,也让"不做什么"成为显式决策。台账还特别标注了post RC状态的延期行(如仓库级 ESLint 源码强制、slate-browser 根级证明通道),进一步说明"未完成"是诚实声明的状态,而非被静默掩盖的缺口。
七、方法论提炼:如何在自己的迁移工程中落地这套体系
Exact Ledgers Plan 虽为 Slate v2 量身定制,但它的四条规则与三种状态完全可以抽象为通用迁移治理模板:
1. 用机械扫描替代人工枚举。台账的原始素材来自对**/test/**等目录的文件级扫描,而不是维护者回忆。任何迁移项目的账本都应从find/ glob 结果生成,保证"账本行数 = 实际文件数"。
2. 路径即主键,状态必显式。每个文件一行、以精确相对路径为主键,杜绝"X 目录下的文件基本都迁移了"这类模糊描述。无法立即裁决的文件标needs-triage,让悬置项浮出水面而不是沉入遗忘。
3. 细粒度状态表达迁移语义。mapped-mirrored(行为被镜像复现)、mapped-recovered(行为被新契约间接恢复)、same-path-current(同路径沿用)、explicit-skip(显式放弃,附理由)——状态词汇越贴近迁移语义,账本的可审计性越强。其中explicit-skip是最容易被忽视却最有价值的一类:它把"删除"从事故变成决策。
4. 主台账只做指针,不做复制。顶层发布台账不应重复维护细节,而应像 release-file-review-ledger.md 那样指向作用域级精确台账(本文对应的四个 ledger 均在 ledgers 目录 下),并诚实声明哪些部分仍在post RC或open状态。这样既保留了顶层可读性,又把穷尽性责任下放到可验证的账本。
5. 把"审计摘要"放在账本头部。每个台账顶部用三行数字(总数 / 已映射 / 显式跳过)给出健康度快照,让 CI 或人工巡检可以秒级判断:是否有未裁决文件、跳过项是否失控、迁移是否真正闭合。
八、执行状态与文档定位
截至当前仓库快照,Exact Ledgers Plan 的状态为in_progress(见 计划文档 的 frontmatter),但其核心产物——四个作用域的精确台账——均已实际生成并持续维护,日期标注为 2026-04-13 至 2026-04-14,且generated: true标记表明这些账本由工具生成而非人工手写,这正是"no silent aggregation"原则的机器保证。后续的 ledgers/README.md(2026-04-16)进一步将其纳入了 fresh-branch 迁移的活文档体系。
对于希望深入研究的读者,建议按以下路径阅读:
- 先读本计划 2026-04-13-slate-v2-exact-ledgers-plan.md 建立问题意识;
- 再读 ledgers/README.md 了解台账目录全景与状态词汇;
- 按需深入四个账本:核心包 legacy-slate-test-files.md(体量最大,最能体现方法论价值)、React 包 legacy-slate-react-test-files.md、历史包 legacy-slate-history-test-files.md、Playwright 示例 legacy-playwright-example-tests.md;
- 最后回到主台账 release-file-review-ledger.md,观察顶层台账如何引用下级账本并诚实声明边界。
这套"精确台账"体系的核心启示可以浓缩为一句话:在大型迁移工程中,可信的进度不来自维护者的自信声明,而来自每一个文件都有显式归宿的可验证账本。
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考