## ADDED Requirements

### Requirement: 规则集驱动的章节检测

系统 SHALL 使用一个有序的「目录规则集」来逐行检测本地 TXT 的章节标题，取代单条硬编码正则。每条规则 MUST 至少包含名称、正则、是否为卷标志（`is_volume`）与启用开关。系统 SHALL 使用 `fancy-regex` 引擎以兼容含前后向断言的规则。

#### Scenario: 以「第N章」格式识别章节

- **WHEN** 解析一本章节标题为顶格 `第1章 罗峰`、`第2章 RR` …（阿拉伯数字 + 章）的 TXT
- **THEN** 系统识别出全部章节标题作为章节条目，且每条标题的字节偏移被正确记录

#### Scenario: 以「第N节」格式识别章节

- **WHEN** 解析一本章节单位为「节」（如 `第一节 纵身亡魔心仍不悔`，中文数字 + 节）的 TXT
- **THEN** 系统正确识别这些「节」为章节条目，而非将其漏掉

### Requirement: 误报抑制启发式

系统在判定某行是否为标题时 MUST 应用以下启发式：对该行先 `trim`（含全角空格 `　` 与 `\r`）、跳过空行、限制标题字符数不超过可配置上限（默认 35）、对计数词后缀做歧义排除（如 `第X部门/部队/部分/节课/集合`）。正文中包含「第…章/第…节」字样的行 MUST NOT 被误判为标题。

#### Scenario: 正文中的章节引用不被误判

- **WHEN** 正文段落里出现「违反了我们商家城的城规第三章第二十五条」「（详情见本卷第672章）」等引用
- **THEN** 这些行不会被识别为章节标题

#### Scenario: 超长行不被当作标题

- **WHEN** 某行包含「第N章」但其字符数超过标题长度上限
- **THEN** 该行被判定为正文而非标题

### Requirement: 分卷检测（卷优先于章）

系统 SHALL 识别卷标题（如 `第一卷 魔性不改`），并在匹配时**卷规则优先于章规则**。卷信息 MUST 以「平行元数据」形式产出（卷标题 + 其首章在扁平章节列表中的索引），且 MUST NOT 改变扁平章节列表的内容提取与导航语义。

#### Scenario: 识别多卷结构

- **WHEN** 解析一本含 `第一卷` … `第六卷` 共 6 个卷标题、章节单位为「节」的 TXT
- **THEN** 系统产出 6 条卷元数据，每条关联其首章索引，章节仍以单一扁平列表存在

#### Scenario: 无分卷的书

- **WHEN** 解析一本不含任何卷标题的 TXT
- **THEN** 卷元数据为空，章节列表与现有行为一致

### Requirement: 多规则竞争自适应选择

当多条章节规则同时可用时，系统 SHALL 统计各规则在样本中的有效命中数（仅计相邻命中间隔足够大的命中，以抑制连续误报刷分），并选择命中最多且分布均匀的规则作为该书的主章节规则。

#### Scenario: 自动适配不同计数词的书

- **WHEN** 同一规则集分别用于「章」格式与「节」格式的两本书
- **THEN** 系统各自选出能产出最合理目录的规则，两本书均被正确解析

### Requirement: 可配置的规则文件与内置默认

系统 SHALL 内置一套默认目录规则集（编译进二进制）作为兜底，并 SHALL 在 `~/.novel/toc_rules.json` 存在时加载用户自定义规则。规则文件格式 MUST 对齐 Legado `TxtTocRule` 结构（至少含 `name`、`rule`、`is_volume`、`enable`，可含 `example`、`serial_number`）。当配置文件缺失或解析失败时，系统 MUST 回退到内置默认规则而不崩溃。

#### Scenario: 无配置文件时使用内置默认

- **WHEN** `~/.novel/toc_rules.json` 不存在
- **THEN** 系统使用内置默认规则集完成检测

#### Scenario: 用户自定义规则生效

- **WHEN** 用户在 `~/.novel/toc_rules.json` 中新增一条启用的章节规则
- **THEN** 该规则参与检测，使原本无法识别的标题格式被正确解析

#### Scenario: 配置文件损坏时安全回退

- **WHEN** `~/.novel/toc_rules.json` 内容非法（无法解析）
- **THEN** 系统回退到内置默认规则并继续正常工作，不中断阅读

### Requirement: 章节检测验收基线

系统对 `test-novels/` 下的真值样本 MUST 满足：`吞噬星空(1-500章).txt` 解析为 500 章、0 卷；`《蛊真人》…txt` 解析为 6 卷、2334 章（节）。

#### Scenario: 真值样本回归

- **WHEN** 对两本真值样本运行检测引擎
- **THEN** 章节数与卷数与上述真值完全一致
