Просмотр исходного кода

docs(api-v13): related_paragraphs 设计文档按第一批实施结果勘误

第一批实施(scripts/related/ 工具链 + related_paragraphs_v1)中查实七处与本文档
不符或本文档未记录的事实,正文就地改正,细节与证据记入新增的 §9。

三处原判断有误:
- cs6_para.csv 并未丢失,仍在 clove 仓库(523283 行)。它不能当生成源(含全部历史
  错误),但是逐段落 diff 基线,也是 book 129 的唯一回填源——该本不需要 LLM
- E8 判据过宽:按 cs 值种类判会把章回绕误报成污染(book 152 有 516 个标记却只 24 个
  cs 值,那是 22 次回绕)。真污染只有 book 207 一段 1499 行
- {name}_{N} 是章标记,mūla 与义注文件同形同义,都不产生 cs 值;义注段挂 mūla 名下
  靠的是 paraN_{mula} 后缀。序言由 {book}_{N>0} 结束而非由 cs 标记结束,序言段内出现
  paraN_{mula} 是正常体例

四处新发现:
- 两类未记录的标记形态:倒序区间 3 行(高位笔误,低位可还原)、多级章标记 247 行
  (an5_1_1 型,义注与 mūla 共用编号,是跨侧章界对齐的现成抓手)
- 段落全集是 pali_texts(523284 段)而非 wbw_templates(516113 段)
- book 107 整本属 kn10(标题证伪 therī 之说);book 177 内含四部书,仅首部为 abhi8
- book 143/144 的 kn10 错名靠 wbw 的 book_tag 自动修复,无需人工

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcQqZgKWhw5HKRj2GDn21h
visuddhinanda 1 месяц назад
Родитель
Сommit
7d35946357
1 измененных файлов с 151 добавлено и 16 удалено
  1. 151 16
      api-v13/documents/related-paragraphs-redesign.md

+ 151 - 16
api-v13/documents/related-paragraphs-redesign.md

@@ -1,9 +1,13 @@
 # related_paragraphs 段落关联体系 修复设计文档
 
-> 状态:已评审;2026-03 对当前库(visuddhinanda_20260311)全量实测复核后修订,待实施
+> 状态:**第一批已实施**(2026-09-09,导出器 + 检测器落地于 `api-v13/scripts/related/`,
+> 第一版数据在影子表 `related_paragraphs_v1`,生产表未动);章回绕与 LLM 补齐两批待做。
 > 背景:2025-08 数据审计发现 related_paragraphs 存在多类系统性数据错误。
-> 原始生成链路(VRI html 锚点 → cs6_para.csv → Laravel 导入)中的 csv 文件已丢失,
-> 决定以 wbw_templates 为唯一数据源重新导出第一版数据,再用补丁文件修正历史问题。
+> 原始生成链路是 VRI html 锚点 → cs6_para.csv → Laravel 导入;决定以 wbw_templates
+> 为生成源重新导出第一版数据,再用补丁文件修正历史问题。
+>
+> **实施复核勘误见 §9**——其中 §6.1 关于 csv 已丢失的判断、§4.3 E8 的判据、
+> §6.2 关于义注 `{mula}_{cs}` 标记的语义三处与实测不符,正文已就地改正。
 
 ---
 
@@ -40,9 +44,11 @@ wbw_templates                (数据源头,逐词表)
   │                 按历史形态保留备注,导出器以实测词表为准)
   │   区间标记:      para151-152 / para151-152_sn4  (1 个 vri 段 ↔ 多个 cs,展开多行)
   │   缩写区间:      para292-3  = 292-293(M 补齐 N 的前缀)
