# 错误处理规范

> 版本：基线 1.0（2026-06-12）。依据：PRD §1.4 产品原则 3/4、§3.5 状态机、§5 非功能需求（健壮性）；story-repo-spec 0.6 不变量 4、§10。

---

## 1. 总原则

1.1 **永不带堆栈崩溃**：任何面向作者的执行路径都禁止抛出未捕获异常。所有可预见的失败必须落入"修复确认"或人话提示兜底。

1.2 **宁停勿崩**：无法安全继续时必须停下并说明状态，禁止带着不一致状态继续执行。

1.3 **可靠性来自自愈，不来自门禁**：能自动修复的先修复再报告；hook 语义必须是 ask，禁止 deny（v6 #113 教训）。

1.4 **系统适应作者，不报错拒绝**：作者手改源文件是合法操作。检测到未入账手改必须提议补登，禁止报错、禁止拒绝启动。

## 2. 错误分级与处理路径

| 级别 | 示例 | 必须采取的处理 |
|---|---|---|
| 可自愈 | `books.jsonl` 缺失/损坏；全角标点等结构性 YAML 错误 | 自动修复（扫描重建 / 预修复），只报不问 |
| 需作者确认 | 源文件解析失败且涉及内容语义 | 修复确认：定位到行、提议保留作者意图的修复、作者确认后执行 |
| 需作者决策 | git 异常（半提交/冲突/锁文件/网盘冲突副本） | 启动时 git 健康检查捕获，每种配自动修复或人话指引 |
| 环境性 | Node 版本不足、不在工作目录启动 | 人话提示该做什么（升级 Node / 回工作目录），禁止英文报错 |

## 3. 原子性

3.1 定稿必须原子：一次 git commit 要么完成，要么工作区原样保留，禁止中间态。所有多文件写入操作必须遵循同一模式——先全部准备好，再一次提交。

3.2 中断恢复：状态机启动时必须能识别"工作区有未完成流程"并从中断的阶段继续，禁止要求作者重来。

3.3 多文件写入的原子边界（实现在 `src/storage/atomic.js` 的 `writeAtomicBatch`）：
- **定稿/建书/卷复盘/修复落盘**等多文件写入：全部先写 `.tmp` 再 `rename`，任一失败删全部 `.tmp`、原文件不动。"要么全成要么原样"。
- **审稿报告**（事实审查/编辑审/审稿单 + 原始 raw）：同上原子批。
- **缓存重建**多表写入：走数据库事务（`BEGIN/COMMIT/ROLLBACK`，见数据规范 §5），不走文件 rename。
- 豁免：工作区内纯临时单文件草稿（如 `细纲.md`）无原子要求。

3.4 定稿回滚范围必须**收窄到本次写入文件集合**（`written`），逐文件 `restore`（已跟踪）+ `clean`（未跟踪新文件），禁止对整棵 `定稿/`+`大纲/` 子树 `restore`/`clean`，以免误伤同子树其他章的未登记手改。

3.5 同章重写导致旧文件名变化时，旧章文件的删除/挪走也属于本次定稿变更，必须纳入同一回滚边界：commit 成功前保留可恢复备份，commit 失败时恢复旧文件并清除新文件，禁止留下"旧章消失、新章未提交"的中间态。

3.6 **一次性建仓流程（迁移等）的目录级原子边界**（M7 起）：在最终落位的同一磁盘卷内用临时目录完整构建（全部文件 + git 初始 commit + 缓存重建校验），全部成功后一次 `rename` 落位；任一步失败必须删除临时目录整树，工作目录零残留。流程启动时必须幂等清扫本流程前缀的历史残留临时目录；迁移的源目录全程只读。

## 4. 面向作者的错误文案

4.1 必须全中文、自然流畅；禁止出现堆栈、错误码、英文术语，也不强求口语化。

4.2 必须说清三件事：发生了什么、影响是什么、作者现在该做什么（或系统已替作者做了什么）。

4.3 提醒与错误必须区分："悬了太久"等账面提醒不是错误，禁止用错误语气呈现。

## 5. 退出码与错误类型

5.1 CLI 退出码：`0` = 命令成功；`1` = 命令失败（已落入人话提示，非堆栈崩溃）。`bin/webnovel-writer.js` 统一用 `process.exitCode`，禁止 `process.exit(n)` 硬退（except 版本门槛/`--version` 早退）。

5.2 所有面向作者的执行路径返回 `{ ok: boolean, error: string }` 结构化结果，禁止抛未捕获异常（总原则 §1.1）。`{ok:false}` 携带中文 `error`，调用方据 `ok` 决定退出码。

5.3 `git.clean` / `git.restore` 等回滚操作必须内部 `try/catch` 吞错（尽力而为，不破坏 `{ok,error}` 契约），残余不一致由 git 健康检查兜底。

## 6. 待增量补充

- [ ] git 健康检查的完整异常清单与修复动作映射
