Files
mdpolish/research-wiki/explanation/review-projection.md
T

88 lines
4.8 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.
# 通用内存评审视图怎样解释一次清洗结果
## 1. 为什么不能直接把所有修改画在最终全文上
`TransformResult.changes` 中的每条范围都属于对应修改器执行前的快照。前一个修改器插入或删除文本后,后一个修改器看到的
位置已经不同;后续修改器也可能再次改写前一阶段生成的内容。因此,把所有 `Change.span` 直接当成最终全文坐标,会产生
错误跳转和错误归属。
当前实现要求调用方同时提供原始 Markdown 和已有 `TransformResult`
```text
原始 Markdown + TransformResult
build_review_document()
│ 验证并重放,不运行 Modifier
ReviewDocument
│ │
│ └── render_markdown_report() ──► 内存 Markdown 字符串
项目自己的界面或转换层
```
文件读取、保存位置、HTML 页面、权限和审核流程仍由调用项目决定。
## 2. 构建过程为什么可以失败关闭
`build_review_document()` 从调用方提供的原文开始,先验证输入和当前全文的 SHA-256,再按修改器位置重建批次。每个有实际
修改的阶段都会检查:
- `modifier_id`、版本和位置与记录的修改器元数据一致;
- `before_sha256``proposal_ref` 和每条编辑都指向当前阶段的修改前快照;
- proposal index、edit index 和报告顺序没有缺失、重复或被重排;
- 范围没有越界、重复或冲突,`before` 与原文精确一致;
- 应用后的全文和 `after_sha256` 一致。
核心执行与评审重放调用 `edits.py` 中同一个私有应用原语。排序键和字符串应用没有在评审模块复制一份;现有
`apply_modifier_batch()` 仍负责生成权威 `Change` 审计记录。
任一条件不成立都会抛出 `ReviewBuildError`。错误只说明契约类别和修改器位置,不包含输入、`before``after` 或上下文
片段。构建函数不会通过搜索或 diff 猜测缺失信息,也不会重新调用修改器。
## 3. `stages_complete` 表示什么
`ErrorStage.PREFLIGHT` 用来区分“修改器尚未开始执行”和“已经进入 transform 后失败”。阶段边界如下:
| 结果 | `ReviewStage` 范围 | `stages_complete` |
| --- | --- | --- |
| `success` | 全部修改器,包括零修改阶段 | `True` |
| `unstable` | 全部 transform 阶段;残留候选不应用 | `True` |
| 只有 final review 错误的 `failed` | 全部 transform 阶段 | `True` |
| preflight 失败 | 空 | `False` |
| 修改器位置 `p` 的 transform 失败 | 只包含 `0..p-1` | `False` |
已经返回 proposals 但元数据复核、批次验证或应用失败的修改器,不会被伪装成零修改阶段。它的修改前全文就是
`ReviewDocument.current_markdown`,失败原因保存在 `errors`;失败位置之后的修改器没有运行,也没有阶段。
`stages_complete=True` 只证明 transform 阶段完整,不表示 final review 成功,更不把 `failed``unstable` 提升成成功
输出。
## 4. 位置口径
`ReviewLocation` 指向 `Change.span.start`,并相对于所属 `ReviewStage.before_markdown` 计算。行和列都是 1-based,列宽使用
Python Unicode 码点:
- BOM 和组合字符各占一个码点;
- 补充平面字符占一个码点,不按 UTF-16 的两个 code unit 计算;
- LF、CRLF 和 CR 都是物理换行,CRLF 是一个换行边界但占两个原始码点;
- 计算前不做 Unicode 或换行规范化。
权威范围仍然是 Python 半开区间 `Change.span``ReviewLocation` 只供人阅读,不用于重新应用修改,也不是 JavaScript、LSP
或终端显示列坐标。
## 5. Markdown reporter 的边界
`render_markdown_report()` 是纯函数,只返回 Markdown 源码字符串。报告包含状态、哈希、修改器顺序、完整输入、完整当前
全文、带物理换行标记的统一 diff,以及按 `ReviewStage` 排列的实际修改。`failed``unstable` 的 diff 文件标签带有
`.partial.md`,避免把部分结果误认成正式输出。
完整 residual proposal 仍保留在 `ReviewDocument` 中。reporter 默认最多列出前 20 条,只显示修改器身份、位置、原因、
span 和修改前后长度,不重复输出 `expected_text``replacement` 或正文摘要。调用方可以把限额设为非负整数,`0` 表示
只显示总数。
报告有意包含完整文档、实际修改的 `before` / `after` 和 diff,可能还原敏感内容。库不会自动打印、保存、上传或缓存
报告;持久化后的路径、访问权限、脱敏和保留周期属于调用项目。每个阶段保存完整前后快照,当前实现优先保证可复核性,
没有声称适合无限长度文档或无限修改器链。