-  │   义注文件:      dn1_0 / dn1_1({mula}_{cs},义注段挂 mūla 名下)
-  │   章节标记:      kn10_2 / an1_5(mūla 文件内的章界)
-  ▼  (旧链路经 cs6_para.csv ——已丢失,废弃)
+  │   章节标记:      dn1_0 / dn1_1 / kn10_2 / an5_1_1({book}_{章号},可多级)
+  │                 实测:mūla 与义注文件里形态相同,都是章界而非 cs 值;
+  │                 唯 _0 特殊,表示义注序言(→ {book}_A)。见 §9 勘误 3
+  │   书界标记:      dn1 / an3(纯书名,文件内的书切换点,93 行)
+  ▼  (旧链路经 cs6_para.csv ——仍存于 clove 仓库,含全部历史错误,只作基线不作源)
 related_paragraphs           (本表,631,838 行)
   book, para                 VRI 文件号 1-217 + 段落号
   book_id ──────────────────▶ book_titles.sn
@@ -85,7 +91,7 @@ pali_texts                   (全文)
 - 正常情况:一个 book_id 内只有一个 book_name 且 cs_para 单调递增(如 book=93)。
   现发现部分书不是:一个 book_id 内出现重复的 cs_para
 - related_paragraphs 数据当年从 wbw_templates(进而来自 VRI html 锚点)导入,
-  具体过程已不可考,cs6_para.csv 原始文件已丢失
+  具体过程已不可考,但 cs6_para.csv 本身仍在(见 §9),可用作逐段落比对基线
 
 ### 4.2 审计确认的正确性判据(修正后的业务模型)
 
@@ -108,8 +114,8 @@ pali_texts                   (全文)
 | E5 | book_id=0 未赋值 | 354 行(201 本各 1-3 行);book 189 审计时整本 1,572 行为 0,现已回填(1,570 行 book_id=230,仅书前页 2 行为 0) | 各文件 para 1-2 书前页(可接受)。sn=280/281 仍无 book_id 行:book 139 para≥925 整段归入 sn 157、book 214 para≥2162 整段归入 sn 276,随 book_id 层重跑修复。另 book_titles sn=230 title 误写 sādhuvilāsinī(与 sn=229 重名,实际应为 sīlakkhandhavaggaabhinavaṭīkā,已由 pali_texts level-1 标题证实) |
 | E6 | 覆盖缺口 | 3,466 段无行 | 主体为缩写区间丢失(见 E7),其余为 wbw_templates 整段缺失 |
 | E7 | **缩写区间丢失**(本次审计新发现) | 1,517 个标记段落 / 44 本:其中 1,292 段(85.2%)无 related 行,其余 225 段带行但 cs 全为乱码值(与 E1 同根) | VRI 缩写语法 `para292-3`(=292-293)旧生成器不识别:多数直接跳过,少数误解析为废值(如 `para32-3`→11,749、`para15-8`→44,058) |
-| E8 | **书边界污染平铺** | kaṅkhāvitaraṇī 义注 1,499 行 cs 恒 75、ṭīkā 669 行 cs 恒 0 等 | 换书(book_id 切换)后无标记,旧生成器无限沿用上一个 cs 值 |
-| E9 | 无标记书 | 16 本(book 8,15,16,25,37,39-42,44,45,47,48,56,61,129)related 有行但 wbw_templates 零标记 | VRI 源文件无锚点。其中 book 129(theragāthā-aṭṭhakathā 后半)等存在真实注释关系,需外部手段补齐 |
+| E8 | **书边界污染平铺** | 判据收窄后实测**仅 1 段**:book 207 / book_id 259 kaṅkhāvitaraṇī 义注 1,499 行 cs 恒 75(见 §9 勘误 2) | 换书(book_id 切换)后无标记,旧生成器无限沿用上一个 cs 值 |
+| E9 | 无标记书 | 16 本(book 8,15,16,25,37,39-42,44,45,47,48,56,61,129)related 有行但 wbw_templates 零标记 | VRI 源文件无锚点。其中 book 129(theragāthā-aṭṭhakathā 后半)存在真实注释关系——外部手段已找到:cs6_para.csv 里它有 6,580 非零行,直接回填即可,不需 LLM。其余 15 本 csv 里也是全零,源头就没有 |
 | E10 | 自造名体系 | NK(book 1,namakkāra 自注释对)、subo(book 10↔11)、dict(book 21↔9) | 非 SC 体系书对的自造 album 名,连接各自 mūla↔注释。架构正确(与 dn1/dn1_A 同构),保留不动;仅其中的乱码/缩写问题随全局规则修复 |
 
 ## 5. 全库书况初步分析表
