# 数据与存储规范

> 版本：基线 1.0（2026-06-12）。依据：story-repo-spec 0.6 §11（缓存）、不变量 1/2、PRD §4-16（真源唯一）。

---

## 1. 真源原则

1.1 **文件即真相**：一本书的全部持久状态必须且只能存在于书仓库的 Markdown / YAML 源文件中（`定稿/`、`大纲/`、`文风/`）。禁止任何"只存在于数据库里"的状态。

1.2 多条记录必须**每条一个文件**（角色卡、伏笔、悬念、感情线、信息差各自成文件）；禁止大一统数据文件。自由文本归 Markdown 正文，front matter 只承载少量平铺短字段。

## 2. 唯一派生物：`.cache/index.db`

2.1 全系统唯一允许的持久派生物是书仓库内的 `.cache/index.db`，必须使用 Node 内置 `node:sqlite`，必须 gitignored。

2.2 该缓存必须**任何时刻可删**：删除后系统从源文件全量重建，所有查询照常回答。"删光 `.cache/` 全量重建"是 CI 验收项。

2.3 **重建器即格式的参考实现**：重建器能完整重建，即证明源文件格式自洽。修改任何源文件格式时必须同步修改重建器。

2.4 表名属机器域，用英文：`chapters`、`threads`、`secrets`、`entities`、`entity_aliases`、`fingerprints`。`entity_aliases` 是 `entities` 的别名索引表（alias → entity_id），供别名解析与唯一性校验。表设计必须支撑精准读取接口（PRD §3.6）的全部查询。

2.5 **派生统计必须确定性可重算**（M5.5 起，`fingerprints` 行与 meta 统计 key 如 `imagery_top`）：同一批源文件任何时候重算，结果必须逐字段一致——禁止时间戳、随机量、locale 相关排序（排序用码元序比较，禁止 `localeCompare`）；对象序列化的键顺序必须由固定的构造顺序保证。"删缓存重算后指纹逐字段一致"是测试断言项。写入方约定：基线段与近段章段重合时只落基线行（同主键两次 upsert 会翻转 `is_baseline`，见 cache-design §1.5）。

## 3. 禁止事项

3.1 禁止引入第二个数据库、向量库（语义检索为可选插件，永不做事实召回主路径）、常驻服务。

3.2 禁止任何形式的"投影/事件溯源"持久层（v6 教训：派生状态与作者手改冲突无解）。

3.3 禁止把缓存当真源读：业务逻辑必须能在"缓存刚被删光"的状态下正确工作（触发重建后照常返回）。

## 4. 系统写出的结构化内容（防呆方言，CI 强制）

4.1 front matter 与 `book.yaml` 必须**一律平铺**，禁止嵌套映射。

4.2 列表必须块格式（一行一条 `- 条目`），禁止行内 `[a, b]`。

4.3 凡可能被 YAML 误判类型的字符串值，写出时必须加引号。

4.4 缩进统一两空格；编码 UTF-8 无 BOM。

4.5 读取必须**容错**：遇到未知字段必须保留原样写回，禁止丢弃或报错。边界——"未知字段保留"仅限**平铺标量与平铺列表**；遇到作者写入的**嵌套映射**字段时不适用：嵌套映射违反 §4.1，防呆序列化器拒绝写出，读到嵌套字段视为格式错误，走修复确认（序0），不静默丢弃也不强行平铺写回。

## 5. 重建器事务性

5.1 全量重建必须在**单事务**内完成（`BEGIN` → DELETE 全表 → 扫描 INSERT → `COMMIT`），中途任何失败（含名册别名冲突等数据完整性违反）必须 `ROLLBACK`，禁止留半填库。

5.2 软失败不回滚：名册缺失或格式解析不动属"best-effort 跳过"，记 warning、不阻断重建、不回滚已写的 chapters/threads/secrets；只有别名冲突等硬错才回滚。名册非必需（角色卡可独立入 `entities`）。

5.3 缓存管理器禁止先删除旧 `index.db` 再重建。必须先在临时数据库中完成 DDL + 全量扫描，成功后再替换正式库；普通手动重建失败时保留上一份可用缓存，定稿后刷新失败时必须让旧缓存不可继续作为最新事实读取（删除/失效），避免 `next` 读旧章号重抄本章。

## 6. 待增量补充

- [ ] 各表的列定义与索引（实现 O4 精准读取接口时定稿）
- [ ] 重建器的增量更新策略（全量重建 vs 按 commit 增量）

## 7. 工作区暂存数据（自动模式批次，M6 起）

7.1 `工作区/待定稿/` 是机器域暂存区：`批次.json`/`定稿包.json` 是机器域 JSON，不受防呆方言约束；`草稿.md` 的 front matter 仍必须用防呆序列化器写出（作者可能打开看）。批次数据必须只经 `src/staging/index.js` 读写，消费点禁止绕过该模块直读批次文件。

7.2 staged 数据**禁止进入任何缓存表与 meta 统计**（`fingerprints` 与 `imagery_top` 只算定稿）：staged 章可能被打回，入表即破坏 §2.5 的确定性重算与 §2.2 的"删缓存重建一致"。叠加视图必须从工作区文件现读。

7.3 叠加消费点（备料/审稿输入/机检）必须以"批次存在"为总开关：无批次时零额外 IO、零行为变化（既有全量测试是该不变量的回归面）。

7.4 `批次.json` 损坏必须从章目录扫描重建元数据，恢复的章状态一律保守置"受影响"——宁可多一轮重审，禁止臆断为"待审收"。
