plate 项目 Slate v2 基准目标注册表(Benchmark Targets Registry)与 Autoresearch 优化控制平面完全指南
2026/9/14 22:45:55 网站建设 项目流程

plate 项目 Slate v2 基准目标注册表(Benchmark Targets Registry)与 Autoresearch 优化控制平面完全指南

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

本文围绕 plate 仓库中 benchmarks/targets/README.md 所定义的 Benchmark Targets 机制展开:它是 Slate v2 基准测试工作的迁移主轴(migration spine),用一份结构化注册表统一回答"我们在测什么决策、Agent 如何运行或优化它"这两个核心问题。读完本文,你将掌握目标注册表的数据契约、全套pnpm bench:targets:*命令的用法与副作用边界、生成报告/历史的读写流程,以及如何用dry-runautoresearch-init驱动一个可审计的基准优化循环。

一、为什么需要"目标注册表":从 Evidence Kit 到单一事实来源

在 Slate v2 的性能工作中,基准测试长期分散在不同位置:benchmarks/editor下的 Evidence Kit(历史导入/报告归档)、各 runtime/package 包内的基准实现、以及大量散落在docs/plans/中的性能计划文档。benchmarks/targets目录正是为了解决这种分散状态而建立的迁移脊柱

  • 基准实现(benchmark implementation)与被测量的 runtime/package 代码放在一起,注册表只负责登记,不重复实现;
  • 注册表(benchmarks/targets/slate-v2.json)通过一个目标 ID 聚合队列(cohort)、指标(metrics)、运行命令(command)、正确性校验(correctness)、产物(artifacts)与证据链接(docs)
  • Autoresearch 会话一次只优化一个目标 ID,且只拥有活跃循环状态(active loop state),避免多个优化会话互相污染;
  • 文档与研究文件只是链接证据(linked evidence),不是基准控制状态。

这一设计原则在注册表的policy字段中被显式固化(benchmarks/targets/slate-v2.json):

"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 a time and own only active loop state.", "docs": "Docs and research files are linked evidence, not benchmark control state." }

二、目录结构与角色分工

benchmarks/targets下当前只有四个文件,分工非常清晰:

路径角色
benchmarks/targets/README.md迁移脊柱的说明文档:所有权、命令、目标契约、生成输出
benchmarks/targets/slate-v2.json注册表本体versionpolicy与 27 个目标定义(唯一输入)
benchmarks/targets/history/slate-v2-latest.json生成的快照:由注册表派生的最新目标历史(含产物存在性检查结果)
benchmarks/targets/reports/slate-v2.md生成的报告:人类可读的目标状态汇总表

生成类文件(history/reports)都由pnpm bench:targets:report从注册表派生,不要手改——pnpm bench:targets:report:check会以字节级比对校验它们是否与注册表一致(见后文)。

三、命令速查与使用场景

原文档给出的命令全集如下(均已映射到 package.json 中的同名bench:targets:*脚本,底层统一指向 tooling/scripts/bench-targets.mjs):

pnpm bench:targets:list pnpm bench:targets:check pnpm bench:targets:report pnpm bench:targets:report:check pnpm bench:targets:dry-run -- react-active-typing-breakdown pnpm bench:targets:run -- react-active-typing-breakdown node tooling/scripts/bench-targets.mjs autoresearch-init react-active-typing-breakdown

各命令的语义与副作用边界,结合脚本源码(tooling/scripts/bench-targets.mjs)逐一说明:

