docs: count the breaking changes again, and say where the fourth door is

This commit is contained in:
2026-09-05 06:37:57 -04:00
parent e06cd8e8b7
commit 32b92a8894
@@ -191,13 +191,16 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语
| 1 | `.env` / `from_env()` / `from_settings()` | `config._cast` 委托 `coerce_effort` | | 1 | `.env` / `from_env()` / `from_settings()` | `config._cast` 委托 `coerce_effort` |
| 2 | 构造函数全量注入 `SourceConfig(...)``chat(reasoning_effort=...)` | `SourceConfig.__post_init__` / `chat()` 入口 | | 2 | 构造函数全量注入 `SourceConfig(...)``chat(reasoning_effort=...)` | `SourceConfig.__post_init__` / `chat()` 入口 |
| 3 | **缓存命中回放** `LLMResponse.applied_effort` | `CacheMW._coerce_applied_effort` | | 3 | **缓存命中回放** `LLMResponse.applied_effort` | `CacheMW._coerce_applied_effort` |
| 4 | **公共函数 `resolve_thinking()` 直调** | 函数入口自行 `coerce_effort`(2026-09-05 独立验证查出) |
第 3 条是 T8 加 `applied_effort` 字段时才浮现的: 响应进 Redis 走 JSON,`StrEnum` 存成裸串, 第 3 条是 T8 加 `applied_effort` 字段时才浮现的: 响应进 Redis 走 JSON,`StrEnum` 存成裸串,
命中回放时类型已丢。与 `thinking_observation` 当年的坑**逐字相同**(见 issue #16/#17),故按同一 命中回放时类型已丢。与 `thinking_observation` 当年的坑**逐字相同**(见 issue #16/#17),故按同一
先例处置: 域外取值降级为 `None` 且**不作废整条缓存**——多项目共用 Redis 时互相打缓存是老问题, 先例处置: 域外取值降级为 `None` 且**不作废整条缓存**——多项目共用 Redis 时互相打缓存是老问题,
为一个可观测字段丢掉整条响应不划算。 为一个可观测字段丢掉整条响应不划算。
新增第四条入口时(新工厂、新 transport 参数、新的反序列化路径)必须同样过 `coerce_effort` 第 4 条是本次换代**自己造出来的**: 该函数在 `__all__` 里,第三参数由 `bool` 换成 `Effort` 后,下游最自然的写法就是从 JSON/配置读出来的裸串 `"low"`。不归一则 `_inject``.value``AttributeError`——一个未文档化、不属四分类的异常
新增第五条入口时(新工厂、新 transport 参数、新的反序列化路径)必须同样过 `coerce_effort`
## 5. 缓存 key ## 5. 缓存 key
@@ -252,7 +255,9 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语
|---|---| |---|---|
| 档位清单与「能否关闭」皆无冲突 | 直接登记 | | 档位清单与「能否关闭」皆无冲突 | 直接登记 |
| **档位清单三源一致,仅「能否关闭」存疑**(如 kimi-k3: 官方档位无 `none`,OpenRouter 却标 `mandatory:false`) | 按**保守方向**登记(不含 `none`),evidence 注明存疑点。理由: 不登记会退回 Phase 3 的「尽力注入」,下游配 `none` 时静默失效——**那正是 issue #20 的病**;保守登记则报错并给出最低档,明确且有出路 | | **档位清单三源一致,仅「能否关闭」存疑**(如 kimi-k3: 官方档位无 `none`,OpenRouter 却标 `mandatory:false`) | 按**保守方向**登记(不含 `none`),evidence 注明存疑点。理由: 不登记会退回 Phase 3 的「尽力注入」,下游配 `none` 时静默失效——**那正是 issue #20 的病**;保守登记则报错并给出最低档,明确且有出路 |
| 档位清单本身未知(`未查到`/`推定同上`) | 不登记,走 Phase 3 |`default` 列只是调研记录,按 §3.2 并入 `evidence` 文本,不进字段。 | 档位清单本身无该型号直接证据(`未查到`,或仅由**同系**推定如 `推定同上`) | 不登记,走 Phase 3 |
第二档与第三档的分界是**有没有该型号自己的档位证据**,不是「关不关得掉存不存疑」: `kimi-k3` 进第二档,因为月之暗面官方文档直接写明它的三档是 `low/high/max`,只有「能否关」两源分歧;而 `gemini-3-flash``claude-haiku-5` 的档位清单是从同系型号(3.1-pro / opus-5)推来的,**没有该型号自己的文档**,故进第三档。Phase 3 并非静默——它会 warning 指路「实测后用 `register_capability` 登记」,且未登记模型的运行期对账文案也专门写了这一句;登记一个纯推定值反而会让下游以为库确认过。T10 实测时这三个型号优先补。`default` 列只是调研记录,按 §3.2 并入 `evidence` 文本,不进字段。
| 模型 | supported_efforts(推定) | 厂商默认(入 evidence) | 关? | | 模型 | supported_efforts(推定) | 厂商默认(入 evidence) | 关? |
|---|---|---|---| |---|---|---|---|
@@ -309,7 +314,17 @@ request.reasoning_effort > source.reasoning_effort > source.enable_thinking(语
## 12. 迁移与兼容 ## 12. 迁移与兼容
**破坏性变更**: `ThinkingCapability` 的构造签名(`can_disable``supported_efforts`) **破坏性变更**(初稿只列了第 1 条,其余四条为 2026-09-05 独立验证实测补全——照初稿写 CHANGELOG 会让下游撞上没有预告的 `TypeError`):
| # | 位置 | 变更 | 谁会断 |
|---|---|---|---|
| 1 | `ThinkingCapability` | 构造签名 `can_disable``supported_efforts` | 自建能力表的调用方 |
| 2 | `ports.Transport.complete()` | 新增**无默认值**参数 `reasoning_effort` | 任何自建 transport 实现 |
| 3 | `ports.TelemetryRecorder.record_llm_call()` | 新增无默认值参数 `reasoning_effort` | 任何自建 recorder 实现 |
| 4 | `thinking.resolve_thinking()` | 第三参数换语义(`bool``Effort`),**返回类型由 `Mapping` 改为 `ThinkingResolution`** | 读侧代码一律断 |
| 5 | `providers.ProviderProfile` | `thinking_on`/`thinking_off``thinking: ThinkingWire` | 自建 profile 的调用方 |
五者都在包根导出面或端口面上。
**先更正**(Codex 审查指出): 初稿称「已核实 `reference/` 三项目无调用点,实际影响面为零」——**该结论不成立**。`reference/` 下当前**没有** GovDoc-SaaS / Video-Tree-TRM5 / CHSAnalyzer 三个目录(工作区实际只有本次调研克隆的四个开源项目),此前的 `grep` 因目录不存在而输出空,被误读成「无匹配」。 **先更正**(Codex 审查指出): 初稿称「已核实 `reference/` 三项目无调用点,实际影响面为零」——**该结论不成立**。`reference/` 下当前**没有** GovDoc-SaaS / Video-Tree-TRM5 / CHSAnalyzer 三个目录(工作区实际只有本次调研克隆的四个开源项目),此前的 `grep` 因目录不存在而输出空,被误读成「无匹配」。