---
type: plan
node_id: plan:governance-backend-error
title: "实现计划: 治理后端故障归位为 scope 级不可用(Issue #7)"
date: 2026-08-06
---

# 实现计划: 治理后端故障归位为 scope 级不可用(Issue #7)

全文见 `2026-08-06-governance-backend-error-plan.md`。实现设计 [[governance-backend-error]](已批准 2026-08-06)。

## 五个任务

| # | 任务 | 关键约束 |
|---|---|---|
| T1 | `ARCHITECTURE.md` §6.1 回补两行 + reason 值域扩为 6 值 | **必须先行**——单一事实源纪律,先改代码后补文档等于让实现与事实源脱节(设计 §8.1) |
| T2 | `errors.py` 纯增量: 新常量、新 reason、`SourceNotConfiguredError` + 顶层导出 | 刻意不动 `GovernanceBackendError`,故全套件保持通过,可独立提交 |
| T3 | `GovernanceBackendError` 归位 + 22 处构造点 + gate scope 注入 + 全部受影响测试 | **必须原子**: `scope` 是必填 keyword,分批提交的中间状态会 `TypeError` |
| T4 | README 公开错误面两列表 + 迁移文档补注 | issue #7 的第二诉求,作者认为比第一条更值得改 |
| T5 | 版本 1.1.0 + CHANGELOG + Wiki 同步 | 加父类是扩大不是破坏,故 minor 而非 major |

## 保真校验(适用)

触及 ARCHITECTURE §1.4 的移植蓝本(CHS `app/domain/errors.py` 与 `app/coordination/`)。本次**有意变更**的语义仅一条(`GovernanceBackendError` 的类型归属);`retry_after_s` 非可选语义、两个 reason 值域、fail-closed 方向、记账/闸门分工、`RedisPermit` 释放侧降级五条**不得被顺带改动**,每任务完成前逐条自查。

## 独立审查修正(2026-08-06, Codex)

4 条意见全部核实属实并已折回:

1. **T3 测试证据定位错误**(重要)——原写"复用 `test_backpressure.py:176-186` 的注入桩"覆盖三条泄漏路径,实测那三个桩是 `record_success`/`record_failure`/`mark_progress` 的**记账侧降级**,与闸门路径无关;`try_acquire`/`try_enter` 全无覆盖。已改为"三条桩都要新增"并写明现状。
2. **T3 漏了既有测试构造点**(重要)——新签名 keyword-only 必填,`test_backpressure.py:176/181/186`、`test_errors.py:89` 的裸 `GovernanceBackendError("...")` 与 `:255/:257` 的 `QuotaGate(_L())` 漏改即 `TypeError`。已补一张同批更新清单。
3. **`__all__` 插入位置写反**(次要)——按字母序应在 `SourceDeadError` **之后**而非之前。已改。
4. **设计中 telemetry 行号过时**(次要)——`:210` → `:250`,系本分支加 `_AttemptUsage` 造成的漂移。设计与摘要页已同步更新。

Codex 同时独立核实了计划的可执行性锚点: 22 处构造点、三处 gate 装配、后端层 `self._scope` 位置、README/ARCH 章节行号,均与 `src/` 现状相符。

## 独立验证炸出的阻塞缺陷(2026-08-06,全新上下文 verifier)

T1–T5 全绿、四道门禁全过之后,verifier 用一个**走 `QuotaGate` 的**端到端用例证明: 装配缺陷在唯一的生产路径上根本没拆出去——包装器的 `except GovernanceBackendError: raise` 只放行旧类型,`SourceNotConfiguredError` 落进下一行 `except Exception` 被重新包回去,配置写错照样永远重投。**盲区在于 T3 写的两条用例都直接打私有 `_cfg()`,比生产路径低一层。**

修复见正文 §T6(9 处放行 + 遥测终态捕获 + 走包装器的回归测试)。复核时 verifier 又指出一颗雷: 新放行让该异常能穿透 `_record_quietly`,而那层降级的存在理由是"调用已真实完成,写回失败不该丢弃成功响应"——同批把三处 `_record_quietly` 一并放宽并加了回归断言。

两轮都订正了同一处事实错误: 闸门泄漏路径是**五条**不是三条(`QuotaGate.stats` 与 `BreakerGate.retry_after_s` 同样未被 `_record_quietly` 包裹)。

相关: [[governance-backend-error]](design)、[[m2-distributed]]
