docs: record approval, verification evidence and a follow-up gap
Corrects the changelog claim that the old guard messages only named env keys: they named fields too, it was the remediation advice that pointed at env keys. Records the human approval of the design, the mutation-testing evidence from the independent verifier, and the same-class gap it found: 14 checks (redis_url presence, telemetry paths, enum validity) still live only in from_env, while client.py asserts they were already validated. Deliberately out of scope here.
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
直接构造 `GatewaySettings` 或对它做 `dataclasses.replace` 时,若上述组合非法,**现在会在构造期抛 `ValueError`**,而不是留到运行时。经 `from_env()` 装配的调用方**不受影响**——那条路本就跑这些守卫。手工拼配置(如从 YAML 读出后构造)的调用方若此前撞上过上述任一故障,升级后会在启动时立即得到点名字段的报错。
|
直接构造 `GatewaySettings` 或对它做 `dataclasses.replace` 时,若上述组合非法,**现在会在构造期抛 `ValueError`**,而不是留到运行时。经 `from_env()` 装配的调用方**不受影响**——那条路本就跑这些守卫。手工拼配置(如从 YAML 读出后构造)的调用方若此前撞上过上述任一故障,升级后会在启动时立即得到点名字段的报错。
|
||||||
|
|
||||||
守卫的报错文案改为点字段名(`lease_ttl_s`、`backpressure.stall_window_s`、`breaker.probe_ttl_s`)。原文案只点环境变量键,而不走 env 的调用方从没设过那些键。键名映射见 `.env.example` 与 wiki `参考-配置键`。
|
守卫报错文案的**补救建议**改为点字段名(`lease_ttl_s`、`backpressure.stall_window_s`、`breaker.probe_ttl_s`)。原文案已点出字段名,但建议部分给的是环境变量键(如"调大 `PGW_LEASE_TTL_S`"),而不走 env 的调用方从没设过那些键。键名映射见 `.env.example` 与 wiki `参考-配置键`。
|
||||||
|
|
||||||
## 1.0.0(2026-07-22)
|
## 1.0.0(2026-07-22)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# GatewaySettings 跨字段不变量守卫的生效范围
|
# GatewaySettings 跨字段不变量守卫的生效范围
|
||||||
|
|
||||||
- **日期**: 2026-07-29;**状态**: 待人类审批(改变库对下游的构造承诺,强制人类门)
|
- **日期**: 2026-07-29;**状态**: **已批准并实施**(2026-07-29 人类门通过;§8 结论见文末)
|
||||||
- **范围拍板**(用户 2026-07-29): 功能对齐社区 PR#1,但按本库规范重写;顺带销掉 PR#1 遗留的两个缺陷
|
- **范围拍板**(用户 2026-07-29): 功能对齐社区 PR#1,但按本库规范重写;顺带销掉 PR#1 遗留的两个缺陷
|
||||||
- **上游依据**: ARCHITECTURE §7.3 契约补强 G6(装配期守卫,"违反直接报错拒绝装配")、§9 配置聚合、CLAUDE.md §4.5(装配只有两条路)、`types.py` 同族 frozen dataclass 的既有校验笔迹
|
- **上游依据**: ARCHITECTURE §7.3 契约补强 G6(装配期守卫,"违反直接报错拒绝装配")、§9 配置聚合、CLAUDE.md §4.5(装配只有两条路)、`types.py` 同族 frozen dataclass 的既有校验笔迹
|
||||||
|
|
||||||
@@ -123,9 +123,29 @@ TDD 顺序:先写测试跑出预期失败(预计 3 条守卫 + 空源 + from_set
|
|||||||
|
|
||||||
合并后应关闭 PR#1 并在其中说明:诊断被采纳,实现按库内规范重写并扩展了覆盖范围。
|
合并后应关闭 PR#1 并在其中说明:诊断被采纳,实现按库内规范重写并扩展了覆盖范围。
|
||||||
|
|
||||||
## 8. 待人类拍板
|
## 8. 人类拍板结论(2026-07-29)
|
||||||
|
|
||||||
1. **主决策**:接受方案 A(构造期强制,承诺收紧)?
|
| 问题 | 结论 |
|
||||||
2. **范围**:`probe_ttl_s` 与空 sources 一并纳入(推荐),还是严格只对齐 PR#1 的两条?
|
|---|---|
|
||||||
3. **消息文案**:去掉 env 键名(推荐,§2.3),还是保留 PR#1 的附注形式?
|
| 主决策 | **接受方案 A**,构造期强制,承诺收紧 |
|
||||||
4. **PR#1 处置**:重写合并后关闭并说明,还是先请提交者按 review 修改?
|
| 范围 | **全量**:`probe_ttl_s` 与空 sources 一并纳入 |
|
||||||
|
| 消息文案 | **去掉 env 键名**,只点字段名(§2.3) |
|
||||||
|
| 版本 | **1.0.1**(patch);初稿建议的 minor 被否,理由与代偿见 §4 |
|
||||||
|
| PR#1 处置 | 重写合并后关闭并说明,诊断归功于提交者 |
|
||||||
|
|
||||||
|
## 9. 实施与验证留痕
|
||||||
|
|
||||||
|
实施于 `fix/settings-invariant-guards`(5 commits)。TDD 证据:新测试类先 **6 failed / 3 passed**(3 条为边界护栏,本就应过),实现后全绿。
|
||||||
|
|
||||||
|
独立 verifier(全新上下文)核验结论 **可以合并,无阻塞**,其中两项证据值得留档:
|
||||||
|
|
||||||
|
- **变异测试 12/12 全杀**:逐个破坏实现(删各 `_validate_*` 调用、`>`↔`>=`、`<`↔`<=`、删空源检查、`_PROBE_GRACE_S` 归零)均有测试失败,无一存活。边界侧用例(恰好相等必过)对每条守卫都真实有效,差一错误可捕获。
|
||||||
|
- **无热路径回归**:库内**没有任何地方**构造或 `replace` `GatewaySettings`(`src/` 中 4 处 `dataclasses.replace` 全在 `middleware/structured.py`,作用于 `ChatRequest`/`LLMResponse`)。单次构造实测 1.45 µs,装配期一次性成本。`pickle`/`deepcopy` 不触发 `__post_init__`,只有 `replace` 触发——序列化往返既无额外开销也不构成二次守卫点。
|
||||||
|
|
||||||
|
### 9.1 verifier 发现的同族遗漏(范围外,另起任务)
|
||||||
|
|
||||||
|
`GatewaySettings` 仍有 **14 条校验只挂在 `from_env`**,直接构造/`replace` 全部放行,与本设计所修的是同一个 bug 类:`limiter/breaker/cache_backend=redis` 但 `redis_url=None`、`telemetry_backend=sqlite/postgres` 但 path/dsn 为 None、`selector`/`quota_full`/各 backend 的枚举合法性、`structured_max_retries` 负值、`scope` 空串等。
|
||||||
|
|
||||||
|
严重性高于本次所修的三条,因为 `client.py:262/282/302/312/316` 有 5 处 `assert ... # 内部不变量: config 已校验` **明文依赖这个前提**,而该前提在 `from_settings` 路上为假:断言开启时抛裸 `AssertionError`(不点字段不说原因),`python -O` 下断言消失、错误退化为 redis 库抛出的天书。后者同时违反 CLAUDE.md §4.3"禁止 assert 承担生产校验"。
|
||||||
|
|
||||||
|
**有意不纳入本次交付**(避免任务外扩张),另起任务处理。
|
||||||
|
|||||||
Reference in New Issue
Block a user