docs: finalize M2 design after human approval gate

This commit is contained in:
2026-07-20 23:41:20 -04:00
parent dfd9dcfee4
commit b165c2aae6
3 changed files with 13 additions and 13 deletions
+1 -1
View File
@@ -397,7 +397,7 @@ flowchart TB
- `InMemoryLimiter`: 同一契约的进程内实现(semaphore + 滑动窗口计数);单进程场景下语义等价。
- **配额满行为可配**: `wait`(等待,配 stall 判定——本地等待超窗 + 全局无进展超窗双条件才判卡死)或 `fail-fast`(立即抛)。
- 全局活性信号: `mark_progress()`/`progress_age_s()`("最近一次出餐"时刻)供背压 stall 判定,移植 `CHSAnalyzer limiter.py:193`
- **契约补强(2026-07-20,CHS 迁移缺口 G6)**: `settle()`/`release()` 幂等(重复调用无副作用);装配期守卫——`timeout_s ≤ permit 租约 TTL`(防租约先于请求过期)、`stall_window ≥ 最慢源 TTFT 上限`(防误判卡死),违反直接报错拒绝装配。降级方向细化(2026-07-20 M1): "报错不放行"适用于**准入侧**(try_acquire/try_enter );已成功调用后的 settle/release 释放侧失败降级 warning——释放失败不构成放行,且不得掩盖主异常与取消。
- **契约补强(2026-07-20,CHS 迁移缺口 G6)**: `settle()`/`release()` 幂等(重复调用无副作用);装配期守卫——`timeout_s ≤ permit 租约 TTL`(防租约先于请求过期)、`stall_window ≥ 最慢源 TTFT 上限`(防误判卡死),违反直接报错拒绝装配。降级方向细化(2026-07-20 M1): "报错不放行"适用于**准入侧**(try_acquire/try_enter 及选源路径消费的 source_stats/retry_after_s);已成功调用后的 settle/release 释放侧失败降级 warning——释放失败不构成放行,且不得掩盖主异常与取消。**勘误(2026-07-20 M2 设计,人类批准)**: 记账侧的 `record_success`/`record_failure`/`mark_progress` 同归此类——调用已真实完成,后端失败若冒泡会丢弃真实成功响应或掩盖原始尝试异常,故降级 warning(CHS 原版一律报错,此为有意反转;丢一次熔断记账最多延迟状态迁移且方向偏保守,epoch fencing 防污染)。
### 7.4 熔断
+1 -1
View File
@@ -16,7 +16,7 @@
|---|---|---|---|
| P0 奠基 | 调研、ARCHITECTURE.md、CLAUDE.md、skill Fable 5 改造、hooks 硬边界、脚手架(git/pyproject/Makefile/conda 环境/CI 绿) | — | ✅ 完成(2026-07-20) |
| M1 核心 | 内核类型 + httpx transport + 治理中间件(内存后端)+ 多源多账号 + 缓存 + SQLite 遥测 + 结构化输出 + from_env | GovDoc、Video-Tree | ✅ 完成(2026-07-20;239 测试全绿、覆盖 92%、真实网关+真实 Redis 验收通过、独立 verifier 问题清零;见 designs/2026-07-20-m1-core-design.md 状态行) |
| M2 分布式 | Redis 限流/熔断后端、多源 × Redis 联合验证、背压、Postgres 遥测、成本 | CHSAnalyzer(治理) | ⬜ 未开始 |
| M2 分布式 | Redis 限流/熔断后端、多源 × Redis 联合验证、背压、Postgres 遥测、成本、Embedding(Q3)、压测 harness | CHSAnalyzer(治理) | 🔨 进行中(设计已过人类门 2026-07-20,见 designs/2026-07-20-m2-distributed-design.md) |
| M3 OCR | OCR 端口族 + MonkeyOCR transport | CHSAnalyzer(全量)、Video-Tree(OCR 升级) | ⬜ 未开始 |
| M4 迁移验证 | 三项目逐一按 ARCHITECTURE §11 验收,缺口回补,发 v1.0 | 全部 | ⬜ 未开始 |
@@ -1,6 +1,6 @@
# M2 分布式里程碑设计:Redis 治理后端 + 背压 + Postgres 遥测 + pricing + Embedding + 压测 harness
> **状态**: 已过 Claude 自审独立 subagent 审(2026-07-20,2 Critical + 6 Important + 3 Minor 全部核验采纳修订:熔断契约时间用例 1:1 变体机制、stall entered_at 回归 CHS 口径、记账侧降级定案、Postgres 两级降级、embedding 遥测字段、probe_ttl 派生守卫对齐等)→ **待人类门**
> **状态**: ✅ **人类门已过(2026-07-20)**。流程:Claude 自审独立 subagent 审(2C+6I+3M 全部核验采纳)→ 人类批准,批准时修正两处:时间语义变体**真实量级等待不缩放**(§2.3)、压测 token 硬顶上调至 **2 亿**(§8.1);Postgres 测试环境定为实验室专用库 `polygateway`(§11.5)。→ 下一步 `writing-plans`
> **依据**: ARCHITECTURE.md §7.3/§7.4/§7.8、ROADMAP §3(Q3 已拍板纳入 Embedding)、findings/2026-07-20-m2-soak-workload.md、M1 冻结契约(designs/2026-07-20-m1-core-design.md)、三份 reference 逐字调研(CHS 协调层 / Embedding 两版 / Postgres+pricing)
> **硬约束**: M1 冻结的公共签名与双后端契约(`ports.py` 的 `RateLimiter`/`Permit`/`ProviderGate`/`GateDecision`/`GateUpdate`/`TelemetryRecorder` 18 字段)**不改动**;Redis 后端必须通过 `tests/contracts/` 同一套契约测试。
@@ -55,7 +55,7 @@
| T1 fixture 增参 + 真实 Redis | `tests/contracts/conftest.py``limiter_factory`/`gate_factory` params 增 `"redis"`;无 `REDIS_URL` 时该 param skip;每 test 唯一 scope(uuid)隔离 | **推荐**:M1 预留的接入方式,测试体零改动 |
| T2 fakeredis | 进程内模拟 | 否决:不执行真实 Lua,违反"Redis 测试用真实 Redis"规约 |
**时间语义用例的裁决(限流 2 例 + 熔断 8 例,即全部依赖 `clock.advance` 的用例)**:FakeClock 对 Redis 后端不可用(时间源是 Lua 内服务器 `TIME`,无法注入),且按比例缩放会破坏绝对值断言(如 progress age `41<age<43`)。方案:`clock` fixture 后端感知——memory param 返回 FakeClock;redis param 返回哨兵时钟,其 `advance()` 触发 `pytest.skip`(理由注明变体位置)。被 skip 的每个用例在 `tests/integration/test_redis_governance_time.py`**1:1 对应的真实等待变体**(小时长配置:cooldown_s≈0.5、probe_ttl_s≈1.0、lease_ttl_s≈1.0,断言同名行为;窗口翻滚移植 CHS `_await_window_headroom` 防抖),plan 中附映射表逐条核对不漏。**两契约测试文件本体零改动**;不依赖时钟推进的用例(状态机、同 epoch fencing、幂等、六闸判定、settle 退款)在 redis param 下直接运行全绿。验收口径"双后端同一契约套件全绿"据此细化为:非时间用例双后端同套件,时间用例 memory 走契约文件、redis 走 1:1 变体——此口径请人类批准设计时一并认可(§13)。测试固定用 db3。
**时间语义用例的裁决(限流 2 例 + 熔断 8 例,即全部依赖 `clock.advance` 的用例)**:FakeClock 对 Redis 后端不可用(时间源是 Lua 内服务器 `TIME`,无法注入),且按比例缩放会破坏绝对值断言(如 progress age `41<age<43`)。方案:`clock` fixture 后端感知——memory param 返回 FakeClock;redis param 返回哨兵时钟,其 `advance()` 触发 `pytest.skip`(理由注明变体位置)。被 skip 的每个用例在 `tests/integration/test_redis_governance_time.py`**1:1 对应的真实等待变体**——**人类拍板(2026-07-20):不缩放时长,用真实量级配置真实等待**(cooldown_s/probe_ttl_s 取契约同值或贴近生产的值,如 cooldown 60s、probe_ttl 120s;整文件预计 10-20 分钟,标记 `@pytest.mark.slow`,缺 `REDIS_URL` 自动 skip;窗口翻滚移植 CHS `_await_window_headroom` 防抖),plan 中附映射表逐条核对不漏。**两契约测试文件本体零改动**;不依赖时钟推进的用例(状态机、同 epoch fencing、幂等、六闸判定、settle 退款)在 redis param 下直接运行全绿。验收口径"双后端同一契约套件全绿"据此细化为:非时间用例双后端同套件,时间用例 memory 走契约文件、redis 走 1:1 变体——此口径请人类批准设计时一并认可(§13)。测试固定用 db3。
## 3. Redis 熔断(`backends/redis/breaker.py`)
@@ -175,7 +175,7 @@ class EmbeddingClient:
| 项 | 提议值(可改) |
|---|---|
| 预算上限 | P1≤500 次 / P2≤450 次 / P3+P4≤2500 次 / P5≤1000 次 / P6≤8000 次或 3h;全程 token 硬顶 5000 万(输入+输出合计,按遥测实测累计) |
| 预算上限 | P1≤500 次 / P2≤450 次 / P3+P4≤2500 次 / P5≤1000 次 / P6≤8000 次或 3h;全程 token 硬顶 **2 亿**(输入+输出合计,按遥测实测累计;2026-07-20 人类签字,自提议值 5000 万上调) |
| 网关保护 | harness 全局闸:max_concurrency=100、全局 RPM=600;跑 P6 建议夜间时段(具体由人类定) |
| P6 混合比例 | P1 10% / P2 20% / P3 50%(其中 3/10 为重复 messages 走缓存双向,即 P4)/ P5 20% |
@@ -207,7 +207,7 @@ class EmbeddingClient:
2. **保真**:Lua 移植逐段比对 CHS 行号(plan 内设检查点);移植 CHS 三个跨连接集成用例(双连接池共享全局并发/全局 RPM/进度可见)。
3. **联合验证(③)**:多 client 双连接池下,多源换源 + 全局 RPM 不超配 + 熔断状态跨连接共享的集成测试;取消穿透在 Redis 后端下重验(in-flight 取消 → lease 释放)。ROADMAP"多 worker 压测下全局限额真实生效"的验收通道 = pytest 双连接池等价验证(Redis 只见连接不见进程,Redis 后端无共享本地状态,连接≈进程)+ harness `--workers≥2` 真多进程冒烟,此口径请人类认可(§13)。
4. **stall**:memory 后端 FakeClock 推进双条件各自与同时成立的四象限;fail_fast 路径不受影响回归。
5. **Postgres**:真实实验室 Postgres?——**无现成实例,用 conda 环境本地起临时 postgres 或 docker;若都不可用则该集成测试标 skip 并在验收注明**(integration;幂等/降级/并发 50 写并落全部)。
5. **Postgres**:实验室实例的**专用库 `polygateway`**(2026-07-20 已创建;该实例上有 app/chs_prod/mimiciv 等在用库,遥测测试严禁指向,与 Redis db3 同款隔离纪律);DSN 走 `.env``PGW_TELEMETRY_PG_DSN`(已配,不入任何提交文件),缺键自动 skip(integration;幂等/降级/并发 50 写并落全部)。
6. **Embedding**:unit(ScriptedTransport 分批/保序/归一化/维度校验/重试换源)+ e2e 真实网关冒烟(若网关有 embedding 端点;没有则 e2e 降为对 MiniMax chat 网关的 404 行为记录,unit 全覆盖)。
7. **harness**:本体不入 pytest;`corpus.py` 的 traces 还原器与不变量断言函数给 unit 测试(纯函数)。
@@ -217,11 +217,11 @@ class EmbeddingClient:
沿 ROADMAP §3 顺序(编号为本设计重排:ROADMAP ⑤=Postgres+pricing、⑥=Embedding,此处拆为 ⑤⑥⑦):① Redis 限流 → ② Redis 熔断 → ③ 联合验证 → ④ stall → ⑤ Postgres 遥测 + ⑥ pricing(可并行)→ ⑦ Embedding → ⑧ harness(⑤-⑧ 相互独立,⑧ 依赖全部)。交付物:`backends/redis/{limiter,breaker}.py``middleware/retry.py` stall 增量、`telemetry/postgres.py``pricing.py``embedding.py` + transport 增量 + `ports.py`/`types.py` 新增(EmbeddingTransport/EmbeddingResponse,只增不改)、config 增量、`tools/soak/``.env.example` 回填、迁移文档 embedding 条目更新。
## 13. 开放问题(设计内已给提议,批准时可一并裁决)
## 13. 开放问题(2026-07-20 人类门全部裁决)
1. §8.1 三项签字(预算/网关保护/P6 比例)
2. Postgres 集成测试环境:实验室有无可用 Postgres 实例?(无则按 §11.5 降级方案)
3. 真实网关是否有 embedding 端点可供 e2e?(无则按 §11.6 降级方案)
4. 契约验收口径认可(§2.3):时间语义 10 用例 redis param 下 skip、由 1:1 真实等待 integration 变体覆盖——"双后端同一契约套件全绿"含此细化
5. 多 worker 验收口径认可(§11.3):pytest 双连接池等价 + harness `--workers≥2` 真多进程冒烟
6. 记账/释放侧降级定案认可(§10):`record_success`/`record_failure`/`mark_progress` Redis 失败降级 warning(CHS 原版报错,有意反转),批准后勘误 ARCHITECTURE。
1. §8.1 三项签字:✅ 按提议值,唯 token 硬顶上调至 2 亿
2. Postgres 测试环境:实验室实例专用库 `polygateway`(见 §11.5)。
3. 网关 embedding 端点:人类未明示,按推荐默认**实现时发一次真实探测请求**,有则 e2e、无则记录降级(§11.6);可随时推翻。
4. 契约验收口径:✅ 认可,且修正为**真实量级时长真实等待、不缩放**(§2.3)
5. 多 worker 验收口径:✅ 认可(pytest 双连接池等价 + harness 真多进程)
6. 记账/释放侧降级反转:✅ 认可,ARCHITECTURE 勘误随本次提交