feat: 增加项目无关的本地清洗评审器

This commit is contained in:
2026-08-28 19:06:10 +08:00
parent 10c026c7ad
commit 6c0dd5974b
82 changed files with 9335 additions and 48 deletions
+93 -35
View File
@@ -3,10 +3,9 @@
`mdpolish` 是实验室共用的、项目无关的 Python Markdown 修改库。它提供函数式 `Modifier`、精确文本编辑执行器、
有序 `Pipeline`、正则修改器工厂,以及少量可以用合成样例完整说明的通用修改器。
当前发布版本是 [`v0.6.0`](https://github.com/Bepr4/mdpolish/releases/tag/v0.6.0),当前工作树候选版本是尚未发布的
`0.6.1`。库只处理内存中的 Markdown 字符串,
不读取或写入文件,不提供默认流水线,也不包含任何项目的规则集合、
数据清单、实验脚本或评审界面。
当前发布版本是 [`v0.7.0`](https://github.com/Bepr4/mdpolish/releases/tag/v0.7.0)。清洗核心只处理内存中的 Markdown
字符串,不读取或写入文件,不提供默认流水线,也不包含任何项目的规则集合、数据清单或实验脚本。安装包另外提供一个
必须显式启动的本地只读评审器,用来展示项目已经保存的正式 `full` review JSON;它不替项目运行清洗或管理产物。
## 当前能力
@@ -19,6 +18,8 @@
| `render_markdown_report()` | 把评审视图编排成完整 Markdown 源码报告字符串 | 只返回内存字符串,不创建文件或业务页面 |
| `review_document_to_dict()` | 按 schema `1.0` 把评审视图投影成普通 JSON 基本值 | 单向投影,不反序列化或重新应用修改 |
| `render_json_report()` | 复用正式 dict 投影生成确定的内存 JSON 字符串 | 不创建文件;默认摘要不等于公开安全日志 |
| `parse_json_report()` | 解析并校验正式 review JSON`full` 会验证哈希、阶段链和 Change 重放 | 不恢复 `ReviewDocument`,不接收路径 |
| `mdpolish-reviewer` | 在回环地址展示一个明确目录中的 `full` JSON | 只读,不运行 Pipeline,不提供业务审核流程 |
| `mdpolish.text_ranges` | 返回 CR/LF/CRLF 物理行的精确不可变原文范围 | 不解析 Markdown 块,不自动执行或修改文本 |
| `regex_replace()` | 把非空正则匹配转换为精确编辑 | 不提供规则注册表、配置加载或默认模式 |
| `mapped_line_join()` | 用精确、正则或可选本地词典规则合并跨行片段 | 无默认规则;代码、表格、未知结构和歧义失败关闭 |
@@ -38,15 +39,15 @@
不可移动的 tag
```bash
python -m pip install 'mdpolish @ git+https://github.com/Bepr4/mdpolish.git@v0.6.0'
python -m pip install 'mdpolish[lexical] @ git+https://github.com/Bepr4/mdpolish.git@v0.6.0'
python -m pip install 'mdpolish[frequency] @ git+https://github.com/Bepr4/mdpolish.git@v0.6.0'
python -m pip install 'mdpolish @ git+https://github.com/Bepr4/mdpolish.git@v0.7.0'
python -m pip install 'mdpolish[lexical] @ git+https://github.com/Bepr4/mdpolish.git@v0.7.0'
python -m pip install 'mdpolish[frequency] @ git+https://github.com/Bepr4/mdpolish.git@v0.7.0'
```
也可以安装同一 GitHub Release 附带的 wheel
```bash
python -m pip install 'mdpolish[lexical] @ https://github.com/Bepr4/mdpolish/releases/download/v0.6.0/mdpolish-0.6.0-py3-none-any.whl'
python -m pip install 'mdpolish[lexical] @ https://github.com/Bepr4/mdpolish/releases/download/v0.7.0/mdpolish-0.7.0-py3-none-any.whl'
```
Release 页面同时提供 wheel 的 SHA-256 校验值。仓库或 Release 如果是私有的,调用方需要自行配置 GitHub 访问权限;
@@ -57,7 +58,8 @@ python -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
```
核心运行时只依赖 Python 标准库,支持 Python 3.11 及以上版本。自动词典规则需要调用方明确安装并选择对应 extra:
核心和本地评审服务的 Python 运行时只依赖标准库,支持 Python 3.11 及以上版本。React 和 CodeMirror 已编译为 wheel
内的静态资源,使用评审器不需要 Node.js。自动词典规则需要调用方明确安装并选择对应 extra:
```bash
python -m pip install '/path/to/mdpolish[lexical]' # pyspellchecker + Pyphen
@@ -163,8 +165,9 @@ if result.status is RunStatus.SUCCESS and result.output_markdown is not None:
output_path.write_text(result.output_markdown, encoding="utf-8")
```
文件读取、输出命名、覆盖策略批处理和 CLI 都属于调用项目。`mdpolish` 可以生成通用的内存评审视图、机器投影、JSON
字符串与 Markdown 报告字符串,但不会自动保存它们,也不知道报告来自哪个文件。
清洗输入发现、输出命名、覆盖策略批处理属于调用项目。`mdpolish` 可以生成通用的内存评审视图、机器投影、JSON
字符串与 Markdown 报告字符串,但不会自动保存它们,也不知道报告来自哪个文件。唯一通用 CLI 是下面的只读评审器;它只
消费调用方已经保存的正式 JSON,不承担项目文件适配。
## 构建内存评审视图和报告
@@ -173,6 +176,7 @@ if result.status is RunStatus.SUCCESS and result.output_markdown is not None:
```python
from mdpolish.review import (
build_review_document,
parse_json_report,
render_json_report,
render_markdown_report,
review_document_to_dict,
@@ -185,11 +189,13 @@ review = build_review_document(input_markdown, result)
review_summary = review_document_to_dict(review)
report_json = render_json_report(review, detail="changes")
report_markdown = render_markdown_report(review)
parsed_report = parse_json_report(report_json, expected_detail="changes")
assert review.current_markdown == "an example text"
assert review_summary["schema_version"] == "1.0"
assert review_summary["detail"] == "summary"
assert report_json.startswith('{\n "schema_name": "mdpolish.review"')
assert parsed_report["status"] == "success"
assert report_markdown.startswith("# mdpolish review report\n")
```
@@ -210,9 +216,51 @@ Markdown reporter 会包含完整输入、当前全文、统一 diff 以及实
- `full`:再加入完整输入、当前全文和每个阶段的完整前后全文。
高 detail 可能还原敏感内容。即使 `summary` 不含正文,它仍然携带项目元数据和哈希,不能自动视为匿名或适合公开传播。
dict 和 JSON 都是单向派生视图,不用于恢复 `ReviewDocument` 或重新应用修改。完整 schema、坐标、哈希和兼容口径见
dict 和 JSON 都是单向派生视图,不用于恢复 `ReviewDocument` 或重新应用修改。`parse_json_report()` 返回新的普通 dict/list
容器;对 `full` 会验证全文哈希、阶段首尾,并用核心共用的精确编辑原语证明每个 stage after 确实由所列 Change 产生。
完整 schema、坐标、哈希和兼容口径见
[`review-projection-schema-v1.md`](research-wiki/reference/review-projection-schema-v1.md)。
## 使用本地评审页面
项目先把每份评审结果显式保存为直属的 `*.review.json`。页面需要完整输入、当前文本和所有 Modifier 阶段,因此必须使用
`detail="full"`
```python
from pathlib import Path
from mdpolish.review import build_review_document, render_json_report
review = build_review_document(input_markdown, result)
review_path = Path("artifacts/reviews/example.review.json")
review_path.parent.mkdir(parents=True, exist_ok=True)
review_path.write_text(
render_json_report(review, detail="full") + "\n",
encoding="utf-8",
)
```
文件路径、目录创建、权限、Git 忽略、覆盖和保留周期都属于项目。`full` JSON 重复包含完整文档和阶段全文,不能当作安全日志
或公开产物。
然后显式启动只读页面:
```bash
mdpolish-reviewer --review-dir artifacts/reviews
```
也可以使用等价模块入口:
```bash
python -m mdpolish.reviewer --review-dir artifacts/reviews
```
命令默认绑定 `127.0.0.1` 的系统空闲端口,并打印本机 URL。页面可以选择文档和 Modifier,比较完整 before/after,保留
零修改阶段,并通过 Change 列表跳转。服务只读取所给目录直属的 `*.review.json`,不递归、不跟随符号链接、不运行
Pipeline,也不渲染原文中的 Markdown、HTML、图片或脚本。文件名去掉 `.review.json` 后只是页面标签,不会被解释成输入
路径或业务文档 ID。完整操作与排障见
[`use-local-reviewer.md`](research-wiki/guides/use-local-reviewer.md)。
## 扫描精确物理行
项目 Modifier 如果需要识别独占行、检查相邻行或连同行尾删除一行,可以按原文 code point 范围扫描:
@@ -307,10 +355,14 @@ src/mdpolish/
├── modifier.py # 函数式 Modifier 契约
├── edits.py # 批次验证与原子应用
├── pipeline.py # 有序执行与最终稳定性复查
├── review.py # 可信评审视图、机器投影及内存 JSON/Markdown reporter
├── review.py # 可信评审视图、机器投影、JSON reader 及内存 reporter
├── _review_json.py # 正式 JSON 的私有解析和 full 语义校验
├── reviewer.py # 本地只读服务和公共 CLI
├── _reviewer_static/ # wheel 内的页面 bundle 与第三方许可证
├── regex.py # 正则修改器工厂
├── text_ranges.py # 公共精确物理行范围
└── modifiers/ # 少量项目无关的通用修改器
reviewer/ # React/TypeScript 源码、锁文件与合成界面测试
tests/ # 只使用虚构文本的核心与通用修改器测试
research-wiki/
├── design/ # 已批准决策及被冻结的历史记录
@@ -322,10 +374,10 @@ research-wiki/
## 当前不提供
- 文件适配器、公共 CLI、配置文件、profile 或批处理协议;
- 清洗文件适配器、清洗 CLI、配置文件、profile 或批处理协议;
- 自动规则发现、注册表或默认流水线;
- Markdown AST、完整 HTML parser 或必装的第三方运行依赖;
- artifact、自动保存的报告文件、正式 JSON Schema 文件、HTML reporter、Web/桌面评审器或项目审核流程;
- artifact、自动保存的报告文件、正式 JSON Schema 文件、远程/桌面评审器或项目审核流程;
- 任何业务项目的规则、固定参数、文档 ID、数据或验收统计。
公共边界与原因见
@@ -337,6 +389,8 @@ research-wiki/
查询口径见 [`review-projection-schema-v1.md`](research-wiki/reference/review-projection-schema-v1.md)。精确物理行公共接口的边界见
[`0013-public-physical-line-ranges.md`](research-wiki/design/0013-public-physical-line-ranges.md),稳定查询口径见
[`physical-line-ranges.md`](research-wiki/reference/physical-line-ranges.md)。旧 design 只保存历史决策,不代表当前交付能力。
项目无关本地评审器的批准边界见
[`0014-generic-local-reviewer.md`](research-wiki/design/0014-generic-local-reviewer.md)。
## 当前可用检查
@@ -349,6 +403,16 @@ research-wiki/
.venv/bin/python -m pip wheel . --no-deps --wheel-dir /tmp/mdpolish-wheel-check
```
修改前端源码或依赖时,再在 Node.js 24 环境中运行:
```bash
cd reviewer
nvm use 24
npm ci
npm run check
cd ..
```
检查本地变更:
```bash
@@ -356,27 +420,21 @@ git diff --check
git status --short
```
上述检查已于 2026-08-27 实际运行。Python 3.13.11 核心开发环境中 Ruff 和 mypy 通过pytest 为
`211 passed, 3 skipped`三个 skip 是该环境没有安装的真实 optional backend 路径,不计入发布验收
上述检查已于 2026-08-28 对 `v0.7.0` 实际运行。Python 3.13.11 开发环境中 Ruff 和 mypy 通过;未安装可选 backend 时
pytest 为 `330 passed, 3 skipped`三个 skip 分别对应真实 lexical 和 frequency backend 路径。
`mdpolish-0.4.0-py3-none-any.whl` 共 17 个文件,包含 `review.py``py.typed`,不包含 tests、Wiki、artifact、页面或
真实数据。安装全部 extras 后,Python 3.11.16 和 Python 3.13.11 环境分别得到 `214 passed`,没有 skip;仓库外消费者
smoke test 已覆盖核心正则、`pyspellchecker + Pyphen``wordfreq`、评审视图和 Markdown reporter。核心运行依赖仍只有
Python 标准库。Release wheel 的 SHA-256 是
`12e24863314958130ed082f78e89ab8bc0dad39a3848f2ae42e273d19a409693`
Node.js 24.19.0、npm 11.17.0 环境中,`npm ci` 未发现漏洞,ESLint、TypeScript、8 项 Vitest 和 Vite 生产构建通过。
生产 bundle 随 wheel 提供;普通使用者不需要 Node.js,页面运行时不从 CDN 下载资源。24 份生产依赖许可证文本和版本清单
已随 bundle 收录。
上述结果证明当前版本可安装并按合成契约运行,不代表任意词典阈值已经在真实业务语料上达到生产准确率。
同一个 Release wheel 在全新 Python 3.11.16 和 Python 3.13.11 环境中安装全部 extras 后,分别得到 `333 passed`,没有
skip;导入路径均确认来自环境的 `site-packages`。另一全新环境只安装 wheel、未安装第三方运行依赖,已实际完成 full JSON
生成、console script 与模块入口启动、集合/文档/Modifier API、UTF-16 定位和静态页面资源 smoke test。
`v0.6.0` 于 2026-08-28 在 Python 3.13.11 开发环境中实际得到:Ruff 和 mypy 通过,pytest 为
`290 passed, 3 skipped`;三个 skip 仍是没有安装的 optional backend。
`mdpolish-0.7.0-py3-none-any.whl` 压缩后为 315,279 bytes,共 49 个文件;解压后为 961,976 bytes,其中 29 个页面与许可证
文件为 742,678 bytes。相对未发布的 `0.6.1` 候选增加 32 个文件和 274,510 bytes 压缩体积。wheel 不包含 tests、Wiki、
`node_modules`、source map、真实报告、项目规则或数据。Release wheel 的 SHA-256 是
`b81a9a07fa0479854cd21d5a65f0f485cadf2031b5d731c3658ca10a1d72dc09`
Release wheel `mdpolish-0.6.0-py3-none-any.whl` 共 17 个文件,包含 `text_ranges.py``review.py``py.typed`,不包含
`_text_ranges.py`、tests、Wiki、报告或真实数据;在仓库外全新虚拟环境中无依赖安装后,版本、公共导入、精确混合行尾范围、
行尾集合、空行判断和 wheel 清单 smoke test 通过。Release wheel 的 SHA-256 是
`695502b1a443d4e98dbf63e8bdcee59452baea2185cb7e1e13160127f70c920f`
尚未发布的 `0.6.1` 候选修复了严格 HTML 表格扫描在未闭合或无法解析的外层 `<table>` 中继续处理完整内层表格的问题;
两个 HTML Modifier 的版本均为 `1.0.1`。2026-08-28 在 Python 3.13.11 开发环境中 Ruff 和 mypy 通过,pytest 为
`294 passed, 3 skipped`。安装候选 wheel 的全部 extras 后,Python 3.11.15 和 Python 3.13.11 环境分别得到
`297 passed`,没有 skip。候选 wheel 共 17 个文件并通过内容检查,SHA-256 是
`f628658a6d0b2860720e9425d190a477b78723dcda9b2d4b5a5e9f6e252faf07`
自动检查不能替代真实浏览器中的最终视觉、长文滚动和跨 Modifier 跳转人工确认。上述结果只证明当前版本可安装并按合成契约
运行,不代表任意清洗规则已经在真实业务语料上达到生产准确率。