# Devlog · M2 IR 脊梁（版本化 + provenance + 质量评分骨架）

> 日期：2026-06-09 · 里程碑：[plans/m2-ir-spine.md](../plans/m2-ir-spine.md) · 状态：✅ 完成
> 结果：schema 版本化 + 文档级 provenance + 每 chunk confidence + `core::quality` 评分；确定性 100/100；零回归

---

## 1. 目标

把"确定 + 可溯源"两项胜负手落到 IR 上，且**便宜、早定**（roadmap §3"先定契约"）。这是系统最重要的长期接口（模块 1），改一次要稳。

## 2. 设计取舍

- **provenance 放文档级、不放每 chunk**：parser/version 对单解析器文档是冗余信息，存一份即可；元素级溯源用**已有的 `bbox+page`**（即引用锚点）。多来源融合（M7）再加元素级 source 覆盖。
- **per-chunk 只加 `confidence: f32`**：确定性路径恒 1.0，给未来 OCR/VLM 校正留低置信度钩子。
- **质量评分进 `core`**（格式无关），只**产分不行动**——路由 M7 才接。
- **serde `default`**：新字段 `#[serde(default)]`，旧 JSON 仍可载（前后兼容）。

## 3. 落点

| 文件 | 改动 |
|---|---|
| `core/ir.rs` | `SCHEMA_VERSION="0.2.0"`、`Provenance{schema_version,parser,parser_version}`、`TextChunk.confidence`、`Document.provenance: Option<Provenance>` |
| `core/quality.rs`（新） | `QualityReport`（pages/text_pages/coverage/total_chars/garbled_chars/garbled_ratio/flags）+ `QualityFlag`（ScannedNoText/PartialTextCoverage/HighGarble）+ `analyze(&Document)`；4 单测 |
| `core/lib.rs` | `pub mod quality` |
| `pdf/lib.rs` | `Document.provenance = Provenance::new("pdf", CARGO_PKG_VERSION)` |
| `pdf/interpreter.rs` | `TextChunk{ confidence: 1.0 }` |
| `cli/main.rs` | `--quality` flag：`QualityReport` JSON 打到 **stderr**（不污染 stdout 输出）|

## 4. 验证（对应 plan 验收）

- **provenance**：JSON 顶层 `{schema_version:"0.2.0", parser:"pdf", parser_version:"0.1.0"}`。
- **引用可定位率 100%**：每 text chunk 含 `bbox+page+confidence`。
- **确定性**：1901 解析 **100/100** 输出 JSON 逐字节同哈希（rayon `par_iter().collect()` 保序 + `sort_by_key`；font HashMap 不入输出序）。
- **质量评分**：`chinese_scan` coverage=0、flag `scanned_no_text`；`1901` coverage=1.0、garbled=0.0（佐证 M1 解码干净，无控制/替换字符）、44736 字符。
- **零回归**：lorem 387 / bialetti 3829 / 1901 10730 / 2408 14991，文本不变；clippy 零 warning；单测 core 6 + pdf 14 全过。

## 5. 边界与遗留

- **reading-order 异常分**留空（plan 已声明）：需要 M3 段落/版面信号后才有意义，届时补进 `QualityReport`。
- **元素级 source 覆盖**（某 chunk 来自不同解析器/模型）留到 M7 多来源融合。
- `garbled` 启发式只看控制/替换字符；真正的"乱码"（错误编码出的合法 Unicode）需更强信号，后续可加（如非常见字频）。

## 6. 对记分牌的影响（roadmap §6）

- **确定性**：100/100 逐字节一致——差异化记分牌达标。
- **引用可定位率**：100% chunk 带 bbox+page+confidence——M6 切块溯源的地基已就位。
- **质量分**：coverage/garbled 可计算，M7 路由的输入就绪。

## 7. 下一步

进入 **M3 版面可读**（段落聚合 + 页眉页脚）——直接抬 NID，并解决 M1 遗留的标题/正文词块可读性。
