Files
PolyGateway/CLAUDE.md
T
iomgaa 4f2c149a9d docs: add D13 retry decision and development roadmap
Record tenacity vs self-built evaluation as D13 in ARCHITECTURE.md
(self-built wins: per-attempt orchestration, cancellation guarantees,
supply-chain discipline). Add research-wiki/ROADMAP.md expanding the
milestone table with ordering rationale and exit criteria.
2026-07-20 01:02:35 -04:00

144 lines
12 KiB
Markdown

# CLAUDE.md
> [!URGENT]
> **实验室内部通用基础库(生产级、非 MVP、零业务假设)**
> 1. 本项目是被多个科研/生产项目依赖的**库**,不是应用:稳定性、并发性、防御性、可观测与测试不可为"简单"让步(YAGNI 仍适用,但不削减健壮性)。库的 bug 会同时击穿所有下游项目。
> 2. 你的所有思考过程和回复必须使用 **简体中文**。
## 1. 项目元数据
- **核心目标**: PolyGateway = 统一的大语言模型(LLM/VLM/OCR,音频预留)调度与中转库。治理单位是**一次模型调用**:请求封装、多源多账号、限流、错误分类与重试、熔断、Redis 响应缓存、流式看门狗、遥测(含成本)、结构化输出策略。全组件端口化可插拔。
- **架构权威文档**: `research-wiki/ARCHITECTURE.md`(架构单一事实源,含 D1-D13 决策及讨论过程、子系统设计、三项目迁移验收标准;**不受 400 行设计文档限制**,以无歧义传达既有讨论为准绳)。开发顺序见 `research-wiki/ROADMAP.md`;`research-wiki/designs/` 仅存放每次实现具体功能的设计文档。
- **参考项目**: `reference/` 下三个项目是本库的需求来源与代码蓝本(**只读,勿改**);库必须能按 ARCHITECTURE.md §11 被它们迁移接入,否则即边界缺口。
- **技术栈**: Python 3.11+,核心仅依赖 `httpx` + `pydantic`,其余(redis/sqlite/postgres/json_repair/openai)一律 optional extras。conda 环境 `PolyGateway`
## 2. 常用命令
> [!CRITICAL]
> 所有 Python 命令必须在 `PolyGateway` conda 环境中执行(`conda run -n PolyGateway <cmd>` 或先激活)。长时间运行的程序用 tmux 且禁用日志缓存。
```bash
make install # editable 安装(含 dev 与全部 extras)
make test # pytest + 覆盖率
make lint # ruff --fix + import-linter(依赖铁律机械化执法)
make format # ruff format
make ci # 只读验证(check + test)
```
## 3. 标准作业程序(分档触发)
> **档位原则(Fable 5 适配,2026-07 调研决策)**: 约束"边界与验收",不规定思考步骤。强制档(MANDATORY)是硬门;其余由模型按 skill description 自判,自判标准是任务实质(规模/风险/是否触及公共承诺),不是省事。硬边界(reference/ 只读、危险命令、提交质量门)由 `.claude/settings.json` 注册的 hooks **确定性执行**,不依赖提示词自觉。
### Phase 1: 规划与设计
1. 涉及**公共 API、端口签名、架构边界、新子系统**的变更**必须**调用 `brainstorming`(产出 2-3 备选方案+权衡)并经**人类确认**后实施;其余任务自判(判据: 是否改变库对下游的承诺)。动手前查阅 `research-wiki/`(单一事实源)。
2. 功能产生运行时数据时**必须**调用 `structured-logging`
3. **里程碑级/跨多文件**功能编码前**必须**调用 `writing-plans`;小改动自判。审核门控: design 走 Claude 自审 → Codex 审 → **人类审**;plan 走 Claude 自审 → Codex 审 → 直接执行。
### Phase 2: 执行与验证
1. **测试结果门**: 合并前每个行为变更必须有"先失败后通过"的测试证据(`test-driven-development`);bug 修复必带回归测试;不规定中间怎么走。
2. **独立验证**: 里程碑级/跨多文件/合并前**必须**派全新上下文的 verifier subagent(`verification-before-completion`);任何规模的完成声明都必须逐条对应本会话内的工具输出(证据化声明,禁止虚报)。
3. **反 gold-plating**: 不做任务外的重构、抽象与"顺手清理"。
## 4. 核心规则
### 4.1 核心原则(按优先级)
- **P1 YAGNI**: 不写当前用不到的代码;但并发控制、防御校验、可观测埋点、错误隔离与测试是"当前需要",不在削减之列。
- **P2 高可读性**: 领域术语命名;注释解释"为什么"。
- **P3 单一职责**: 一句话说不清职责(需要"和")= 拆分。
- **P4 显式优于隐式**: 公共函数完整类型注解;依赖注入,不从全局偷取;严禁默认参数掩盖关键逻辑。
- **P5 防御性与安全性**: 一切外部输入(网关响应、LLM 返回、配置)校验后使用;严禁 `except Exception: pass`;严禁默认值掩盖错误;敏感信息只走 `.env`
- **P6 可测试性**: 纯函数优先;外部依赖经 Protocol 注入;测试用真实样本或其二次构造。
- **P7 架构依赖规则**: 决策逻辑与状态存储分离(中间件算法一份,后端可插拔);`ports.py`/`types.py`/`errors.py` 为最内层,不 import 任何具体实现;`middleware/` 只依赖端口;`transports/``backends/``telemetry/` 只实现端口,互不依赖(import-linter 契约执法)。
### 4.2 库铁律(本项目特有,违反即 bug)
| 铁律 | 内容 |
|---|---|
| 零业务假设 | 库内禁止出现任何下游业务领域词汇(视频/文书/超声等)与业务 fixtures;扩展点一律 Protocol |
| 纯 asyncio 中立 | 无全局状态、无框架假设、无模块级单例;同一 `GatewayClient` 在 arq worker 与裸脚本中行为一致 |
| 取消可穿透 | `asyncio.CancelledError` 永不捕获吞没;重试循环、限流等待、流式读取全部可被取消;in-flight 资源在 finally 释放 |
| 错误分类驱动 | 一切失败必须落入 `errors.py` 四分类(Transient/SourceDead/RequestRejected/ResultInvalid),由分类决定重试/换源/熔断,禁止散落 ad-hoc 判断 |
| 遥测必录 | 每次调用(含缓存命中、失败)必经 `TelemetryRecorder` 记录,遥测写失败降级不冒泡;遥测调用点收敛为单一 helper,禁止复制参数列表(三项目 4 处复制的教训) |
| 降级方向 | 缓存/遥测后端不可用 → 静默降级(warning);限流/熔断后端不可用 → **报错而非放行**(防击穿网关) |
| 依赖极简 | 核心仅 httpx + pydantic;新增任何依赖必须进 optional extras 并经人类确认 |
| 无缓存毒化 | 缓存 key 必含 model + messages 摘要 + 命名空间/租户 + salt;多模态 content 先摘要再 hash |
### 4.3 代码开发规范
- 模块/类/方法必须有**中文 Docstring**;复杂逻辑用 `# Phase N` 注释组织。
- 校验分层: 外部输入校验用显式异常(Python `-O` 移除 assert,禁止 assert 承担生产校验);assert 仅用于内部不变量。
- 类名 `PascalCase`,私有前缀 `_`;导入顺序标准库→第三方→项目内。
- 日志统一 **loguru**,禁用 `print()`;返回类型用 frozen dataclass。
- 不考虑向后兼容,直接修改原文件。**例外**: `LLMResponse` 等已被三项目消费的公共类型,字段只增不删不改名(迁移兼容约束,见 ARCHITECTURE.md §5.1)。
### 4.4 Git 工作流
- 一切开发在 feature 分支,严禁直改 main;频繁语义化提交;提交**必须**调用 `commit` skill;大改动前先提交回滚点。
### 4.5 配置管理
- 工程配置走 `pydantic-settings` + `.env`(模板 `.env.example`,敏感项不提交);严禁硬编码默认值;缺失关键配置直接报错。
- 多源命名约定 `{SCOPE}__{PROVIDER}__{N}__{FIELD}`;韧性参数键名沿用三项目习惯(`LLM_TIMEOUT` 等),降低迁移成本。
- 装配只有两条路: `GatewayClient.from_env()`/`from_settings()`(工厂)或构造函数全量注入(测试/高级);库内部任何组件不得自读环境变量。
### 4.6 测试组织
- `tests/{unit,integration,e2e}`;真实场景优先(录制的真实网关响应二次构造优于凭空 mock)。
- 覆盖率目标 80%;并发/韧性行为是一等测试对象: 重试穿透取消、熔断开路半开、限流结算退款、Redis 掉线降级方向、缓存 key 隔离。
- Redis 相关测试用真实 Redis(integration),不 mock Lua 行为;限流契约测试随实现一起交付(参考 CHSAnalyzer `tests/contracts_limiter.py`)。
- 涉及真实 LLM 的测试输出结构化 Markdown 至 `tests/outputs/<module>/<test>_<ts>.md`
## 5. 项目结构
```text
project_root/
├── src/polygateway/ # 库本体(结构见奠基设计 §7: ports/types/errors 内核 +
│ # middleware/ transports/ backends/ telemetry/ structured/,
│ # 见 ARCHITECTURE.md §8)
├── tests/ # unit/integration/e2e + 限流契约测试
├── reference/ # 三个参考项目(只读,勿改,不提交)
├── tools/ # 独立工具脚本(不被 import)
├── scripts/ # 仅 .sh
├── research-wiki/ # 单一事实源(designs/plans/findings/adrs/reviews)
├── data/ logs/ # 运行产物,不提交
└── Makefile / pyproject.toml / .env(.example) / CLAUDE.md
```
> 注: 以上为**目标结构**。当前已落地: `research-wiki/ARCHITECTURE.md`、`reference/`、`.claude/`(18 个 skill 已完成 Fable 5 适配改造 + hooks 硬边界 + settings.json);其余随 M1 里程碑创建(ARCHITECTURE.md §12)。
硬性规则: 根目录不得出现 `.py`;`scripts/` 只放 `.sh`;禁止 `helpers/ common/ shared/ misc/ lib/` 目录名;`data/``logs/``tests/outputs/` 不提交;`reference/` 只读且不入库。
## 6. 上下文导航
| 需求 | 路径 |
|---|---|
| 架构全貌: 决策 D1-D13 及讨论过程、端口清单、错误分类、子系统设计、迁移验收 | `research-wiki/ARCHITECTURE.md`(单一事实源) |
| 开发顺序与里程碑状态 | `research-wiki/ROADMAP.md`(活文档,随进度更新) |
| 功能设计文档(每次实现新功能时新增) | `research-wiki/designs/` |
| 实现计划 | `research-wiki/plans/` |
| 治理网关参考实现 | `reference/Video-Tree-TRM5/adapters/`(llm/breaker/streaming/redis_cache/telemetry) |
| 分布式限流/熔断参考实现 | `reference/CHSAnalyzer/app/coordination/`(limiter+Lua/provider_gate)与 `app/providers/governance.py` |
| 错误分类参考 | `reference/CHSAnalyzer/app/domain/errors.py` |
| OCR 两端点参考 | `reference/Video-Tree-TRM5/adapters/ocr.py``reference/CHSAnalyzer/app/providers/invokers.py:408-552` |
| 第一次抽库尝试(教训与蓝本) | `reference/GovDoc-SaaS/packages/docagent-core/` |
## 7. 输出规范
- 所有输出**中文**;文档优先表格/伪代码/Mermaid;禁止超 15 行代码块入文档、禁止连续超 5 条碎片列点;设计 ≤400 行、计划 ≤1000 行、报告 ≤300 行。
- **例外**: `research-wiki/ARCHITECTURE.md` 不受行数限制——它的准绳是"后来的 AI/人类无需还原原始讨论即可准确理解全部决策及理由",宁详勿略(详细 ≠ 琐碎:记录论证与取舍,不堆砌实现细节)。
## 8. Skill 使用规则
> [!CRITICAL]
> **Skill 的 description 即触发边界。** 下表标注 **MANDATORY** 的情形是硬门(设计人类门、合并前测试证据门、合并前独立验证门、commit 格式),不得跳过;其余情形按 description 边界自判——自判看任务实质(规模/风险/是否触及公共承诺),不是省事。任何 skill 流程不得引入任务外的重构或抽象。优先级: 用户显式指令 > Skill 详细流程 > 本文件宏观规则。
| Skill | 触发边界 |
|-------|---------|
| `brainstorming` | **MANDATORY**: 公共 API/端口签名/架构边界/新子系统变更;其余自判 |
| `writing-plans` | **MANDATORY**: 里程碑级/跨多文件功能;小改动自判 |
| `test-driven-development`(测试结果门) | **MANDATORY**: 合并前——行为变更须有先失败后通过的测试证据 |
| `verification-before-completion`(独立验证) | **MANDATORY**: 声称完成/合并前;里程碑级须派全新上下文 verifier subagent |
| `commit` | **MANDATORY**: 提交代码时 |
| `requesting-code-review` / `receiving-code-review` | **MANDATORY**: 合并/PR 前 / 收到审查反馈后;中途审查自判 |
| `systematic-debugging` | 遇到 bug、测试失败、异常行为时(根因先于修复) |
| `structured-logging` | 功能会产生运行时数据时 |
| `subagent-driven-development` | 执行大型已批准计划时的**可选**执行器(内含合并前一次整分支审查) |
| `finishing-a-development-branch` | 实现完成且测试通过,准备集成时 |
| `using-git-worktrees` | 需要并行/隔离的分支开发时 |
| `research-wiki` / `graphify` | 管理知识库时 / 已建图后的代码结构检索 |
| 科研类: `harness-eval` `idea-creator` `novelty-check` `research-lit` | 惰性资产,现阶段不用,由模型按任务实际需要启用 |