命令副作用行为说明
bench:targets:list只读按 ID 排序输出每个目标的idfamily、主指标、运行命令(对应脚本listTargets
bench:targets:check只读对注册表执行结构校验validateRegistry):version必须为 1、targets非空、字段齐全、ID 唯一、cwd/artifacts.path必须是仓库相对路径、metrics.direction只能是lower/highermetrics.printsMetric必须是布尔、correctness.commandartifacts必填;任一错误即非零退出
bench:targets:report写文件重建 history 与 markdown 报告并写入 benchmarks/targets/history/slate-v2-latest.json 和 benchmarks/targets/reports/slate-v2.md
bench:targets:report:check只读assertFileEquals逐字节比对两个生成文件与当前注册表的派生结果,过期即报错generated file is stale
bench:targets:report:dry-run只读仅打印targets=N missingRequired=M概览,不落盘
bench:targets:dry-run -- <target-id>只读校验注册表、在内存中构建报告模型,并调用 Autoresearch 的setup-plan为指定目标生成设置计划(JSON),打印autoresearchSetupOkbenchmarkMode等关键结论
bench:targets:run -- <target-id>运行基准读取目标的cwdcommand,用 shell 同步执行并透传 stdio(脚本runTarget使用spawnSync(..., { shell: true, stdio: 'inherit' })),退出码透传
autoresearch-init <target-id>.tmp会话文件调用 Autoresearch 的setup命令,创建或替换真实的.tmp/slate-v2/autoresearch.*会话文件
autoresearch-setup-plan <target-id>只读仅打印设置计划(setup-plan),不写任何会话文件

原文档特别强调的安全边界值得重复:bench:targets:dry-run是只读的——它只检查注册表并打印该目标的 Autoresearch 设置计划;只有当你确实要创建或替换真实的.tmp/slate-v2/autoresearch.*会话文件时才使用autoresearch-init。对操作者(operator)工作流,应优先调用slate-ar*系列技能而不是直接操作包脚本(相关示例见 docs/plans/2026-06-01-slate-ar-target-finalize-pagination.md,其中记录了pnpm slate:ar:setup-target -- <id>pnpm slate:ar:statepnpm slate:ar:finalize-preview等技能化入口)。

四、目标契约(Target Contract)逐字段解析

每个目标都是一个自包含的"决策单元"。以注册表中react-huge-document-legacy-compare为例(benchmarks/targets/slate-v2.json):

{ "id": "react-huge-document-legacy-compare", "question": "Does Slate v2 beat legacy Slate for 5,000-block React editing, selection, startup, and full-document replacement?", "owner": "slate-v2", "family": "react-large-document", "kind": "slate-legacy-compare", "cwd": ".tmp/slate-v2", "command": "REACT_HUGE_COMPARE_LEGACY_REPO=../../../slate REACT_HUGE_COMPARE_DISPOSE_DELAY_MS=0 REACT_HUGE_COMPARE_SPLIT_SELECTION=1 REACT_HUGE_COMPARE_ISOLATE_SURFACES=1 REACT_HUGE_COMPARE_SURFACES=v2DefaultRenderAuto,v2DomPresent REACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:local", "metrics": { "primary": "react_huge_doc_legacy_compare_worst_p95_ratio", "direction": "lower", "unit": "ratio", "printsMetric": true, "upgrade": "Primary metric is the worst p95 ratio across the 5,000-block default/render-auto and DOM-present product lanes versus legacy chunking-on." }, "correctness": { "command": "bun check", "policy": "Promotion requires the benchmark p95 ratio plus the fast Slate v2 check suite." }, "artifacts": [ { "path": ".tmp/slate-v2/tmp/slate-react-huge-document-legacy-compare-benchmark-compare-v2DefaultRenderAuto-v2DomPresent-blocks-5000-iters-5-ops-10-isolated-surfaces-split-selection-no-profile.json", "required": true } ], "docs": { "sources": [ "benchmarks/editor/research/evidence-source-map.md", "benchmarks/editor/iterations/003-evidence-control-plane.md", "docs/plans/2026-06-01-react-huge-document-legacy-ar-perf.md" ] }, "thresholds": { "promotion": "react_huge_doc_legacy_compare_worst_p95_ratio<=1.5", "stop": "stop when the promotion target is stable across two correctness-green repeat packets or when the remaining owner needs architecture work" }, "migration": { "importedFrom": "benchmarks/editor/research/benchmark-registry.json", "evidenceKitId": "react-huge-document-legacy-compare", "evidenceKitCategory": "slate-react-huge-document-legacy-compare", "evidenceKitActive": true } }

