2026-09-07 20:52:58 +08:00
# 合并注意事项 · 风控 Agent 模块并入 main( AL-09 执行手册)
2026-09-08 20:00:39 +08:00
> 版本:2026-09-07 v1.0(基于 `risk-control-agent` 分支 HEAD `cfbd056` 实测编制)
> **执行状态:AL-09 已完成(2026-09-08,工作分支 `merger`) ** — 下文 §0~§7 为合并前手册,保留作审计参照;执行摘要见下节。
---
## ✅ AL-09 执行记录(2026-09-08)
| 项 | 结果 |
| --- | --- |
| 工作分支 | `merger` (已 merge 风控模块 + 宿主 Wave 0) |
| JWT 统一 | `/api/auth/login` → `auth_service.issue_dev_token` ; `gateway/jwt_service` issuer/audience 读 `settings` |
| 模块 chat 恢复 | `chat.py` / `agent_service.py` / `memory_service.py` (含 sessions/stream) |
| S2 接缝 | `auth_adapter.module_auth_from_host()` 已接线 |
| trace 中间件 | ApiError / AppError / PermissionDenied / RequestValidationError / StarletteHTTPException **re-raise** ;仅未捕获 → 500 |
| 边界测试 | `tests/test_module_boundary.py` 全绿(宿主 D 类文件排除跨层扫描) |
2026-09-11 17:07:22 +08:00
| 测试基线 | ** `python -m pytest` → 530 passed, 0 skipped**( AL-09 当时快照)· **当前 merger 全量见 `docs/memory/MEMORY.md` §0( 825) ** |
2026-09-08 20:00:39 +08:00
**架构结论:** 宿主 `gateway/` 与模块 `deps.py` **双栈并存** ;对外 token 统一;模块 API 禁止 import `app/gateway/` 。
2026-09-07 20:52:58 +08:00
> 用途:**给合并执行人**——风控模块开发方已交付(482 用例全绿 + 接口实调验收通过),本文档是该模块并入 main 的全部注意事项。逐项过完再动手,可避开已知的全部坑。
> 裁决依据(冲突逐文件怎么改):**《风控Agent模块边界与合并接缝标注.md》§4 裁决表**——本文档讲"操作顺序与坑",与它配合读。
---
## 0. 前置状态(合并前先核对)
| 项 | 状态 |
| --- | --- |
| 开发分支 | `risk-control-agent` ,领先本地 main 85 提交 / 落后 0 |
| 最新交付 | HEAD `cfbd056` ; tag `risk-m1~m4` (m4 = C4~C6 完成,仅本地) |
| 测试基线 | **482 passed 0 failed** (系统 Python 3.13.14, sqlite + 真 MySQL 集成) |
| 接口验收 | 2026-09-07 实调通过:suitability/check 阻断+放行、simulate/trade 阻断、三条鉴权边界(401/403/403),错误体统一结构 |
| 分叉点 | `1ddd44a` (09-05 旧骨架);main 侧在分叉后有 5 个提交,最关键的是 ** `3995cb4` Wave 0 平行实现** |
## 1. 【最高风险】合并基底必须用本地 `main`(3995cb4),不要用 `origin/main`
**实测:`origin/main` 仍停在 Initial commit `53701db`, Wave 0( `3995cb4`)从未推送到远端。**
- 若执行 `git merge origin/main` 或 `git pull` (默认合 origin/main):因 Initial commit 是分支祖先,会**"干净成功"零冲突,但完全不引入 Wave 0 的任何代码**——20 个冲突文件一个不报、13 类双套风险全部缺席,看似合并完成实则漏合并,且事后极难发现。
- **正确操作**: `git merge main` (本地 main,校验 `git rev-parse main` = `3995cb4` )。
- **附带动作**:合并前建议先让 main 侧负责人把 Wave 0 推上远端(`git push origin main` ),否则本次合并结果推到 `risk-control-agent` 远端后,远端历史里依然没有 Wave 0 的原初提交,后续审计/回溯会困惑。
- 本机 git 2.55 有 ref 异常史(fetch/update-ref 成功但读回旧值),**一律用 commit hash 校验,不依赖 ref 名**。
## 2. 冲突解决:20 个文件,逐个按裁决表,禁止批量 ours/theirs
`git merge-tree --write-tree --name-only risk-control-agent main` 实测 **20 个冲突文件** :
```text
AGENTS.md app/main.py app/utils/exceptions.py
app/api/chat.py app/model/suitability.py app/utils/response.py
app/config/settings.py app/repository/core_ro.py docs/memory/ENVIRONMENT.md
app/gateway/__init__.py app/service/agent_service.py docs/memory/FLOW.md
scripts/core/02-seed-base.sql app/service/memory_service.py docs/memory/FRAMEWORK.md
tests/conftest.py docs/memory/ITERATION.md
docs/memory/MEMORY.md
docs/memory/REQUIREMENTS.md
docs/memory/TODO.md
```
- **逐文件裁决规则见《边界标注》§4**(概要:core_ro / model-suitability / conftest / 02-seed-base / memory 六件套 **以模块版为准**并吸收 main 新增实质内容;chat / main / settings / agent_service / memory_service / exceptions / response **以 main 为主** ,模块侧功能经 4 接缝回挂)。
- 禁止 `git checkout --ours/--theirs` 批量处理:两侧不是"新旧关系"而是"平行实现",批量必丢功能。
## 3. 静默并入文件:14 个(git 不报冲突、直接进仓库,双套风险)
**代码 11 个** ( main 的 Wave 0 平行实现,与模块同名能力并存):
```text
app/api/auth.py # main 的鉴权路由(模块无此路由,无冲突)
app/gateway/auth_deps.py # ┐
app/gateway/jwt_service.py # │ main 的鉴权四件套(vs 模块 app/service/auth_service.py + app/api/deps.py)
app/gateway/rbac.py # │
app/gateway/ownership.py # ┘
app/middleware/__init__.py # ┐
app/middleware/trace.py # ┘ main 的 trace 中间件(vs 模块 app/utils/trace.py + audit_middleware)
app/repository/agent_repository.py # ┐
app/repository/audit_repository.py # │ main 的三仓储(vs 模块 session_repository / risk_repository)
app/repository/advisor_rel_repository.py # ┘
app/utils/input_guard.py # main 的输入防护(vs 模块 app/service/input_guard.py)
```
**测试 3 个** : `tests/test_wave0_auth.py` / `test_wave0_input_guard.py` / `test_wave0_trace.py` (main 侧自带测试,合并后一并入库运行)。
另有 `docs/来自客户的项目资料/` 约 20 个资料文件静默并入(纯文档,无风险,正常收下)。
**双套并存是拍板过的架构决策** (风控模块自治,模块内自带鉴权/防护/trace;与宿主耦合只走 4 接缝 S1 挂载点 / S2 AuthContext / S3 settings / S4 引擎工厂)。**约束:模块代码绝不允许 import 上述 main 实现**——`tests/test_module_boundary.py` 已用 21 例断言锁死(禁止跨层 import `app.gateway.*` / `app.config.database` / `app.middleware.*` / `app.utils.input_guard` / `app.model.schemas` )。合并后该测试必须全绿,红了说明冲突解决时误伤了边界。
## 4. 三处已知硬伤的处置
1. **JWT issuer 不一致** :模块 `.internal` vs main `.dev` (audience 相同)。自治方案下**不统一**:模块链路走自己的 issuer,跨层身份转换走 S2 适配器 `app/api/auth_adapter.py` (已预制、未接线,合并即用),避免全量 token 重签。
2. **main `DEFAULT_ROLES_BY_ACTOR` 无 STAFF-90001** (风控演示账号):`scripts/core/02-seed-base.sql` 手工融合时**必保 STAFF-90001**,并补 STAFF-31001/31002( C5 的 risk_manager 演示账号)。
3. **main `infer_roles` fail-open** ( `app/gateway/jwt_service.py:89` 附近:未知 actor 默认 `["analyst"]` ,含 `sql:execute:readonly` ):模块链路不调用它(模块为 fail-closed),但**该代码随静默文件并入仓库后就是宿主侧 P1 安全缺陷**。建议合并时一并修复(未知 actor 应拒绝),或至少登记为 main 侧待修事项,绝不给宿主路由接线。
## 5. 合并后必测清单(顺序执行,全过才算合并完成)
1. `python -m pytest tests/test_module_boundary.py -q` (系统 Python 3.13.14)——边界 21 例全绿,冲突解决没伤模块。
2. **中间件顺序实测** :起 uvicorn 打任意 API,断言 `http_access` 审计行带非空 `trace_id` 。main 的 `add_middleware(TraceMiddleware)` 与模块的 `@app.middleware` 叠加后,若 trace 落在 audit 内层,全部审计 trace_id 会变空(合规红线 P-05)。
3. **chat 链路端到端冒烟** : `app/api/chat.py` 依赖 `agent_service` ,而 main 版签名是 `run_chat(ctx, msg, cust)` 、模块版是 `chat(...)` , **不兼容**。按边界标注 §4 #4 用适配层对接后,必须实调一次 `/api/chat` 确认不炸(单测可能因 mock 掩盖签名错配)。
4. 按《演示SOP-风控模块.md》§2 **重灌两库** (合并后 02-seed-base 是融合版,库结构须重建)。
5. 全量 `python -m pytest -q` ——基线参考:模块侧交付时 482 绿 + main 侧 3 个 wave0 测试文件;有红灯先分清是环境残留(演示库未重灌)还是冲突解决引入。
6. `tests/test_auth_adapter.py` 11 例(S2 适配器若已接线)。
## 6. 演示库重灌特别提醒(易误判为 bug)
- 种子客户 33 人中仅 6 人(1001/1002/1003/3001/4001/9527)会被 `prepare_risk_demo.sql` 刷新为未过期,其余 27 人 expires_at 是 2026 年的绝对旧日期。**只跑 `reset.ps1` 不跑 `prepare_risk_demo.sql` → 462 组合适性检查全部返回 risk_expired**(约 82%),这是种子设计不是缺陷,但极易误判——重灌务必两步都跑。
- `reset.ps1` 是交互式(要输密码),不能无人值守直跑。
## 7. 交付基线快照(合并出问题时回滚参照)
- 分支交付态:`risk-control-agent` @ `cfbd056` ( 482 绿)
- 功能里程碑:`risk-m1` (阶段A)→ `risk-m2` (阶段B 事件线)→ `risk-m3` (阶段C 对话线)→ `risk-m4` ( C4~C6 追加需求)
- 冲突裁决权威:《风控Agent模块边界与合并接缝标注.md》;模块需求权威:`docs/PRD/PRD-风控监测Agent.md` ( v1.1,§4A = 追加需求)