Plate Slate v2 补丁工作流(slate-patch):一条通道完成 Bug 复现、回归测试与架构压力审查
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
本文基于 Plate 仓库中的 Agent 技能定义 .agents/skills/slate-patch/SKILL.md,完整解析slate-patch这条“一次通过”的 Slate v2 缺陷修复工作流:它如何约束 Agent 先复现、再写行为级回归测试、在正确包/运行时归属层修复、以“严厉维护者”视角做架构压力审查,最后用基准目标交接与 autoreview 收口。读完本文,你可以掌握一套可直接借鉴的编辑器级 Bug 修复方法论——包括 11 类 Bug 分类法、选区/导航覆盖矩阵、验证门(gate)选择策略,以及补丁与性能优化通道(slate-ar-perf)的边界划分。
技能定义与来源:SKILL.md 由规则源生成
slate-patch的完整契约定义在前端 frontmatter 与正文中:
--- description: Fix Slate v2 bugs in one pass with reproduction, behavior tests, architecture/DX/perf pressure, proactive rearchitecture when the patch is not the cleanest long-term shape, and final autoreview. argument-hint: '[repair <expectation> | <Slate v2 bug report, route, issue, or regression cluster>]' disable-model-invocation: true name: slate-patch metadata: skiller: source: .agents/rules/slate-patch.mdc ---这里有两点值得注意:
source: .agents/rules/slate-patch.mdc表明 SKILL.md 并非手写终稿,而是由 规则源文件 经 skiller 管线生成的产物。两者当前内容逐行一致,规则源是“唯一事实源(source of truth)”,技能文件是同步后的运行时形态。disable-model-invocation: true表示该技能不会被模型自行调用,只能由用户显式触发(如slate-patch <bug report>或slate-patch repair <expectation>)。这是 Plate 对高风险修复通道的刻意设计:修复 Slate v2 主干代码的行为必须显式发起。
技能正文开篇即给出定位:
Use this for Slate v2 bug fixes where the agent should fix the bug now, then challenge its own patch with Slate Plan-level architecture pressure before handoff. This is the implementation lane for "fix it, but do not ship a dirty local patch".
也就是说,slate-patch是实现通道(implementation lane):现在就把 Bug 修掉,但在交付前用 Plan 级别的架构压力反审自己的补丁。“One pass(一次通过)”被明确定义为:复现、测试、修复、必要时重构、验证、autoreview、交接——而不是“最小 diff 获胜”。
适用边界:何时用、何时不该用
技能文档用两节划定了清晰的触发与排除条件,这是该工作流可复用性的关键:
应使用(Use When):
- 用户显式调用
slate-patch; - 用户报告 Slate v2 浏览器/编辑器 Bug 且要求的是修复而非方案;
- 近期多个 Bug 落在同一类别:selection、focus、history、undo、multi-root、content roots、void roots、DOM coverage、hidden DOM、rendering、schema、normalization、clipboard、IME、浏览器事件归属;
- 此前的本地补丁修好了症状但“味道不对”:example-only glue、调用方专属分支、测试安抚(test appeasement);
- 用户调用
slate-patch repair <expectation>,因为既往运行遗漏了某个周期性证明、流程或交接标准。
不应使用(Do Not Use When):
- 用户只要求架构方案或提案——应走
slate-plan; - 用户只要一次普通 diff 审查——应走 autoreview;
- 目标不是 Slate v2 或
.tmp/slate-v2checkout; - 修复属于所有 goal-backed 工作流的共性缺失——应走
autogoal repair; - 唯一诚实的下一步是多轮公共 API RFC 并需用户评审——应明确说明并路由到
slate-plan。
与 Slate AR 通道的分工
文档还专门用一小节划清与 Autoresearch 系技能(slate-ar/slate-ar-perf,见 规则源)的边界:
| 场景 | 路由 |
|---|---|
| 正确性失败 | slate-patch |
| 已有证明面的通用测量循环 | slate-ar |
| 已有正确性 oracle 的指标优化 | slate-ar-perf |
| 性能循环缺少 oracle | 先在slate-patch内补复现/测试/浏览器证明,再交接slate-ar-perf |
| 性能敏感的“正确性修复” | 可以以基准目标交接(benchmark target handoff)收尾,而非进入 Autoresearch packet 循环 |
从源码结构看,这一边界设计对应 Plate 的整体技能拓扑:.agents/skills/下并存的slate-ar、slate-ar-perf、slate-ar-fast、slate-ar-quality等十余个 AR 变体,全部以slate-patch产出的“正确性证明”为前置输入——补丁通道负责让行为变对,AR 通道负责让指标变好。
硬性规则(Hard Rules)
这是全文约束力最强的一节,逐条列出(原文语义完整保留):
- 当前
.tmp/slate-v2源码高于一切:胜过 Agent 记忆、旧方案、既往诊断。 - Slate v2 命令必须从
.tmp/slate-v2运行。在plate-2(主仓库 checkout)里跑的命令不能证明 Slate v2 行为——因为 Plate 主仓与正在重写的 Slate v2 是两份代码。 - 基准目标工作从
plate-2侧执行,通过 benchmarks/targets/slate-v2.json 与pnpm bench:targets:*命令族进行。它用于路由下一步工作、暴露基准缺口、向slate-ar-perf交接优化,但永不替代.tmp/slate-v2内的复现、测试与浏览器证明。 - 能复现就先复现。浏览器路由类 Bug 要用真实路由与行为级交互复现,不能只调模型状态。
- 合理时补行为级回归测试,优先覆盖 Bug 类别而非仅复现某个具体截图。
- 修归属边界:系统性 Bug 修包/运行时层优先于修 example;只有 example 契约本身错误时才允许改 example。
- 允许破坏性变更,当它换来更优的长期架构/API/DX/性能结果;不允许出于惯性保留坏的兼容性。
- 第一个补丁若不是最干净的长期形态,必须在验证前返工,禁止交付“能跑但脏”。
- 同类别多个 Bug 出现时,默认子系统不够健壮:搜索相邻 owner,在宣称切片完成前补类别级覆盖。
- 选区/导航类 Bug 使用通用编辑器导航矩阵,不得只覆盖暴露失败的那条路由、那种 content root/hidden block/void/synced block。
- 不制造 issue-ledger 或 PR 引用仪式,除非提示词本身是 issue-backed 或明确要求 issue 记账。
- 非平凡实现变更的最后一步永远是
autoreview。
Repair Command:修复技能本身的命令
当参数以repair <expectation>开头时,进入 Repair Command 分支——它修复的不是 Slate 运行时 Bug,而是技能工作流本身的遗漏,确保未来的slate-patch运行默认做对。
适用场景(原文列举):
- 未来补丁应包含某个周期性行为矩阵;
- 技能遗漏了必需的证明项或交接字段;
- 工作流审查了错误的 checkout;
- 某类周期性编辑器 Bug 被当成了孤立的本地补丁。
禁止用于:.tmp/slate-v2的运行时/产品 Bug、一次性措辞偏好、属于autogoal repair的目标生命周期遗漏、以及手工编辑生成物.agents/skills/*/SKILL.md。
六步修复工作流:
- 用一句话重述被遗漏的期望(missed expectation);
- 修补源 owner,通常是 .agents/rules/slate-patch.mdc;
- 若期望超出技能正文容量,新增或更新小型参考文档并从技能链接出去——选区/导航覆盖的参考文档固定为 docs/slate-v2/selection-navigation-coverage.md;
- 修改
.agents/rules/**后执行pnpm install重新生成.agents/skills/**; - 用三样东西证明修复:
rg确认规则源中的新规则、rg确认再生成的 SKILL.md 文本、文档/脚本变更时跑对应的 docs 审计或语法检查; - 最终回复包含四要素:expectation、repaired owner、sync 命令、proof。
这套“规则源 → 生成物 → 再同步 → 双重 grep 验证”的机制,正是 frontmatter 中skiller.source字段背后的工程实践:技能文件是派生物,直接改派生物会被视为违规(第 114 行的 Do not use 明确禁止 hand-editing generated SKILL.md)。
Goal Setup:以 autogoal 为生命周期内核
对非平凡的 Slate Patch 工作,技能要求使用 autogoal 作为生命周期内核。autogoal 负责活跃目标冲突、目标形状、计划状态、完成规则、阻塞规则与 repair 路由;而slate-patch这条派生通道自己拥有:复现、行为覆盖、Slate v2 证明、架构压力、autoreview 与基准交接。
目标句柄(goal handle)有固定模板:
Fix Slate Patch <bug/cluster>; done when repro, behavior coverage, Slate v2 proof, and autoreview pass; target `.tmp/slate-v2`.文档同时明确:不要为 slate-patch 创建 Slate Plan 式的 pass 排期——它只有一个实现切片,不是规划通道。
八步核心工作流
1. Reproduce And Bound(复现与定界)
- 读取最新的用户报告、附件媒体、路由、issue 或失败测试;
- 检查
.tmp/slate-v2中的 live owner; - 用最窄的诚实路径复现:
- UI Bug:浏览器路由 + 真实键盘/鼠标输入;
- 纯模型行为:包/单元测试;
- DOM import/export 与模型变更可能不一致时:两者都要;
- 捕获五要素:实际行为、期望行为、相关时的当前模型 selection/value、相关时的 DOM/原生 selection、负责的包/示例/测试。
2. Classify The Bug Class(先命名 Bug 类别)
打补丁之前必须先命名类别,候选类别共 11 类:
- selection import/export
- focus ownership
- history/undo
- DOM coverage / hidden content
- multi-root / content root / void root
- synced/root state
- normalization / schema
- rendering/projection
- clipboard/paste
- IME/mobile/browser event ownership
- performance/scalability
若该类别近期在对话线程或相邻测试中出现过,要扩大修复面:搜索共享同一错误假设的兄弟 example、包内 helper 与测试。这一条与 Hard Rule 第 9 条互为表里——类别复发即子系统不健壮。
3. Red Test(红测试)
新增或更新“对当前 Bug 会失败的最小行为测试”,按症状类型选择测试面:
- Playwright:浏览器可见的 selection、focus、hidden DOM、鼠标、键盘、剪贴板、路由回归;
- 包测试:模型 transforms、schema、operation、history、normalization 与确定性状态行为;
- 模型变换导致浏览器症状时:两个层面都写。
测试应同时断言用户可见不变量与模型不变量(当两者都重要时)。
Editor Selection Navigation Coverage(选区/导航覆盖矩阵)
当 Bug 类别触及 selection、键盘导航、鼠标选区、focus handoff、history focus、DOM coverage、hidden DOM、multi-root、content root、editable void、synced root、选区后剪贴板、选区后删除、选区后换行时,写测试前必须先从 selection-navigation-coverage.md 选取相关切片。红测试必须指明四个维度:
| 维度 | 可选取值(原文枚举) |
|---|---|
| command family(命令族) | arrow、shift-arrow、option-arrow、shift-option-arrow、command-arrow、shift-command-arrow、mouse drag、delete、backspace、insert break、copy、undo、redo |
| direction(方向) | forward、backward、up、down、into boundary、out of boundary、across many boundaries |
| topology(拓扑) | plain blocks、hidden DOM、DOM coverage boundary、multi-root、content root、editable void、synced root、virtualized DOM、mixed topology |
| starting state(起始状态) | collapsed、expanded forward、expanded backward、edge of block、multi-line、after focus handoff、after history restore |
| assertions(断言) | 精确的模型 selection/value;涉及浏览器可见行为时再加 DOM selection/focus/chrome 健全性断言 |
覆盖矩阵文档本身将其定义为“generic editor law(通用编辑器法则)”而非 content-root 清单,其命令族表比 SKILL.md 的枚举更细,例如字符移动族覆盖ArrowLeft/Right/Up/Down,边缘移动族覆盖Cmd+Arrow*、Home、End,鼠标选区族覆盖 click、click-drag、drag top-to-bottom、drag bottom-to-top、从失焦编辑器起拖五种形态,后续变更族还包含“移动/选区后 type、Backspace、Delete、Enter、粘贴”。文档强调:不要为每个 Bug 跑全矩阵,选择“最小诚实切片”,并记录刻意跳过的行及原因——“除非相关 command × direction × topology × starting-state 行实际全绿,否则不得宣称选区/导航已完整测试”。
针对selectionPolicy: 'materialize'类 Bug,还必须包含 materialize 专属覆盖行:首次垂直 Shift+Arrow 进入必须打开 hidden DOM;挂载后的下一次普通垂直 Shift+Arrow 不得保持 model-owned,除非它进入另一个未挂载的 materialize 边界;并且要包含“最后一条渲染行中线上、hidden 内容之前”的 caret 位置,不能只测块边缘。
4. Fix The Owner(修归属层)
只修那个“能让行为普遍成立”的 owner,并按五级归属阶梯选择:
- core package/runtime 架构;
- 共享 DOM/React 桥;
- schema/API 契约;
- 共享 example/组件模式;
- 仅当 example 是契约 owner 时,才改单个 example。
优先(Prefer)清单:更少的公共概念;更窄的订阅与 dirty scope;确定性的模型操作;schema 拥有的行为而非渲染器猜测;root/content 身份而非 DOM/index 推断;稳定的浏览器证明而非计时等待;修好真正的 owner 后删除绕路代码。
禁止偏好(Do not prefer)清单:调用方专属分支;example-only 掩盖包级 Bug;为未发布的坏 API 加兼容 shim;断言实现 trivia 的测试;一次使用且内联更清晰时的 helper 抽取。
5. Architecture Pressure Review(架构压力审查)
第一个补丁变绿后停下来,以“苛刻的 Slate 维护者”视角自审。任何一项回答薄弱,都要在最终验证前返工。九项检查清单:
- Architecture:这是最干净的长期 owner,还是只打了症状?
- API/DX:一个原生 Slate 用户或插件作者,不读这个 Bug 线程能否理解契约?
- Unopinionated core:是否把 Plate/产品策略排除在 Slate core 之外?
- Performance:热路径是否有界?有无全局扫描、大范围重渲染、过期 DOM 读取、重复布局计算?
- Data/model:编辑、undo、类远端重放之后,paths、runtime ids、root ids、schema 与 operation 语义是否仍然确定?
- Browser:DOM selection/focus/hidden content 行为是否匹配模型契约?
- Regression coverage:测试能否抓到整个类别,包括下一个最可能失败的兄弟案例?
- Breaking changes:如果干净的修复需要 break,是否直接取了 break 而非续命坏形态?
- Simplicity:能否删掉任何一个 helper、分支、选项、shim 或测试夹具?
判定必须是三者之一:
keep:补丁是正确长期形态;rework:先修再最终验证;escalate:停止,路由到slate-plan,因为正确修复是更大的公共架构决策。
6. Verify(验证门)
从.tmp/slate-v2运行聚焦门(gates),按触及面挑选集合:
- 变更包的单元测试;
- 变更包的 typecheck;
- 涉及 example 时的 site typecheck;
- 聚焦的 Playwright 路由测试;
- Playwright 不够时的浏览器复现脚本;
bun check:仅当触及面值得更宽的快门时;bun check:full:仅用于发布级浏览器声明或被显式要求时。
规则还规定:若某个门因无关的既有债务失败,记录确切命令与无关理由;不得掩盖相关失败。
7. Benchmark Target Handoff(基准目标交接)
Slate v2 正确性证明完成后,判断补丁是否需要基准目标同步或slate-ar-perf交接。触发条件:Bug 类别或补丁触及 performance/scalability、rendering/projection、React 重渲染行为、超大文档、history、clipboard、collaboration、浏览器 trace、operation replay、Slate-vs-Slate-v2 对等性,或任何应当被benchmarks/targets/slate-v2.json覆盖的行为。
五步工作流:
- 从
plate-2检查 slate-v2.json 并运行pnpm bench:targets:check; - 用
pnpm bench:targets:list或node tooling/scripts/slate-autoresearch.mjs suggest-loops --with-checks找匹配目标; - 目标存在时运行
pnpm bench:targets:dry-run -- <target-id>,记录slate-ar-perf是否应接管后续优化; - 目标不存在时记录
Benchmark target candidate needed - <behavior>及预期的基准命令与正确性命令; - 正确性 oracle 缺失时,所有权留在
slate-patch,直到测试/浏览器证明存在。
仓库侧证据与这条流程一一对应:根 package.json 定义了完整命令族——bench:targets:check、list、report、report:check、report:dry-run、dry-run、run、import-evidence-kit,全部落在 tooling/scripts/bench-targets.mjs;benchmarks/targets/README.md 说明该目录是“Slate 基准工作的迁移脊柱(migration spine)”,并明确 dry-run 是只读的(校验注册表并打印 Autoresearch 初始化计划)。目标注册表本身声明了迁移策略:
"policy": { "authority": "Benchmark targets are the future source of truth. Evidence Kit is a legacy import/report archive during migration.", "benchmarkCode": "Benchmark implementation lives with the runtime/package code it measures.", "activeLoops": "Autoresearch sessions optimize one target id at one time and own only active loop state." }其中benchmarkCode策略正体现了第 4 步“归属阶梯”思想在基准域的应用:基准实现与被测量的运行时/包代码同居一处。注册表内的实际目标(如react-huge-document-legacy-compare:对比 5,000 块 React 编辑/选区/启动/整文替换下 Slate v2 与 legacy Slate 的 p95 比值,cwd 为.tmp/slate-v2,正确性门为bun check)展示了 target id、primary metric、方向、correctness command 与 artifacts 的完整结构。
文档同时给出两个反向约束:不要把这步变成“无基准家族的微小模型修复”的税;也不要因为聚焦测试通过就跳过性能敏感的编辑器行为——测试证明正确性,目标注册表让基准积压保持诚实。
8. Autoreview(自动审查收口)
非平凡实现变更的最终清单项,六步:
- 加载 .agents/skills/autoreview/SKILL.md;
- 从拥有补丁的那个 checkout 运行 helper;
- 对
.tmp/slate-v2补丁,cwd 必须是.tmp/slate-v2,命令形如:
/Users/zbeyens/git/plate-2/.agents/skills/autoreview/scripts/autoreview --mode local- 对照源码核验每条 accepted/actionable 发现;
- 修复有效发现;
- 重跑聚焦证明与 autoreview,直到没有 accepted/actionable 发现为止。
末尾红线:不要从plate-2对.tmp/slate-v2补丁跑 dirty-local autoreview——那审查的是错误的 checkout。这一点与 Hard Rule 第 2 条同源:多 checkout 环境下,cwd 决定了你证明的是哪份代码。从 autoreview 技能 本身可见其契约:审查输出是建议性的、必须逐条读代码核验、以“helper 退出 0 且无可操作发现”为干净收口、审查可能持续至 30 分钟且心跳行代表健康推进。
Final Response:交接回复的固定字段
工作流收尾的回复要求保持简短,但必须包含:
- 根因(root cause);
- 架构决策,以及压力审查后是否发生过返工;
- 适用时的选区/导航矩阵切片:覆盖了哪些行、哪些行被刻意跳过;
- 运行过的测试/证明及不明确时的 cwd;
- 适用时的基准目标交接:target dry-run、
slate-ar-perf交接、候选目标待建,或带理由的 N/A; - autoreview 结果;
- 任何相关未解决门或无关的既有失败。
若架构压力判定为escalate,必须精确说明原因,并点名接下来要打开的slate-plan面。
方法论小结:为什么这条工作流值得借鉴
从这份技能定义可以看出 Plate 团队处理“重写中的 Slate v2”时的一贯工程判断,可提炼为四条可迁移原则:
- 复现先于假设,源码先于记忆:
.tmp/slate-v2当前源码是唯一权威,禁止以旧诊断直接打补丁。 - 类别化覆盖而非点状修复:11 类 Bug 分类 + 四维(命令族 × 方向 × 拓扑 × 起始状态)导航矩阵,把“修好这一个截图”升级为“关掉这一类 Bug”,并要求记录刻意跳过的行。
- 归属阶梯 + 压力审查双重闸门:五级归属阶梯约束“改哪里”,九项压力清单约束“改得干不干净”,且允许为了长期形态采取破坏性变更、允许第一版补丁推翻重来——“works but dirty”不可交付。
- 正确性与性能分道治理:正确性证明留在
slate-patch;指标优化经基准目标注册表交接给slate-ar-perf;oracle 缺失时先补证明再交接。测试证明正确性,注册表保持基准积压诚实,两者互不替代。
该工作流的全部事实依据均可在仓库内追溯:技能本体见 .agents/skills/slate-patch/SKILL.md 与其规则源 .agents/rules/slate-patch.mdc,导航矩阵见 docs/slate-v2/selection-navigation-coverage.md,基准命令见 package.json 的bench:targets:*脚本族与 tooling/scripts/bench-targets.mjs,目标注册表见 benchmarks/targets/slate-v2.json 及其 README,收口审查见 .agents/skills/autoreview/SKILL.md,生命周期内核见 .agents/skills/autogoal/SKILL.md。
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考