原文档列出的契约字段与含义:

  • id:面向命令的稳定 ID,贯穿dry-runrunautoresearch-init等所有命令;
  • question:该基准要回答的决策问题(这是"目标"与普通脚本的关键区别——每个目标绑定一个明确决策);
  • owner:runtime/package 所有者(当前均为slate-v2);
  • familykind:用于报告分组的两个维度——family是主题族(如react-large-documentcore-compare),kind是形态(如currentcomparebrowser-tracebenchmark-suiterowsslate-legacy-compareissue-replay);
  • cwdcommand:仓库相对的工作目录与实际执行命令;校验器强制cwd不能是绝对路径;
  • metrics:主指标(primary)、优化方向(direction,仅允许lower/higher)、单位(unit),以及printsMetric布尔位——表示命令输出是否原生打印METRIC name=value行;
  • correctness:防止"提速却破坏编辑器行为"的守卫命令;多数目标默认bun check,个别目标有更精确的定向测试(见下节);
  • artifacts:目标产生的结果文件(required标记是否必须存在);报告生成时逐文件做存在性检查;
  • docs:支撑证据链接(计划文档、研究文档);
  • migration:Evidence Kit 退役期间的临时来源追踪(importedFromevidenceKitIdevidenceKitCategoryevidenceKitActive)。

原文档还特别强调输出规范:基准输出应逐步向原生METRICARTIFACT行收敛;在尚未收敛前,Autoresearch 可以用metrics.printsMetric: false来包装计时(即由 Autoresearch 自行测量耗时,而不是读取基准打印的指标行)。这在脚本autoresearchSetupArgs中体现为--benchmark-prints-metric参数(tooling/scripts/bench-targets.mjs)。

五、27 个目标的分族全景与代表性目标深度解析

当前注册表登记了27 个目标、27 个产物声明(其中 25 个必选),可归为以下族(数据来自 benchmarks/targets/slate-v2.json):

  • react-large-document(React 大文档)react-huge-document-legacy-comparereact-huge-document-fullreact-huge-document-overlaysreact-huge-document-browser-tracereact-huge-document-virtualized-type-to-paintreact-huge-document-slate-browser-trace
  • react-locality(React 局部性)react-rerender-breadthreact-runtime-node-fanout
  • react-typing / react-paginationreact-active-typing-breakdownreact-pagination-virtualized-char-burst
  • core-current / core-compare(核心当前态与对比)core-normalization-currentcore-query-ref-observationcore-node-transformscore-text-selectioncore-editor-storecore-refs-projectioncore-transaction-currentcore-huge-document-comparecore-normalization-comparecore-observation-comparecore-rich-text-operations-compare
  • historyhistory-comparehistory-retained-memory
  • clipboard / collaboration / browser-rich-text / issue-replayclipboard-large-payloadcollab-readinessbrowser-rich-text-replay-coverageissue-6038-transaction-execution

5.1 综合套件:react-huge-document-full

这是覆盖面最广的目标(kind: benchmark-suite),一条命令串联核心大文档操作、React legacy 对比、浏览器 type-to-paint、长任务与 overlay 局部性等多个车道:

"command": "HUGE_DOC_FULL_LEGACY_REPO=../../../slate HUGE_DOC_FULL_BLOCKS=5000 HUGE_DOC_FULL_ITERATIONS=5 HUGE_DOC_FULL_TRACE_ITERATIONS=5 HUGE_DOC_FULL_TYPE_OPS=10 bun run bench:react:huge-document:full:local", "metrics": { "primary": "react_huge_doc_full_max_budget_ratio", "direction": "lower", "unit": "ratio", "printsMetric": true }, "thresholds": { "promotion": "react_huge_doc_full_max_budget_ratio<=1 and react_huge_doc_full_failure_count=0", "stretch": "react_huge_doc_full_max_budget_ratio<0.67", "plateau": "stop after 2 correctness-green packets with less than 5% gain" }