@@ -122,7 +128,8 @@ pali_texts                   (全文)
 - **缩写丢失 n 处**:缩写区间标记段落无行 → 新导出器自动修复
 - **章回绕 n 次**:cs 重置计数 → 章后缀方案处理(注:含少量合法多轮注释结构
   如 NK 的 ṭīkā 两轮注释,处理时用标题层级甄别)
-- **无标记污染**:cs 值种类极少但行数巨大(书边界沿用平铺)→ 导出器留空 + LLM 补丁
+- **无标记污染**:整段无 cs 标记却被写进非零 cs(书边界沿用平铺)→ 导出器输出 cs=0 + LLM 补丁
+  (注:表内按旧判据「cs 值种类极少」标注的几本实为章回绕误判,见 §9 勘误 2)
 - **全书无标记**:wbw_templates 无任何 para 标记但 related 有行 → LLM 补丁或维持现状
 - **无 book_id 行**:sn 存在但无任何 book_id 归属行(行均被归入同文件前一册)
 
@@ -433,7 +440,11 @@ wbw_templates(唯一数据源,含全部 .ctl. 标记)
 ```
 
 关键决策记录:
-- **cs6_para.csv 废弃**,不再寻找;一切从 wbw_templates 重放
+- **cs6_para.csv 不作生成源**:它是现表的来源、含全部历史错误,一切从 wbw_templates
+  重放。但它并未丢失(`github.com/iapt-platform/clove/pali_title/cs6_para.csv`,523,283 行),
+  已归档为逐段落 diff 基线,并作为 book 129 的唯一回填源(见 §9)
+- **段落全集取 pali_texts 而非 wbw_templates**:pali_texts 523,284 段是严格超集,
+  wbw 少的 7,171 段散在 21 本里;wbw 只负责提供标记
 - **维持 VRI 编号方案**(章内局部编号),SC 数据不采用(SC 层级树与加后缀方案无本质
   区别,且 SC 为 Mahāsaṅgīti 独立校勘本,文本与 VRI 不对齐,无法直接落到 VRI 段落)
 - **回绕处理(分两类)**:
@@ -462,6 +473,7 @@ wbw_templates(唯一数据源,含全部 .ctl. 标记)
 | `paraN-M`(M 位数<N,补齐后>N) | 缩写区间,前缀补齐展开(para292-3→292,293) |
 | `paraN-M_book`(缩写+后缀组合,实测 989 行,如 `para1008-9_sn5`) | 先按缩写规则展开 N..M,再以后缀定 book_name |
 | `paraN-M-K...` | 链式首尾法展开 N..tail(para292-3-6→292..296);实测仅 4 行,旧数据已正确展开(book 189 para 827 → 292-296) |
+| `paraN-M`(M < N 且位数相同,全库 3 行) | 倒序区间=高位笔误,丢弃右端高位、只用低位重新前缀补齐(`para504-407`→504-507、`para706-608`→706-708),并记 issue 人工复核。见 §9 勘误 4 |
 | `paraN-`(M 空,全库仅 1 处:book 11 para 1577) | 留空 + issue(`truncated_marker`),人工定 |
 | 解析值超值域保护阈值 | 拒绝输出 + issue(`cs_out_of_range`),防乱码 |
 | 页码/卷标 `P/M/V/T/O` × 0-5(实测 26 家族 165,907 行) | 忽略,本轮不处理 |
@@ -472,7 +484,7 @@ wbw_templates(唯一数据源,含全部 .ctl. 标记)
 | 输入 | 处理 |
 |---|---|
 | 延续段(同书内有前一标记) | 沿用;区间沿用则整区间展开(含巨区间 844 行场景) |
-| 书边界(book_id 切换)后的无标记段 | **留空 + issue(`no_marker_after_book_switch`)** ⭐ 防污染核心规则 |
+| 书边界(book_id 切换)后的无标记段 | **输出 cs=0 + issue(`segment_without_markers`)** ⭐ 防污染核心规则。实测不能整段不输出:这些段落多是 cs=0 占位行(E4 的无注释体系书、义注序言、书前页),删掉会白丢 20,433 段覆盖,而 `index()` 取锚点要求 `cs_para > 0`,cs=0 行不产生任何配对 |
 | 文件开头段(para 1-2) | cs=0、book_id=0(维持现状语义) |
 | wbw_templates 整段无行 | 自然无输出 + issue(`missing_wbw`) |
 
@@ -482,9 +494,9 @@ wbw_templates(唯一数据源,含全部 .ctl. 标记)
 |---|---|
 | `paraN_book` 后缀 | book_name = 后缀 |
 | 无后缀标记 | 继承当前 book_name;文件开头继承不到 → 留空 + issue |
-| `{mula}_{0}`(义注文件) | 进入 `{mula}_A` 序言模式(重现 dn1_A 正确先例) |
-| `{mula}_{N>0}`(义注文件) | 退出序言模式,book_name=mūla 名 |
-| `{book}_{N}`(mūla 文件) | 章切换事件,触发章后缀上下文 |
+| `{book}_{0}` | 进入 `{book}_A` 序言模式(重现 dn1_A 正确先例) |
+| `{book}_{N>0}` | 退出序言模式;章切换事件,触发章后缀上下文。**不产生 cs 值**——mūla 与义注文件同形同义,见 §9 勘误 3 |
+| 序言段内出现 `paraN_{mula}` 后缀 | 只赋 cs、不夺名,book_name 保持 `{book}_A`。序言里带这种标记是正常体例(book 130 的 `mn1_0` 序言内就有 `para1_mn1`),序言只由 `{book}_{N>0}` 结束 |
 | NK/subo/dict 等自造名 | 由书级配置表提供(保兼容,不重新发明);books 107/143/144 的 kn10 家族导出名同样由书级配置表决定(补丁 old 值必须与之匹配,见 §6.5) |
 
 文件类型(义注 vs mūla)用 tag(aṭṭhakathā/ṭīkā vs mūla/pāḷi)消解
@@ -624,6 +636,129 @@ saṅghādisesa 从 1 重计),修复时按组加后缀(vin6_pr1 型),
 - 标记词表:缩写+后缀组合 `para1008-9_sn5` 型 989 行;链式标记 4 行(旧数据已正确
   展开);截断 `para179-` 仅 book 11 para 1577 一处;页码标记 26 家族 165,907 行
   (本轮忽略);纯书名标记 93 行(书上下文事件);巨区间 para308-1151 现为 844 行。
-- 基础环境:cs6_para.csv 确认已不存在(storage/resources/pali_title 目录缺失);
+- 基础环境:本地 storage/resources/pali_title 目录缺失,但 csv 在 clove 仓库里(见 §9);
   281 个 sn 与 book_titles 一致;tags 的 8 个类型名齐备,文件类型消歧可用;
   新导出器 command 尚未实现,本文档仍处于待实施状态。
+
+---
+
+## 9. 实施复核勘误与新发现(2026-09-09,第一批实施)
+
+工具链落地于 `api-v13/scripts/related/`,第一版数据在影子表 `related_paragraphs_v1`
+(638,076 行),生产表已备份为 `related_paragraphs_bak_20260909` 且未改动。
+以下是实施中与本文档原判断不符、或本文档未记录的事实,正文相应处已就地改正。
+
+### 勘误 1:cs6_para.csv 并未丢失
+
+在 `github.com/iapt-platform/clove/pali_title/cs6_para.csv`,523,283 行,可直接取得。
+本地 `storage/resources/pali_title` 目录确实缺失,§8 据此推断"文件已不存在"是过头了。
+
+它仍不能当生成源——它是现表的来源,含全部历史错误(`462580` 废值、`kn10_A`/`kn10_B`
+错名一个不少)。但两个用途不可替代:
+
+- **逐段落 diff 基线**:它每行一个段落带 `begin,end`,正是重放结果的天然对照
+- **book 129 的唯一回填源**:逐本比对「csv 非零行 vs wbw 标记数」,全库只有 book 129
+  是"csv 有 6,580 非零行、wbw 零标记"。E9 其余 15 本 csv 里也是全零,源头就没有。
+  也就是说这本不需要 LLM,直接回填即可
+
+另:`para504-407` 丢段的完整链路查清了——csv 里原样写着 `begin=504,end=407`,
+旧 Laravel 命令的 `for ($i = $begin; $i <= $end; $i++)` 一圈没进。**丢段发生在导入
+环节的静默空转,不在生成环节**。
+
+### 勘误 2:E8 判据过宽,真污染只有 1 段
+
+按"cs 值种类极少但行数巨大"判会把**章回绕误报成污染**:book 152 有 516 个 cs 标记却
+只有 24 个不同 cs 值,那是 22 次回绕造成的,不是平铺。
+
+污染的准确签名是「整段一个 cs 标记都没有,却被写进了非零 cs」——那个值只能是从上一本
+沿用下来的。按此判,全库只有 **book 207 / book_id 259 kaṅkhāvitaraṇī 一段,1,499 行
+恒 cs=75**。原列的其余几组:
+
+- book 212/273(669 行)、book 180/213(1,219 行)、book 209/261(163 行)cs 恒为 **0**
+  ——0 是"未赋值"不是编造值,不算污染
+- book 152/46/116/154/204 是章回绕(E2),归 E2 处理
+
+### 勘误 3:`{name}_{N}` 是章标记,mūla 与义注文件同形同义
+
+§2 原写"义注文件 `dn1_0 / dn1_1` 是 `{mula}_{cs}`,义注段挂 mūla 名下"。实测不是:
+
+- book 93(mūla)有 `dn1_1..dn1_13`,book 103(义注)有 `dn1_0..dn1_13`,**形态与语义都相同**,
+  都是章界,都不产生 cs 值
+- book 103 para 1460 的 `dn1_12` 并没有让该段 cs=12——该段 cs=499,来自 para 标记
+
+义注段挂 mūla 名下靠的是 **`paraN_{mula}` 后缀**(如 `para4_dn1`),不是章标记。
+唯一特殊的是 `_0`:它表示义注序言(Ganthārambhakathā),进入 `{book}_A` 模式。
+
+配套的两条实测语义:
+
+- **序言由 `{book}_{N>0}` 结束,不由 cs 标记结束**。book 103 的 `dn1_A` 止于 `dn1_1`@199,
+  与旧表的 198/199 分界严丝合缝
+- **序言段内出现 `paraN_{mula}` 是正常体例**。book 130 的 `mn1_0` 序言(paras 5-46)里就有
+  `para1_mn1`@40,book 192 更有一长串。这些后缀只赋 cs、不夺名,段落仍归 `{book}_A`
+
+### 勘误 4:两类本文档未记录的标记形态
+
+全库 330,267 个锚点(`type='.ctl.' and style='#a#'`)经解析器 100% 归类、零 unknown:
+page 167,647 / single 156,919 / interval 4,604 / chapter 1,003 / book_tag 93 / truncated 1。
+其中两类原文档没有:
+
+- **倒序区间 3 行**:`para504-407`(book 103 para 1464)、`para706-608`(book 176 para 753)。
+  是高位笔误,低位正确:前者前邻 502-503、后邻 508,真值 504–507;后者前邻 703-705、
+  后邻 709,真值 706–708。规则是丢弃右端高位、只用低位重新前缀补齐
+- **多级章标记 247 行 / 13 本**:`an5_1_1` 型。义注书 100-102 与 mūla 书 82-92 **共用同一套
+  编号**,这是 §6.1 跨侧章界对齐现成的抓手,做章后缀时应优先用它而非推标题
+
+### 新发现 5:段落全集是 pali_texts 不是 wbw_templates
+
+pali_texts 523,284 段是严格超集(正是 csv 的行数),wbw_templates 只有 516,113 段,
+少的 7,171 段散在 21 本里。按 wbw 取段落全集会白丢这些段落的行。wbw 只负责提供标记。
+
+### 新发现 6:两处书名归属错误
+
+- **book 107(apadāna-aṭṭhakathā)整本属 kn10**。旧表切成 `kn10_A`(para 3-2141) +
+  `kn10_B`(2142-3875) 并称后者对应 therī——标题证伪:para 2146 的标题是
+  `(Dutiyo bhāgo) Therāpadānaṃ`,那是 therāpadāna 的**第二卷**;全书只有一个 level-1
+  标题「Apadāna-aṭṭhakathā」,vagga 编到 56(Yasavaggo)也正是 therāpadāna 的范围,
+  书内无任何 therī 标题。therīapadāna 另在 book 144 para 6534 起。已记入
+  `book_config.json` 的 `overrides`
+- **book 177 内含四部书**:abhidhammāvatāro(sn 205)、nāmarūpaparicchedo(206)、
+  paramatthavinicchayo(207)、saccasaṅkhepo(208)。只有第一部是 `abhi8`,
+  后三部本就没有 SC 书名。生成书级配置表时若过滤掉空书名,`abhi8` 会越过书界铺满
+  整个文件,把 10,695 行错配进 abhi8 的注释链——空书名必须同样成段
+
+### 新发现 7:book 143/144 的 kn10 错名靠 wbw 自动修复
+
+E3 原以为需要人工改名。实测 wbw 里 book 143 有 `kn10@3`、book 144 有 `kn10@3` 与
+`kn11@6532`,书界写得清清楚楚,按 wbw 重放即自动归位。需人工的只有没有 book_tag 的
+book 107(见新发现 6)。
+
+### 第一批成绩
+
+| 探测器 | 旧表 | v1 |
+|---|---|---|
+| E1 cs 乱码 | 1,242 行 | **0** |
+| E3 kn10 | 0 行 | **25,506 行**(kn10_A/B 清零) |
+| E6 覆盖缺口 | 3,464 段 | **1 段**(仅 book 11 那个截断标记) |
+| E7 缩写区间丢失 | 1,292 段无行 + 225 段废值 | **0 + 0** |
+| E8 污染平铺 | 1,499 行 | **0** |
+| 区间展开不符 | 1,611 | **0** |
+| 镜像判据 | 559/1289/524/918 | **保持** |
+| 零错误信号的书 | 128 本 | **148 本** |
+
+与旧表逐段落 91.8% 相同(480,290 / 523,284 段)。差异全部归因:
+`only_in_old` 1 段(截断标记)、`only_in_new` 3,466 段(区间展开补回,与旧表覆盖缺口
+数吻合)、`cs_changed` 10,371 段(8,600 归零防污染 + 528 新赋值 + **1,290 两侧都非零而
+边界不同**)、`name_changed` 29,156 段(29,146 是 kn10 家族修复,余 10 段是各文件
+book_tag 所在段本身)。
+
+那 1,290 段是唯一需要人工判断的部分(占全库 0.25%)。已抽查 book 110 para 993-999:
+旧表把 cs=5 的边界提前了 7 段,而该区间内除页码外无任何标记,`para5` 标记在 para 1000,
+新值(延续 cs=4 至 999)有据、旧值无据。
+
+### 遗留
+
+1. E2 章回绕 677 处未处理(本批不做,先让确定性规则跑干净)
+2. book 129 的 6,605 段现为 cs=0 占位,待用 csv 回填
+3. 20 段 `segment_without_markers` 已输出 cs=0 占位,待 LLM 归属
+4. book 11 para 1577 的 `para179-` 截断标记待人工定
+5. 上述 1,290 段边界差异待抽样复核