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

4.8 KiB
Raw Blame History

通用内存评审视图怎样解释一次清洗结果

1. 为什么不能直接把所有修改画在最终全文上

TransformResult.changes 中的每条范围都属于对应修改器执行前的快照。前一个修改器插入或删除文本后,后一个修改器看到的 位置已经不同;后续修改器也可能再次改写前一阶段生成的内容。因此,把所有 Change.span 直接当成最终全文坐标,会产生 错误跳转和错误归属。

当前实现要求调用方同时提供原始 Markdown 和已有 TransformResult

原始 Markdown + TransformResult
              │
              ▼
   build_review_document()
              │  验证并重放,不运行 Modifier
              ▼
        ReviewDocument
          │          │
          │          └── render_markdown_report() ──► 内存 Markdown 字符串
          ▼
    项目自己的界面或转换层

文件读取、保存位置、HTML 页面、权限和审核流程仍由调用项目决定。

2. 构建过程为什么可以失败关闭

build_review_document() 从调用方提供的原文开始,先验证输入和当前全文的 SHA-256,再按修改器位置重建批次。每个有实际 修改的阶段都会检查:

  • modifier_id、版本和位置与记录的修改器元数据一致;
  • before_sha256proposal_ref 和每条编辑都指向当前阶段的修改前快照;
  • proposal index、edit index 和报告顺序没有缺失、重复或被重排;
  • 范围没有越界、重复或冲突,before 与原文精确一致;
  • 应用后的全文和 after_sha256 一致。

核心执行与评审重放调用 edits.py 中同一个私有应用原语。排序键和字符串应用没有在评审模块复制一份;现有 apply_modifier_batch() 仍负责生成权威 Change 审计记录。

任一条件不成立都会抛出 ReviewBuildError。错误只说明契约类别和修改器位置,不包含输入、beforeafter 或上下文 片段。构建函数不会通过搜索或 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 成功,更不把 failedunstable 提升成成功 输出。

4. 位置口径

ReviewLocation 指向 Change.span.start,并相对于所属 ReviewStage.before_markdown 计算。行和列都是 1-based,列宽使用 Python Unicode 码点:

  • BOM 和组合字符各占一个码点;
  • 补充平面字符占一个码点,不按 UTF-16 的两个 code unit 计算;
  • LF、CRLF 和 CR 都是物理换行,CRLF 是一个换行边界但占两个原始码点;
  • 计算前不做 Unicode 或换行规范化。

权威范围仍然是 Python 半开区间 Change.spanReviewLocation 只供人阅读,不用于重新应用修改,也不是 JavaScript、LSP 或终端显示列坐标。

5. Markdown reporter 的边界

render_markdown_report() 是纯函数,只返回 Markdown 源码字符串。报告包含状态、哈希、修改器顺序、完整输入、完整当前 全文、带物理换行标记的统一 diff,以及按 ReviewStage 排列的实际修改。failedunstable 的 diff 文件标签带有 .partial.md,避免把部分结果误认成正式输出。

完整 residual proposal 仍保留在 ReviewDocument 中。reporter 默认最多列出前 20 条,只显示修改器身份、位置、原因、 span 和修改前后长度,不重复输出 expected_textreplacement 或正文摘要。调用方可以把限额设为非负整数,0 表示 只显示总数。

报告有意包含完整文档、实际修改的 before / after 和 diff,可能还原敏感内容。库不会自动打印、保存、上传或缓存 报告;持久化后的路径、访问权限、脱敏和保留周期属于调用项目。每个阶段保存完整前后快照,当前实现优先保证可复核性, 没有声称适合无限长度文档或无限修改器链。