它的正确性策略最严格:提升(promotion)要求聚合套件指标达标、react_huge_doc_full_failure_count=0,且快版 Slate v2 检查套件通过。thresholds中的三档语义值得注意:promotion是放行线,stretch是理想目标,plateau停止条件(连续 2 个正确性绿包且收益 <5% 就停止优化,避免过度投入)。

5.2 浏览器追踪:react-huge-document-virtualized-type-to-paint

该目标回答"5000 块虚拟化 React 表面能否把 type-to-paint 延迟控制在交互预算内",主指标是react_huge_doc_type_to_paint_p95_ms(单位 ms):

"command": "SLATE_BROWSER_TRACE_SURFACES=virtualized SLATE_BROWSER_TRACE_ITERATIONS=5 SLATE_BROWSER_TRACE_TYPE_OPS=10 SLATE_BROWSER_TRACE_NATIVE_TIMEOUT_MS=5000 bun run bench:react:huge-document:browser-trace:local", "thresholds": { "promotion": "react_huge_doc_type_to_paint_p95_ms<75", "stretch": "react_huge_doc_type_to_paint_p95_ms<50" }

它的correctness.command是 Playwright 定向测试而非bun check,用-g过滤出"虚拟化 DOM 策略控制与指标暴露""动态块高下虚拟化反向滚动稳定"两组用例(benchmarks/targets/slate-v2.json),把性能放行与浏览器行为正确性绑定在一起。

5.3 局部性契约:react-runtime-node-fanout

该目标衡量"根插入、重排、全文档替换是否唤醒无关的 runtime-node selector",主指标是聚合 fanout 违规计数,promotion 线就是 0

"metrics": { "primary": "slate_react_runtime_node_fanout_count", "direction": "lower", "unit": "count", "printsMetric": true }, "correctness": { "command": "cd packages/slate-react && bun test:vitest test/provider-hooks-contract.tsx -t \"fan out|full-document replacement\"", "policy": "Promotion requires the runtime-node selector fanout contract plus the benchmark metric at 0." }, "thresholds": { "promotion": "slate_react_runtime_node_fanout_count=0" }

它示范了"正确性命令可以高度定向":只用 Vitest 过滤出 fan-out 与全文档替换相关的契约用例,而不是跑整个套件。

5.4 对比族:core-rich-text-operations-compare 与 history-compare

对比类目标(kind: compare)衡量 Slate v2 相对 legacy Slate 的 p95 比值。例如core-rich-text-operations-compare通过环境变量控制迭代次数(RICH_TEXT_OPS_COMPARE_ITERATIONS=51),主指标rich_text_structural_ops_p95_ms,且设置了多级阈值:

"thresholds": { "first": "rich_text_structural_ops_p95_ms below 10x legacy", "promotion": "rich_text_structural_ops_p95_ms below 3x legacy", "plateau": "stop after 2 packets with less than 5% gain" }

history-compare则以HISTORY_BENCH_LEGACY_REPO=../../../slate指向 legacy 仓库,主指标history_compare_worst_p95_ratio,promotion 线为"≤2.0 且 bun check 绿"。

5.5 关于 legacy 对比的前提说明

所有*_compare*目标都通过XXX_LEGACY_REPO=../../../slate这类环境变量显式指向同级的 legacy Slate 仓库,且cwd统一为.tmp/slate-v2(从脚本视角看是benchmarks/相对工作区的构建/运行暂存区)。这意味着这些目标依赖本地存在 legacy Slate 源码树,属仓库外部前提,运行前需要自行准备对应 checkout。

六、生成输出:history 快照与报告报告

pnpm bench:targets:report写出的两个文件是Evidence Kit 活跃健康/报告表面的注册表替代品——它们只汇总注册目标与已登记产物的状态,不运行昂贵的基准

  • benchmarks/targets/history/slate-v2-latest.json:结构化快照,含registryPathpolicycounts(目标数、产物数、必选/可选产物、缺失统计、状态计数)与每个目标的展开明细(含status与产物exists标记);
  • benchmarks/targets/reports/slate-v2.md:Markdown 汇总报告,首部是 Summary 块,主体是 27 行目标状态表。

