Files
mdpolish/research-wiki/design/0014-generic-local-reviewer.md
T

403 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 0014:项目无关的本地清洗评审器
## 状态
已于 2026-08-28 获用户明确批准,按本文第 15 节实施。本文自批准起冻结;后续改变决策需新增 design 并使用
`supersedes` 指向本文。
用户在批准本文时同时明确要求:完成实施和验收后提交 Git,创建并推送 `v0.7.0` tag,再用同一个已验收 wheel 及其
SHA-256 校验文件创建 GitHub Release。该授权不包括 PyPI、其他包索引、PR 或其他仓库修改。
`supersedes: 0008`(范围有限):本文拟改变“Web 评审器全部留在项目端”的边界。项目规则、流水线、文件写入和业务审核流程
仍由使用项目拥有;`mdpolish` 只增加读取正式 review JSON 的通用本地查看工具。
`supersedes: 0011`(范围有限):本文拟增加 HTML 浏览器界面和本机只读服务,但不改变 `ReviewDocument`、可信重放、
Markdown reporter 或核心无文件 I/O 的决定。
`supersedes: 0012`(范围有限):本文拟增加正式 JSON 的只读解析与校验入口。它不会把 JSON 恢复为 `ReviewDocument`
不会重新运行 `Modifier`,也不会把机器投影变成可重新应用修改的权威输入。
历史 `0007` 已经被 `0008` 替代,不因本文重新生效。本文只借鉴其本机服务安全边界,以及
`/home/lihaoze/work/mdpolish-wheel-pilot` 中已经实现的双栏界面;不恢复旧 artifact、locator、manifest 或项目实验系统。
## 1. 问题与可观察现象
`mdpolish v0.6.0` 已经能把可信的 `ReviewDocument` 生成为 schema `1.0``full` JSON。这个 JSON 包含完整输入、当前文本、
所有 Modifier 阶段和实际 Change,足以支持准确的浏览器评审。
但是当前库仍明确不提供 JSON 读取器、本地服务或评审页面。每个项目如果要查看结果,还要重复完成以下工作:
1. 解析并校验 `mdpolish.review` JSON
2. 验证正文哈希、阶段链、Change 范围和计数;
3. 把 Python Unicode 码点坐标转换成浏览器编辑器使用的 UTF-16 坐标;
4. 编写本机只读服务、双栏界面和 Change 跳转;
5. 持续跟随 review schema 和前端依赖变化。
wheel-pilot 已经按自己的 `0004` design 实现一版 React + CodeMirror 评审器。只读调查确认它的主要交互是通用的:选择文档、
查看总体输入/输出、按 Modifier 查看完整阶段、保留零修改阶段、滚动长文档,以及点击 Change 跳转。当前参考生产构建约
842 KiB;这只是本次方案比较的观测值,不是未来 wheel 大小承诺。
wheel-pilot 中真正属于项目的部分是论文 Modifier、七步顺序、批处理、`artifacts/v0.6.0/` 路径和五篇文档身份。
页面和只读服务不需要理解这些业务事实。因此,让每个项目继续复制整套 viewer 会形成重复实现和不一致的校验口径。
## 2. 决定摘要
第一版采用以下边界:
```text
使用项目
├── 选择 Modifier、参数和顺序
├── Pipeline.transform()
├── build_review_document()
├── render_json_report(..., detail="full")
└── 自行保存 *.review.json、决定权限与保留周期
mdpolish-reviewer --review-dir <明确目录>
├── mdpolish 官方 JSON 解析与语义校验
├── Python 码点 → UTF-16 只读定位
├── 回环地址上的只读 HTTP 服务
└── React + CodeMirror 双栏页面
```
评审器随同一个 `mdpolish` wheel 交付,但与内存清洗核心隔离。安装 wheel 不会启动服务、读取文件或改变任何 Markdown;
只有用户显式运行评审器命令时,工具才读取明确传入的目录。
项目无需复制前端或 Python 服务。项目只要保存正式 `full` JSON,就能使用同一界面。
## 3. 目标与非目标
### 3.1 目标
- 为所有使用项目提供同一套本地只读清洗结果页面;
- 保留 wheel-pilot 当前已经验证的双栏布局、Modifier 时间线、完整滚动和 Change 跳转体验;
- 直接消费 `mdpolish.review` 正式机器投影,不建立项目 artifact schema
-`mdpolish` 提供正式 JSON 的解析和校验,不让 viewer 私下维护另一套 schema 解释;
-`full` 数据验证正文哈希、阶段首尾、Change 批次、位置、计数和状态一致性,失败时拒绝近似展示;
- 保持 Modifier 阶段坐标的原语义,只为 CodeMirror 额外派生 UTF-16 范围;
- 只绑定本机回环地址,只提供同源静态页面和只读 API;
- 前端生产资源随 wheel 提供,使用项目运行页面时不需要 Node.js,也不从 CDN 下载资源;
- 保持普通 Python 核心安装零第三方运行依赖;
- 使用合成文本覆盖 Unicode、不同换行、空文档、零修改阶段、失败和不稳定状态。
### 3.2 非目标
- 不替项目读取原始 Markdown、运行 Pipeline、选择 Modifier 或保存 review JSON
- 不定义项目的目录层级、批处理协议、文档 ID、标题、审核状态、权限模型或保留周期;
- 不编辑、接受、拒绝、撤销或重新应用 Change,不从页面触发清洗;
- 不渲染 Markdown 排版,不执行原文中的 HTML,不加载图片、字体或其他外部资源;
- 不提供上传、远程访问、账户、数据库、多人协作、批注或生产部署接口;
- 不把 JSON 恢复为 `ReviewDocument``TransformResult` 或 Pipeline
- 不改变 schema `1.0` 的字段、哈希、坐标、detail 或正文暴露语义;
- 不增加默认流水线、项目 profile、业务规则或真实样本;
- 不在本轮修改或删除 wheel-pilot 的 reviewer。它的迁移与清理必须在该仓库另行批准;
- 不读取、复制、修改或提交真实文档、历史报告和外部数据。
## 4. 职责边界
| 能力 | `mdpolish` | 使用项目 |
| --- | --- | --- |
| Modifier 规则、参数和顺序 | 不拥有 | 拥有 |
| 清洗执行与内存审计 | 提供通用核心 | 显式调用 |
| `ReviewDocument` 与正式 JSON 生产 | 提供 | 决定是否生成 |
| review JSON 文件名、目录和覆盖策略 | 不决定 | 拥有 |
| review JSON 内容解析与通用一致性校验 | 提供 | 不再重复实现 |
| UTF-16 编辑器定位 | reviewer 内部提供 | 不需要实现 |
| 双栏页面、Modifier 时间线和 Change 跳转 | 提供 | 直接使用 |
| 文档业务名称、审核结论、批注和权限 | 不拥有 | 如有需要自行实现 |
| 数据脱敏、访问控制和保留周期 | 只说明风险 | 拥有 |
reviewer 不知道 JSON 对应哪个原始文件。页面展示的文档标签只能来自 review JSON 文件名,不能猜测输入路径、论文标题或业务
身份。项目如果需要额外业务字段,应建设自己的外层页面;第一版不为此增加 sidecar manifest 或配置插件。
## 5. 方案比较
| 方案 | 优点 | 代价 | 决定 |
| --- | --- | --- | --- |
| 每个项目继续复制 wheel-pilot reviewer | 上游 wheel 最小 | 校验、API、前端和依赖重复;行为会漂移 | 不采用 |
| 单独发布 `mdpolish-reviewer` wheel | 核心分发物最小 | 两个包必须配对版本、安装和发布;当前 reviewer 无第三方 Python 依赖 | 第一版不采用 |
| 同一 wheel 内放独立 reviewer 模块和静态资源 | 一个版本同时约束 producer、reader 和页面;项目只安装一个 wheel | 所有人下载的 wheel 都会增加静态资源体积 | 采用 |
| 运行时从网络下载页面 | wheel 较小 | 引入网络、版本漂移、隐私和供应链风险 | 不采用 |
| pip 构建 wheel 时自动运行 npm | 不提交生产 bundle | Git direct install 需要 Node.js 和网络,破坏现有 Python 安装体验 | 不采用 |
| 提交经过检查的生产 bundle并打进 wheel | 使用者不需要 Node.jsPython 构建保持简单 | 源码与生成资源必须同步检查,Git diff 会包含压缩文件 | 采用 |
这里的“同一 wheel”不表示 reviewer 成为 Pipeline 的一部分。依赖方向固定为 reviewer 可以导入 review JSON 解析能力,
`models.py``edits.py``modifier.py``pipeline.py` 不导入 reviewer、HTTP 或前端资源。
## 6. 正式 JSON 读取入口
第一版拟在受支持的 `mdpolish.review` 路径增加:
```python
class ReviewParseError(ValueError):
"""机器投影 JSON 不能被安全读取。"""
def parse_json_report(
report: str,
*,
expected_detail: ReviewDetail | str | None = None,
) -> ReviewProjection:
...
```
它接收内存字符串并返回只含 JSON 基本值的新 dict/list 容器。它不接收路径,不读取文件,不返回 `ReviewDocument`,也不重新运行
Modifier。`expected_detail=None` 接受 schema 支持的任一已知 detailreviewer 必须显式要求 `full`
解析至少执行以下通用检查:
- 拒绝重复 object key、非标准 `NaN` / `Infinity`、孤立 surrogate 和非 JSON 值;
- 要求 `schema_name == "mdpolish.review"`,并按 schema major 兼容规则处理版本;
- 验证已知 detail 的必需字段、类型、枚举、整数范围、引用位置和正文暴露边界;
- 对同一 schema major 的未知 object 字段按现有兼容规则忽略其语义,不改变已知字段解释;
- 遇到未知状态、detail、坐标契约或无法安全解释的 enum 时失败,绝不把它降级成 `success`
- 错误消息只给字段路径和契约类别,不拼入正文、参数、reason 或诊断消息。
`summary``changes` 不含完整阶段文本,解析器只能验证它们实际携带的结构和引用。`full` 还必须验证:
1. input、current 和每个阶段全文的 UTF-8 SHA-256 与码点长度;
2. 第一个完成阶段从 input 开始,相邻阶段首尾完全相接;
3. 每个 Change 的 modifier 引用、哈希、范围、原文、行列和顺序;
4. 使用核心共用的精确编辑应用原语重放当前阶段 Change,结果必须等于 stage after
5. 零修改阶段的 before 与 after 完全相同;
6. 完成阶段末尾等于 current,阶段数量与 `stages_complete` 及错误阶段相容;
7. counts、错误、残留候选和 `success` / `failed` / `unstable` 状态相容。
第 4 点比 wheel-pilot 当前服务只检查“before 中能找到片段”更严格。它防止攻击者同时篡改 stage after 正文和哈希后,页面仍把
一个并非由所列 Change 产生的结果展示为可信阶段。
解析器可以从 `edits.py` 复用私有验证与应用原语,但不得复制一份不同的冲突、排序或字符串应用规则。正常清洗公共接口和
schema `1.0` 生产结果必须保持不变。
## 7. 输入集合与文件边界
第一版本地入口拟为:
```text
mdpolish-reviewer --review-dir <review_directory> [--port <port>]
```
同时支持等价的模块入口:
```text
python -m mdpolish.reviewer --review-dir <review_directory>
```
`--review-dir` 必填,没有当前目录或 `artifacts/` 的隐式默认值。服务只读取该目录直属的 `*.review.json` 普通文件,按文件名
确定顺序,不递归、不扫描父目录、不跟随目录或文件符号链接。目录为空时明确失败。
文件适配器负责严格 UTF-8、BOM、读取错误和路径检查,然后把内存字符串交给 `parse_json_report(...,
expected_detail="full")`。核心解析函数不知道路径。
第一版使用去掉末尾 `.review.json` 后的文件名作为页面标签和内部文档身份。例如 `paper-01.review.json` 显示为
`paper-01`;它不自动补 `.md`,也不声称这是原输入文件名。重名、空身份或无法安全形成 URL 身份时启动失败。
目录名只作为页面顶部的本地集合标签,不成为运行 ID、项目 ID 或 schema 字段。绝对路径不返回给浏览器,也不打印正文。
review JSON 可能包含完整敏感正文。`mdpolish` 不自动创建、复制、移动、删除或清理这些文件;项目继续负责把它们保存在
合适的本地目录,设置权限、Git 忽略和保留周期。
## 8. 本机服务和内部 API
服务必须保持以下边界:
- 只绑定 `127.0.0.1`,默认端口 `0` 由操作系统选择;
- 只接受 `GET``HEAD`,其他方法返回 `405`
- 校验 `Host` 与可选 `Origin`,不开放 CORS
- 不提供任意文件路径、写入、删除、移动、重新运行或 shell 接口;
- 静态资源只来自 wheel 内固定目录,拒绝路径穿越和符号链接;
- 页面和 API 设置 `no-store`、CSP、`nosniff``no-referrer` 和禁止 frame 的响应头;
- 日志不输出正文、修改片段、参数或绝对 review 目录;
- 退出时不修改项目目录或浏览器外状态;
- 不自动打开浏览器,终端只打印明确的回环 URL 和不含敏感路径的文档数量。
浏览器使用版本化但只服务同一 reviewer 的内部 `/api/v1/`。API 至少提供:
| 资源 | 内容 |
| --- | --- |
| 集合摘要 | 集合标签、聚合状态、文档顺序和计数,不含正文 |
| 文档比较 | 输入、成功 current、Modifier 摘要、全部 Change 和诊断 |
| Modifier 阶段 | 指定完整阶段的 before、after、Change 和 UTF-16 定位 |
这是 Python 服务与同 wheel 页面之间的内部契约,不承诺给第三方项目直接调用。跨项目稳定数据契约仍是
`mdpolish.review` schema 和第 6 节的解析入口,不能把本地 HTTP API 变成第二个公共 artifact schema。
第一版启动时校验目录内全部 review。任何一份损坏都会阻止服务启动,并指出不含正文的文件标签和错误类别;不在同一次集合
中混合“已可信”和“猜测展示”的文档。若真实项目证明需要隔离单篇坏文件,再新增 design 改变失败策略。
## 9. UTF-16 编辑器定位
schema `1.0``span.start` / `span.end` 是所属阶段 before 文本中的 Python Unicode 码点半开范围。CodeMirror 使用
JavaScript UTF-16 code unit。reviewer 在 full 阶段已经通过校验后,派生:
```json
"editor_range": {
"start": 10,
"end": 12
}
```
这个范围只存在于内部 API,用于左栏选区和滚动,不写回正式 review JSON,不成为新的修改权威。中文基本平面字符通常不改变
数值,emoji 等补充平面字符会占两个 UTF-16 code unit。组合字符仍按原字符串逐码点转换,不做 Unicode 规范化。
转换必须以该 Change 所属的 `stage.before.markdown` 为输入。不得把中间阶段 span 套到原始输入、最终 current 或其他
Modifier 阶段。
## 10. 页面行为
第一版以 wheel-pilot 当前页面为迁移基线,保留用户已经满意的视觉和主要交互:
- 启动后选择第一份文档,默认比较完整 input 与成功 current
- 左侧列出文档和按位置排序的全部 Modifier;
- 选择 Modifier 后比较该阶段完整 before / after
- 零修改 Modifier 仍显示,前后全文相同;
- 不折叠未修改区域,长文由 MergeView 容器完整纵向滚动;
- 总结果列出全部 Change,阶段视图只列当前 Modifier 的 Change
- 点击 Change 时先切换所属阶段,等待 MergeView 用新 before/after 重建,再选中并居中左栏范围;
- `failed``unstable` 只显示准确的 partial/错误/残留证据,不把 current 命名为“清洗后”;
- Markdown、HTML、图片和脚本语法只作为只读源码,不渲染、不请求外部资源;
- 页面文案使用简体中文,第一版不建设主题、国际化或项目定制接口。
前端仍采用 React、TypeScript、Vite、CodeMirror MergeView、Vitest 和 React Testing Library。准确版本只在
`reviewer/package.json` 与锁文件中维护,不在 design 和 README 复制第二份易漂移清单。Node.js 24 只用于仓库开发、测试和
生成生产 bundle;使用 wheel 查看结果不需要 Node.js。
## 11. 源码和交付结构
批准后拟增加:
```text
reviewer/
├── .nvmrc
├── package.json
├── package-lock.json
├── src/ # React、API client、运行时响应校验
└── tests/ # 合成前端测试
src/mdpolish/
├── review.py # 增加正式 JSON 解析入口
├── reviewer.py # 路径适配、本地 API、HTTP 服务和 CLI
└── _reviewer_static/ # 经检查并提交的生产 HTML/JS/CSS
tests/
├── test_review_parsing.py # schema 与 full 语义校验
└── test_reviewer.py # 目录、HTTP、安全和 UTF-16
```
最终文件拆分可以在不改变职责的前提下机械调整,例如把 HTTP handler 放入私有模块;不得把 viewer 逻辑塞进
`pipeline.py` 或让核心导入前端资源。
生产 bundle 提交到 `_reviewer_static/` 并包含在 wheel,使从 Git 地址或 Release wheel 安装时不调用 npm。前端源码或锁文件
变化后必须重新构建并检查 bundle;Python wheel 构建只打包现有已验证资源。测试必须发现缺失或陈旧入口资源,不能在没有
页面时静默构建一个“成功”wheel。
前端 bundle 引入的第三方代码必须在仓库和 wheel 中保留适用的版权与许可证说明。实现验收要列出实际 bundle 和 wheel 大小,
检查 wheel 不包含 `node_modules`、前端测试、coverage、source map、真实数据或 review JSON。
`pyproject.toml` 增加 `mdpolish-reviewer` console script 和静态 package data。普通 `mdpolish` 导入路径不重新导出服务对象;
公共 Python 读取入口仍位于 `mdpolish.review`
## 12. 兼容与版本
本文增加公共 JSON 读取函数、公共 CLI、HTML 页面和 wheel 文件,属于 `0.x` 阶段的功能性次版本变化。实施候选版本计划从当前
未发布的 `0.6.1` 更新为 `0.7.0`;不改变现有 Modifier 版本、Pipeline 结果或 schema `1.0`
reviewer 和 producer 随同一个 wheel 发布,避免建立第二套版本配对规则。页面内部 API 可以随同一 wheel 修改,但必须同步
Python、TypeScript 运行时校验和测试。
正式 `mdpolish.review` schema 继续独立版本。若未来 schema major 改变,reader 必须拒绝;同 major 的加法字段按
`0012` 的兼容规则处理。任何修改现有字段含义、正文暴露等级或坐标口径的工作仍需新的 design,不能借 reviewer 页面绕过。
## 13. 测试与验收
### 13.1 JSON 解析与失败关闭
只使用虚构小文本,至少覆盖:
- `summary``changes``full` 的必需字段和暴露边界;
- 空文档、空流水线、零修改 Modifier 和多 Modifier 链;
- success、unstable、preflight failure、transform failure 和 final review failure
- 中文、emoji、组合字符、BOM 字符、LF、CRLF、CR 和无末尾换行;
- full 中所有文本哈希、阶段链、Change 重放、位置、计数和状态;
- 重复键、BOM 文件、错误 UTF-8、非有限数、孤立 surrogate、未知 schema major/detail/enum
- 损坏 input/current/stage 哈希、断裂阶段、错误 span、冲突 Change、篡改 after、零修改阶段却改变文本;
- 解析错误不包含正文、参数、reason 或诊断消息哨兵;
- 解析器不读文件、不访问网络、不调用 Modifier,不改变传入或返回外部容器。
同一组合成 full report 应分别通过 `ReviewDocument` 生产路径和 JSON 读取路径,逐阶段比较相同的 before、after、哈希与 Change
顺序。只比较最终 current 不足以证明 reader 与 producer 一致。
### 13.2 本地服务
- 明确目录的多份合法 full JSON 可以得到集合、文档和 Modifier 阶段响应;
- 文件名顺序、标签、零修改阶段和聚合计数正确;
- 空目录、递归文件、符号链接、未知文件、损坏 JSON 和重复身份失败;
- 路径穿越、异常 Host/Origin、未知路由和非 GET/HEAD 请求被拒绝;
- 服务只绑定 `127.0.0.1`,安全响应头和媒体类型正确;
- API 和日志不返回绝对目录,不输出正文到终端;
- 码点到 UTF-16 的转换覆盖 emoji、组合字符、不同换行和空插入;
- 缺失静态资源时明确失败,不访问 CDN 或任意磁盘路径。
### 13.3 前端
- 文档列表、聚合状态和修改数显示正确;
- 总结果、Modifier 阶段和零修改阶段切换正确;
- Change 筛选、同阶段跳转、跨 Modifier 跳转和重建后聚焦正确;
- 长文不生成折叠区,MergeView 保持纵向滚动;
- Markdown 中的 HTML、图片和脚本保持惰性文本;
- failed、unstable、API 错误和未知内部响应不显示虚构成功结果;
- ESLint、TypeScript、Vitest 和 Vite 生产构建通过;
- 真实浏览器滚动和视觉仍需人工验收,jsdom 结果不能替代。
### 13.4 回归与交付
实施完成后运行根 README 当时列出的全部检查,并额外确认:
- 现有 Pipeline、Modifier、ReviewDocument、dict/JSON producer 和 Markdown reporter 行为不变;
- 普通核心安装仍没有第三方 Python 运行依赖;
- 最低和当前支持的 Python 环境都能启动 reviewer 并读取合成 full JSON
- wheel 能从仓库外安装和启动页面,静态资源、console script 与版本正确;
- 记录 wheel 文件清单、压缩/解压大小和相对 `0.6.1` 候选的增量;
- wheel 不包含 `node_modules`、前端测试、source map、真实报告、项目规则或数据;
- 前端第三方许可证说明完整;
- `AGENTS.md``CLAUDE.md` 除标题外正文一致;
- Git diff 不混入 wheel-pilot、真实文本、大型实验产物或用户已有改动。
真实项目数据不是实现正确性的必要条件。批准本文也不授权读取或复制 wheel-pilot 的 `local-data/``artifacts/`
若用户随后希望确认页面视觉,可以由 wheel-pilot 继续使用自己的已有结果,或在该仓库另行批准改用上游候选 wheel。
## 14. 风险与代价
- **wheel 明显变大:** 当前参考 bundle 约 842 KiB,实际实现仍需记录。换来的是项目不再安装 Node.js 或复制页面。
- **公共 CLI 需要兼容维护:** `--review-dir` 和只读行为一旦发布就不能随意更名;第一版参数保持最少。
- **提交生成资源会增加 diff** 这是保证 Git direct install 不依赖 npm 的代价,必须用构建和 wheel 测试防止陈旧 bundle。
- **解析器公共表面积增加:** 它需要长期跟随 schema,但比每个项目各写一套校验更可控。
- **full JSON 占用内存:** 每阶段重复全文,reader 和页面还会产生额外容器;第一版不承诺无限文档或批量规模。
- **本机 HTTP 仍有攻击面:** 回环、Host/Origin 校验、无 CORS、CSP、无写接口和明确目录都是必需边界。
- **文件名不等于业务身份:** 通用 schema 没有路径和标题;第一版宁可显示保守标签,也不引入项目 manifest。
- **页面可能被误当成审核系统:** 它只展示清洗证据,不记录批准、拒绝、责任人或结论。
- **wheel-pilot 暂时重复:** 上游实现和发布前,两边 reviewer 会并存。迁移应在消费者仓库单独评审,不能同时删除以制造大爆炸变更。
## 15. 批准后的实施边界
用户明确批准本文后,只授权:
1. 在当前 `mdpolish` 仓库实现第 6 至 11 节的 JSON reader、本机服务、前端、静态资源和 console script
2. 从 wheel-pilot 已提交的页面与服务中参考或迁移项目无关代码,但不修改该仓库,不读取其真实数据与 artifacts;
3. 为共享精确编辑语义做必要的私有机械复用,不改变公共清洗结果;
4. 新增合成 Python/TypeScript 测试,并完成第 13 节的构建、wheel 和仓库外 smoke test
5. 实现完成后更新 README 当前能力、`review-projection.md`、schema reference 和经实际验证的 guide
6. 把候选包版本更新为 `0.7.0`,报告实际 diff、测试、bundle、wheel 和许可证检查。
本次批准还授权在全部必需验收通过后:
1. 提交本文及其实施,使用中文 Git commit subject
2. 把当前分支提交和 `v0.7.0` tag 推送到 `origin`
3. 只把提交前已经验收的同一个 `mdpolish-0.7.0-py3-none-any.whl` 和 SHA-256 校验文件上传到
`v0.7.0` GitHub Release,不能在 tag 后重新构建另一份 wheel 冒充已验收产物。
本次批准不授权:
- 创建 PR,发布到 PyPI、GitHub Packages 或其他包索引;
- 修改 wheel-pilot、其他仓库、真实数据或历史 artifacts;
- 增加远程绑定、写接口、上传、认证、数据库、项目 metadata、审核工作流或 Markdown 渲染;
- 改变清洗规则、Modifier 顺序、误删容忍度、`RunStatus``ReviewDocument` 字段或 schema `1.0` 语义。