From 49f6ca80d8e7600b174eb027d67247c33afd8528 Mon Sep 17 00:00:00 2001 From: lhl Date: Sun, 9 Aug 2026 15:19:55 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E9=94=99=E8=AF=AF=E7=A0=81=E4=B8=80?= =?UTF-8?q?=E8=87=B4=E6=80=A7=E6=B5=8B=E8=AF=95=E8=AE=BE=E8=AE=A1=EF=BC=88?= =?UTF-8?q?api=20=C2=A77=20=E2=86=94=20=E5=BC=82=E5=B8=B8=E6=A0=91?= =?UTF-8?q?=E6=9C=BA=E5=99=A8=E9=AA=8C=E8=AF=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...8-09-error-code-consistency-test-design.md | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-09-error-code-consistency-test-design.md diff --git a/docs/superpowers/specs/2026-08-09-error-code-consistency-test-design.md b/docs/superpowers/specs/2026-08-09-error-code-consistency-test-design.md new file mode 100644 index 0000000..114b8f1 --- /dev/null +++ b/docs/superpowers/specs/2026-08-09-error-code-consistency-test-design.md @@ -0,0 +1,102 @@ +# 错误码一致性测试设计(api-design §7 ↔ exceptions.py) + +> **状态:** 已批准(brainstorming + DX 审查吸收) +> **日期:** 2026-08-09 +> **里程碑后备路径:** LLM 错误码对齐(error_code)收尾 + +## 1. 背景与目标 + +「LLM 错误码对齐」完成后,`api-design.md §7` 错误码表与 `src/genesis/inference/exceptions.py` 的异常树通过 `error_code` 类属性建立了一一对应关系(LLM_TIMEOUT ↔ LLMTimeoutError 等),但该对应关系目前**仅靠人工核对**维护: + +- `test_inference_errors.py` 断言了异常类自身的 `error_code` 值(代码自证代码,防不了文档漂移) +- 文档添加/删除错误码行、或代码新增异常类时,没有测试会在两边失配时变红 + +**目标:** 将「api §7 = 唯一事实源」的核对从人工升级为机器验证——新增回归测试解析 `docs/api-design.md` §7 表格,断言与异常树双向一致,防文档↔代码漂移。 + +## 2. 范围与不做的事 + +**范围:** +- 仅验证 §7 表格中**来源列以 `exceptions.` 开头**的 5 条 LLM 错误码行(LLM_TIMEOUT / LLM_NETWORK_ERROR / LLM_NOT_CONFIGURED / LLM_PARSE_ERROR) +- 双向验证:异常树 → 文档、文档 → 异常树 + +**不做(YAGNI):** +- 不验证非 LLM 错误码行(FILE_TYPE_INVALID、EMBEDDING_FAILED、INTERNAL_ERROR 等来源列为「—」,暂无代码映射) +- 不抽 src 生产模块(测试自包含,零生产代码改动) +- 不做 web-ui §8 端点表等其它文档一致性检查(有第二个需求再提炼共享模块) + +## 3. 设计 + +### 3.1 落点 + +新建独立测试文件 `tests/test_api_design_consistency.py`(单一职责:文档 ↔ 代码一致性门禁),不污染现有 `test_inference_errors.py`。 + +### 3.2 文件定位(沿用项目先例) + +```python +API_DOC = Path(__file__).resolve().parents[1] / "docs/api-design.md" +``` + +(与 `tests/test_real_samples.py:7` 的 `SAMPLES` 定位方式一致;不依赖 CWD,pytest 任意目录启动可跑。) + +### 3.3 解析函数(内联纯函数) + +```python +def _extract_llm_error_rows(document: str) -> dict[str, str]: + """解析 §7 表格中来源列以 exceptions. 开头的行,返回 {错误码: 来源类名}。""" +``` + +- 实现:逐行匹配表格行 ` | \`CODE\` | ... | exceptions.Xxx |`,提取错误码与来源类名 +- 用途:返回 LLM 错误码 → 来源异常类名 的映射;非 LLM 行(来源 "—")被天然排除 + +### 3.4 测试用例(4 个) + +| # | 用例 | 验证方向 | 断言要点 | +|---|------|---------|---------| +| 1 | `test_error_doc_lists_every_llm_error_code` | 异常树 → 文档 | 遍历 `LLMError.__subclasses__()`,每个子类 `error_code`(非 None)必须出现在文档映射中,且来源类名 == 子类名 | +| 2 | `test_error_doc_llm_rows_resolve_to_exception` | 文档 → 异常树 | 文档映射中每个错误码都能在 `LLMError.__subclasses__()` 中找到 `error_code` 相同、类名匹配的唯一类 | +| 3 | `test_error_doc_stable_llm_row_count` | 格式护栏 | 文档映射中 LLM 行数 == 5(防止表格结构变化静默失效;新增/删除 LLM 行需显式更新此数) | +| 4 | `test_error_doc_parse_guard_prevents_silent_noop` | 格式护栏 | 若解析结果为空(表格格式被改动导致正则失配),立即硬失败而非静默通过 | + +### 3.5 失败可诊断(DX 修正 F1/F2) + +- 测试 1/2 断言失败时,输出**双向差异清单**:文档有而代码无的码、代码有而文档无的码,并附引导语「请同步 api-design.md §7 或 exceptions.py」 +- 通过 pytest 的断言消息(`assert ... , "差异说明"`)实现,避免裸 `assert 'LLM_QUOTA' in dict` 的模糊失败 + +### 3.6 契约可读性(DX 修正 F4) + +- 文件头部模块 docstring 写明:「此测试为 api-design §7 ↔ exceptions.py 的机器契约,变更错误码必须两处同步修改」 + +## 4. 错误处理 + +| 场景 | 行为 | +|------|------| +| 文档缺失 | `read_text()` 抛 FileNotFoundError → 测试失败(显式暴露) | +| 表格行解析失配(0 行) | 用例 4 硬失败,杜绝静默失效 | +| 新增异常未登记 / 文档多行无单码 | 用例 1/2 分别双硬失败并列出差异 | +| LLM 行数变化 | 用例 3 失败,提示显式更新计数 | + +## 5. 测试策略与覆盖 + +- 本功能自身即测试;不新增生产代码,`fail_under=99` 红线不受触碰(其按 `src/` 生效,tests/ 命中不计) +- 全量回归保持 ≥ 128 passed(新增 4 用例后 ≥ 132) +- 验证命令:`python -m pytest tests/test_api_design_consistency.py -v`(聚焦);`python -m pytest -q`(全量) + +## 6. 验收标准 + +1. `pytest tests/test_api_design_consistency.py -v` 全绿(4 passed) +2. 全量回归 `python -m pytest -q` ≥ 132 passed / 100.00% 覆盖 +3. 手工破坏验证(可选):临时删除文档某 LLM 行 → 用例 1 变红且差异清单可读;恢复正常 +4. 不修改任何现有源文件或测试文件 + +## 7. 影响面 + +- 新增 1 个测试文件(约 60-80 行) +- 修改 1 个文件:`_AI_USAGE_LOG.md`(追加日志行) +- 提交消息:`test: api §7 与异常树错误码一致性门禁测试(防文档漂移)` + +## 8. 不做的事(YAGNI 最终确认) + +- ❌ 非 LLM 行验证 +- ❌ src 生产辅助模块 +- ❌ Enum 化错误码(spec 已明确 str) +- ❌ 其它文档表一致性检查 \ No newline at end of file