报告生成逻辑在 tooling/scripts/bench-targets.mjs 的buildTargetHistoryrenderMarkdownReport中实现,其中状态判定规则清晰可读:

status: missingArtifacts.length > 0 ? 'missing-required-artifact' : missingOptionalArtifacts.length > 0 ? 'missing-optional-artifact' : 'ok'

当前快照(benchmarks/targets/history/slate-v2-latest.json)显示:27 个目标、25 个必选产物全部存在、缺 2 个可选产物(core-transaction-currenthistory-retained-memory的产物被标记为required: false),状态分布为ok=25, missing-optional-artifact=2missing-required-artifact=0。报告表格的 "Metric output" 列区分yes(基准原生打印 METRIC 行)与wrapped(需 Autoresearch 包装计时)。

七、实操:一个完整的目标优化工作流

把上述机制串起来,一个规范化的基准优化闭环如下:

  1. 登记/校验:确认目标已在 benchmarks/targets/slate-v2.json 中定义,运行pnpm bench:targets:check保证注册表结构合法;
  2. 预演:运行pnpm bench:targets:dry-run -- <target-id>(只读),它会校验注册表、在内存中构建报告模型,并让 Autoresearch 输出该目标的setup-plan——若autoresearchSetupOk=true说明设置计划可生成,这是开始真实优化循环前必须确认的一步;
  3. 建会话:确认要创建/替换真实会话文件后,运行node tooling/scripts/bench-targets.mjs autoresearch-init <target-id>(等价于pnpm slate:ar:setup-target -- <target-id>技能化入口);
  4. 运行基准pnpm bench:targets:run -- <target-id>在目标cwd下以 shell 执行其command
  5. 正确性门禁:按目标correctness.command跑校验(默认bun check,定向目标则跑对应 Vitest/Playwright 用例),确保性能提升没有破坏编辑器行为;
  6. 评估阈值:对照目标thresholds.promotion(及stretch/plateau)判断是否可以放行、是否应停止;
  7. 刷新产出pnpm bench:targets:report重新生成 history 与报告,pnpm bench:targets:report:check验证生成文件与注册表一致(CI 可复用该检查防止生成物过期漂移)。

八、迁移与演进:Evidence Kit 的退役路径

pnpm bench:targets:import-evidence-kit仅在从 benchmarks/editor/research/benchmark-registry.json 迁移活跃行时使用。脚本importEvidenceKit(tooling/scripts/bench-targets.mjs)读取 legacy 注册表,将每个 artifact 映射为新式目标(decisionquestioncwd/path归一化为仓库相对路径、自动按family/kind推断默认指标名metricNameFor,如react-typing族 →typing_secondsbrowser-trace形态 →browser_trace_secondscore-*族 →core_benchmark_seconds),并写入migration追踪块。不带--write时仅打印映射结果供预览。

迁移完成后,直接在注册表中编辑目标定义即可,不再需要回写 Evidence Kit;migration块只保留"从哪来"的临时来源信息(importedFromevidenceKitIdevidenceKitCategoryevidenceKitActive),供审计追溯。这也解释了为什么当前 27 个目标中大多数仍带有migration块,而 2026-06 之后新增的目标(如react-runtime-node-fanoutreact-huge-document-virtualized-type-to-paintreact-pagination-virtualized-char-burst)已不再需要——它们从诞生起就是注册表原生目标(migration: null)。

九、小结

Benchmark Targets 注册表把 Slate v2 的基准工作收敛为"一个 JSON、一套脚本、两个生成物"的控制平面:注册表是唯一输入,校验命令保证结构合法,dry-run/autoresearch-init 支撑可审计的 Agent 优化循环,report/check 保证产物可追溯。对于需要在该仓库上开展性能工作的开发者或 Agent 而言,正确姿势是先list找到目标 ID,再dry-run预演、autoresearch-init建会话,优化期间用目标自带的correctness.command守住行为底线,最后用reportreport:check落盘并验证产出——全程不触碰注册表以外任何"控制状态"。

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询