docs: 合并注意事项手册(给合并执行人) + 文档口径清理
- 新增《合并注意事项-风控模块并入main.md》:面向合并执行人的 AL-09 操作手册—— 基底锁定(本地 main 3995cb4,origin/main 停在 Initial commit 勿用)/20 冲突文件 指引裁决表/14 个静默并入文件清单(11 代码+3 测试,双套风险与边界防呆)/三处 硬伤处置(issuer 不统一/STAFF-90001 必保/infer_roles fail-open P1)/合并后 必测清单(边界测试→中间件顺序→chat 签名→重灌→全量)/演示库重灌提醒 - TODO/MEMORY 口径落账:接口实调验收通过(2026-09-07 AI 代验:三接口契约+三 鉴权边界 401/403/403 零偏差,前端未 init 口径为后端接口验证);合并 main 移交合并执行人;模块侧开放项=actor_id 透传评估+前端入口归属拍板;修正 AL-09 旧口径(9 文件→实测 20 文件);删重复待办行
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
| `docs/需求拆解/` | 已定 | 场景 P0、矩阵、合规原文 |
|
| `docs/需求拆解/` | 已定 | 场景 P0、矩阵、合规原文 |
|
||||||
| `docs/PRD/PRD-风控监测Agent.md` | **已冻结(v1.1)** | 风控 PRD v1.0 + v1.1 追加 FR-8/9/10(§4A)+ 规则表附录 |
|
| `docs/PRD/PRD-风控监测Agent.md` | **已冻结(v1.1)** | 风控 PRD v1.0 + v1.1 追加 FR-8/9/10(§4A)+ 规则表附录 |
|
||||||
| `docs/项目框架设计/实现方案-风控追加需求v1.1-C4C6.md` | **已定稿** | C4~C6 编码依据(经独立 AI 评审修订闭环);分支/进度速览另见项目根 `交接文档.md` |
|
| `docs/项目框架设计/实现方案-风控追加需求v1.1-C4C6.md` | **已定稿** | C4~C6 编码依据(经独立 AI 评审修订闭环);分支/进度速览另见项目根 `交接文档.md` |
|
||||||
|
| `docs/项目框架设计/合并注意事项-风控模块并入main.md` | **已定稿(2026-09-07)** | **给合并执行人**:基底锁定(本地 main 3995cb4,origin/main 停在 Initial commit)/ 20 冲突裁决指引 / 14 静默并入文件 / 三处硬伤处置 / 合并后必测清单 |
|
||||||
| `docs/项目框架设计/表设计/` | 已定 | Agent 共用 11 表 + agent 专用 SQL |
|
| `docs/项目框架设计/表设计/` | 已定 | Agent 共用 11 表 + agent 专用 SQL |
|
||||||
| `docs/项目框架设计/Core模拟底座/` | 已定 | 无真实 Core 时的 L0 方案 |
|
| `docs/项目框架设计/Core模拟底座/` | 已定 | 无真实 Core 时的 L0 方案 |
|
||||||
| `web/` | **不存在** | 前端 React 待 init |
|
| `web/` | **不存在** | 前端 React 待 init |
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
> **本机 ①~⑤已执行、`.env` 已配置,勿重做**;本机状态与已知坑(mysql.exe 路径 / reset.ps1 交互式 -p / `redis`、`python-jose` 包漏装已补)见 `FLOW.md` §0 尾注。
|
> **本机 ①~⑤已执行、`.env` 已配置,勿重做**;本机状态与已知坑(mysql.exe 路径 / reset.ps1 交互式 -p / `redis`、`python-jose` 包漏装已补)见 `FLOW.md` §0 尾注。
|
||||||
> **演示库状态(2026-09-07)**:已按演示 SOP §2 重灌并清理冒烟数据(alerts 0 / AML 8 / 会话 0),pytest 全量可直接跑;**下次演示/走查后再按 SOP §2 重灌**(核查单⑥前置断言会对走查残留显式 fail,属防护行为)。
|
> **演示库状态(2026-09-07)**:已按演示 SOP §2 重灌并清理冒烟数据(alerts 0 / AML 8 / 会话 0),pytest 全量可直接跑;**下次演示/走查后再按 SOP §2 重灌**(核查单⑥前置断言会对走查残留显式 fail,属防护行为)。
|
||||||
|
|
||||||
**下一步开发(见 TODO):** 阶段一验收门(**合并 main 前交付检查点,非分支开发阻塞**;用户浏览器目视确认 UI;pytest 482 绿 + 冒烟已通过)→ AL-09 合并 main → AL-10 PRD v1.2 → AL-11 docx 登记 → 阶段二 C4~C6(**编码已完成:C4 RISK-006 `fe4801b` / C5 RISK-007 `90d0660` / C6 RISK-008 `66ec7eb`,全量 pytest 482 passed 0 failed**;收尾=演示 SOP 补代理人扮演步骤 + 02-redis-keys.md 增补 + tag `risk-m4` 已打(2026-09-07 指向 `323d98b`,仅本地未 push,按计划里程碑 tag 不入库))/ 前端 React 多 Agent 入口。演示走查按 `docs/项目框架设计/演示SOP-风控模块.md`(debug 头通道仍有效;JWT 通道签发用 `scripts/dev/issue_dev_token.py`;**演示库已按 AL-08 expires_at 新口径重灌**)。知识库入库:`python scripts/kb/build_kb.py`(先启 Ollama;**Milvus 数据路径必须纯英文**——faiss 不支持中文路径,本机 .env 已配 C:/Users/YUAN/.jinrong/milvus/)。
|
**下一步开发(见 TODO):** **模块侧交付完毕(2026-09-07:全量 pytest 482 绿 + 接口实调验收通过——suitability/check 阻断+放行、simulate/trade 阻断、三条鉴权边界 401/403/403 契约零偏差;`risk-m1~m4` tag 齐)。合并 main 已移交合并执行人,操作手册《docs/项目框架设计/合并注意事项-风控模块并入main.md》(含基底锁定/20 冲突裁决/14 静默文件/三硬伤/合并后必测,实测数据编制)。模块侧开放项:chat 链路 risk_suitability_log.actor_id 落 SYSTEM 待评估 / 前端 React 多 Agent 入口(`web/` 未 init,归属待拍板)。**演示走查按 `docs/项目框架设计/演示SOP-风控模块.md`(debug 头通道仍有效;JWT 通道签发用 `scripts/dev/issue_dev_token.py`;演示库已按 AL-08 expires_at 新口径重灌)。知识库入库:`python scripts/kb/build_kb.py`(先启 Ollama;**Milvus 数据路径必须纯英文**——faiss 不支持中文路径,本机 .env 已配 C:/Users/YUAN/.jinrong/milvus/)。
|
||||||
|
|
||||||
**禁止(改代码前必记):** Core 正式 C1~C5 不可被画像覆盖 · 审计表只 INSERT · 代理人草稿不外发 · 仅 R-02 可阻断交易 · 四 Agent 不互调 LLM。
|
**禁止(改代码前必记):** Core 正式 C1~C5 不可被画像覆盖 · 审计表只 INSERT · 代理人草稿不外发 · 仅 R-02 可阻断交易 · 四 Agent 不互调 LLM。
|
||||||
|
|
||||||
@@ -78,8 +79,8 @@
|
|||||||
## 1. 项目简介
|
## 1. 项目简介
|
||||||
|
|
||||||
- **名称:** JinRong 金融四 Agent 智能管家
|
- **名称:** JinRong 金融四 Agent 智能管家
|
||||||
- **当前阶段:** **阶段一「对齐 main 基准」AL-01~AL-08 已完成(2026-09-07,commit bb244f4~b5fd52e,406 绿 + 冒烟通过;合并 main 前交付检查点=用户浏览器目视确认 UI,**不影响分支继续开发/推送**)**;T-21 知识库入库已完成并评审闭环(2026-09-07,425 绿基线,commit 9cc2e59);风控阶段 C 完成(M3 tag risk-m3,345 绿);T-03 输入防护完成(378 绿,评审 PASS with findings P0=0);**追加需求 FR-8/9/10(C4~C6)编码已完成(C4 `fe4801b`/C5 `90d0660`/C6 `66ec7eb`,全量 pytest 482 绿)+ 文档落账 `323d98b` + `risk-m4` tag 已打(2026-09-07,指向 `323d98b`,仅本地);挂账 #1~#9 逐项核对无违规**
|
- **当前阶段:** **模块交付完毕(2026-09-07)**——阶段一 AL-01~08 + 阶段二 C4~C6 全部完成,482 绿,接口实调验收通过(AI 代验),`risk-m1~m4` tag 齐;合并 main 已移交合并执行人(手册:《合并注意事项-风控模块并入main.md》)
|
||||||
- **当前优先级:** 阶段一验收门(**合并 main 前交付检查点,非分支开发阻塞**)→ AL-09/10/11 → 前端 React 入口(C4~C6 已收口)
|
- **当前优先级:** 模块侧开放项(actor_id 透传评估 / 前端 React 入口归属拍板);合并进度由合并执行人负责,模块侧不阻塞
|
||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|||||||
+9
-10
@@ -5,14 +5,11 @@
|
|||||||
|
|
||||||
## 进行中
|
## 进行中
|
||||||
|
|
||||||
**阶段一「对齐 main 基准」AL-01~AL-08 已全部完成(2026-09-07,逐项独立 commit bb244f4~b5fd52e)**,验收门进度:pytest 全量 **482 passed 0 failed 0 skipped**(含阶段一 406 + 阶段二 C4~C6;含真库集成)✓ · uvicorn 冒烟三端点(/health · /api/simulate/trade SUIT_RISK_MISMATCH+rule_refs · /api/risk/suitability/check 新契约)✓ · risk-m1 补打 ✓(指向 3c07de6)——**合并 main 前交付检查点(非分支开发阻塞):用户浏览器目视确认 UI**。确认通过(即决定合并时)按 AL-09 → AL-10 → AL-11 收尾,再进阶段二 C4~C6。
|
**阶段一 AL-01~AL-08 与阶段二 C4~C6 均已完成(2026-09-07)**:全量 pytest **482 passed 0 failed 0 skipped**(真库集成)✓ · uvicorn 冒烟三端点 ✓ · 接口实调验收 ✓(2026-09-07:suitability/check 阻断+放行、simulate/trade 阻断、三条鉴权边界 401/403/403,契约零偏差)· risk-m1~m4 tag 齐。**合并 main 已移交合并执行人**(操作手册:《docs/项目框架设计/合并注意事项-风控模块并入main.md》,随分支上传),后续模块侧待办见下方。
|
||||||
|
|
||||||
## 待办(推荐顺序)
|
## 待办(推荐顺序)
|
||||||
|
|
||||||
- [ ] **【阶段一验收门】用户浏览器目视确认 UI**(合并 main 前交付检查点,非分支开发阻塞;pytest 482 绿 + 冒烟均已自动通过)
|
- [x] **【阶段一验收门】接口实调验收** —— **通过(2026-09-07 委托 AI 代验:三接口契约 + 三鉴权边界全部符合;前端 web/ 未 init,验收口径为后端接口验证)**
|
||||||
- [ ] **【阶段一收尾】AL-09 合并 main 分支**(9 文件冲突按修改报告 AL-09 口径解决:memory 文档以我方为准,吸收 main 新增资料;02-seed-base 两方账号并存)
|
|
||||||
- [ ] **【阶段一收尾】AL-10 PRD v1.2 修订**(SUIT-001~008 编号体系退役登记,用户拍板②授权)
|
|
||||||
- [ ] **【阶段一收尾】AL-11 `01-客户.docx` 11~16 条读取登记**(用户拍板⑤:用工具读 docx)
|
|
||||||
- [x] **【阶段二】C4~C6 追加需求编码**(实现方案已定稿)—— **全部完成(C4 RISK-006 `fe4801b` / C5 RISK-007 `90d0660` / C6 RISK-008 `66ec7eb`,全量 pytest 482 passed 0 failed);收尾=演示 SOP 补代理人扮演步骤 + 02-redis-keys.md 增补 + tag `risk-m4`(见下条)**
|
- [x] **【阶段二】C4~C6 追加需求编码**(实现方案已定稿)—— **全部完成(C4 RISK-006 `fe4801b` / C5 RISK-007 `90d0660` / C6 RISK-008 `66ec7eb`,全量 pytest 482 passed 0 failed);收尾=演示 SOP 补代理人扮演步骤 + 02-redis-keys.md 增补 + tag `risk-m4`(见下条)**
|
||||||
- [x] **【阶段二前置】**`python -m pytest` 全量(系统 Python 3.13.14)确认基线绿 —— **482 passed 0 failed ✓(2026-09-07)**
|
- [x] **【阶段二前置】**`python -m pytest` 全量(系统 Python 3.13.14)确认基线绿 —— **482 passed 0 failed ✓(2026-09-07)**
|
||||||
- [x] **【阶段二】C5 前置联动**(挂账 #6):seed STAFF-31001/31002 + AGENT_ACCESS_MATRIX 增补 risk_manager + chat.py 显式 deny(对话线维持仅 risk_officer)+ risk.py 台账 manager 只读分支 + JWT 手册 §5.3 —— **完成(随 C5 落地,见挂账 #6 核对)**
|
- [x] **【阶段二】C5 前置联动**(挂账 #6):seed STAFF-31001/31002 + AGENT_ACCESS_MATRIX 增补 risk_manager + chat.py 显式 deny(对话线维持仅 risk_officer)+ risk.py 台账 manager 只读分支 + JWT 手册 §5.3 —— **完成(随 C5 落地,见挂账 #6 核对)**
|
||||||
@@ -35,17 +32,19 @@
|
|||||||
| #9 | payload JSON 检索性能 | `risk_repository` 仅改 `append/merge/find` 逻辑,无新增索引/查询计划优化 | ✓ 未动 |
|
| #9 | payload JSON 检索性能 | `risk_repository` 仅改 `append/merge/find` 逻辑,无新增索引/查询计划优化 | ✓ 未动 |
|
||||||
|
|
||||||
**红线复核**:C4~C6 无 DDL/迁移脚本(`scripts/core/02-seed-base.sql` 仅补 seed 行,非改表);审计仅 INSERT;升级标记仅 cron 可写;manager 无处置权;四 Agent 不互调 LLM。挂账清单无一项退化为本期误做。
|
**红线复核**:C4~C6 无 DDL/迁移脚本(`scripts/core/02-seed-base.sql` 仅补 seed 行,非改表);审计仅 INSERT;升级标记仅 cron 可写;manager 无处置权;四 Agent 不互调 LLM。挂账清单无一项退化为本期误做。
|
||||||
- [ ] 前端 React 多 Agent 入口(HashRouter,`web/` init)
|
|
||||||
|
|
||||||
- [x] **【阶段一】对齐 main 基准 AL-01~AL-08 —— 完成(2026-09-07,逐项独立 commit `bb244f4`~`b5fd52e`)**:AL-01 Core 表结构+矩阵表(core_suitability_rule 25 行 + is_hnw + 风评七新列 expires_at/investor_category + 33 客户/14 产品种子,保留 STAFF-90001)· AL-02 risk_suitability_log 重建 21 列(match_result 五值/mismatch_type 七值/block_response_code 八值/check_source 四值/rule_refs JSON + 6 索引;tests/_ddl.py 同步)· AL-03 core_ro 融合(check_suitability C×R 数据驱动 + list_products_for_customer + list_holdings 合并 + list_trades;CURDATE() 改 Python 端 `_is_expired`/`_as_date` sqlite 兼容;保留我方骨架与风控扩展)· AL-04 model/suitability 引入(build_suitability_log_row + compute_rule_refs 公共函数防漂移)· AL-05 suitability 服务换核(SUIT-001~008 判定内核 → check_suitability;判定链 not_found→FM-03 过期→JR-AST-PRO 豁免→JR-AST-012 矩阵 forbidden→披露→FM-01 网点确认;SuitabilityResult 扩新字段+兼容层;settings.risk_assessment_valid_days 退役改 expires_at;insert_suitability_log 21 列;check_source r02_trade/manual + actor_id 透传;NotFoundError 改结构化)· AL-06 chat_tools.suitability_check 返回体新枚举 + tool_service 文案重写(check_source='r02_chat')· AL-07 test_suitability 按 main 契约重写(七判定路径正反例 + compute_rule_refs 四类组合 + 21 列落库端到端 + MySQL 方言冒烟)· AL-08 演示 SQL expires_at 口径改写(测评 90 天前/剩余 275 天,CUST-1004 保持过期)+ SOP 同步 + 网关阻断响应补全契约 + 双库重灌。**验证:406 passed 0 failed 0 skipped(sqlite + 真 MySQL 集成);uvicorn 冒烟三端点通过;真库 risk_suitability_log 按 21 列 DDL 重建(旧表 RENAME 备份 bak_20260907 零数据丢失)**
|
## 待办(模块侧开放项)
|
||||||
- [x] **【阶段一拍板项】六项待确认全部落定(2026-09-07 用户拍板)**:①SUIT-006 退役以 main FM-01 为准 ✓ ②SUIT-001~008 编号体系退役授权 PRD v1.2 ✓ ③risk_assessment_valid_days 退役改 expires_at ✓ ④risk-m1 补打 ✓(已指向 3c07de6)⑤docx 用工具读取 ✓ ⑥合并 main 时机=阶段一验收门后 ✓
|
|
||||||
- [ ] 待办提醒:chat 链路 risk_suitability_log.actor_id 暂落 SYSTEM(run_tool 统一透传需动 core_tools/kb_tools 冻结 func 契约,发起者留痕已由 agent_tool_call 覆盖)——AL-06 遗留,阶段二顺带评估
|
- [ ] chat 链路 `risk_suitability_log.actor_id` 暂落 SYSTEM(run_tool 统一透传需动 core_tools/kb_tools 冻结 func 契约,发起者留痕已由 agent_tool_call 覆盖)——AL-06 遗留,动 Tool 契约前先出方案
|
||||||
|
- [ ] 前端 React 多 Agent 入口(HashRouter,`web/` init)——是否归风控模块由用户拍板
|
||||||
|
- [x] 2026-09-05 memory 文件夹更新(新 Agent 交接清单)
|
||||||
|
|
||||||
|
> **合并 main 相关(AL-09 / AL-10 / AL-11)已移交合并执行人**——模块侧交付完毕(482 绿 + 接口实调验收通过 2026-09-07),执行手册:《docs/项目框架设计/合并注意事项-风控模块并入main.md》(含基底锁定/20 冲突裁决/14 静默文件/三硬伤/合并后必测清单,实测数据编制)。
|
||||||
|
|
||||||
- [x] T-04 Core RO 封装为 Tool 节点;A-01 归属校验(chat Tool 接入 + agent_tool_call 落库)—— **完成(2026-09-07)**:`app/tool/core_tools.py`(L0/持仓/流水三只读 Tool + TOOL_REGISTRY 白名单)+ `app/service/tool_service.py`(关键词意图仅 customer/advisor;归属校验对齐 deps.assert_customer_access 口径——Tool 层拒绝不抛 403 而 blocked 留痕,纵深防御;run_tool 执行+落库,落库失败降级)+ agent_service 图 tool 节点(START→tool→llm→guard;结果注入 LLM 上下文,降级回复带摘要)+ session_repository.insert_tool_call(message_id 一期 NULL)。**A-01 口径:本任务只做 Tool 层归属校验语义(customer 本人/advisor assigned/risk_officer 全量/其余拒),A-01 完整场景(代理人画像)仍归 T-20**;risk 分支四 Tool 归 C1 复用 run_tool。**评审闭环(2026-09-07):首评 P1×2+P2×3+P3×2 → 修复 `40a9ee2` → 复审 P2×1+P3×4 → 修复 `1216d26`,pytest 321 绿;入参白名单+days 钳制、公共鉴权双写 `utils/authz.py`、list_holdings LIMIT 均落地**
|
- [x] T-04 Core RO 封装为 Tool 节点;A-01 归属校验(chat Tool 接入 + agent_tool_call 落库)—— **完成(2026-09-07)**:`app/tool/core_tools.py`(L0/持仓/流水三只读 Tool + TOOL_REGISTRY 白名单)+ `app/service/tool_service.py`(关键词意图仅 customer/advisor;归属校验对齐 deps.assert_customer_access 口径——Tool 层拒绝不抛 403 而 blocked 留痕,纵深防御;run_tool 执行+落库,落库失败降级)+ agent_service 图 tool 节点(START→tool→llm→guard;结果注入 LLM 上下文,降级回复带摘要)+ session_repository.insert_tool_call(message_id 一期 NULL)。**A-01 口径:本任务只做 Tool 层归属校验语义(customer 本人/advisor assigned/risk_officer 全量/其余拒),A-01 完整场景(代理人画像)仍归 T-20**;risk 分支四 Tool 归 C1 复用 run_tool。**评审闭环(2026-09-07):首评 P1×2+P2×3+P3×2 → 修复 `40a9ee2` → 复审 P2×1+P3×4 → 修复 `1216d26`,pytest 321 绿;入参白名单+days 钳制、公共鉴权双写 `utils/authz.py`、list_holdings LIMIT 均落地**
|
||||||
- [x] T-21 Milvus Lite + kb_product_rules 首批入库 —— **完成(2026-09-07,commits e34973f~535c8a0 共 6 个 + 评审闭环 9cc2e59)**:`app/service/embedding.py`(Ollama bge-m3 批量 /api/embed 1024 维,四类失败一律 EmbeddingError 不静默降级)+ `app/service/milvus_service.py`(kb_product_rules 幂等建集合+upsert+search_kb 溯源/effective_date 合规过滤)+ `data/kb/` 6 只种子产品手册(prospectus/fee/rule/risk 四节 24 块)+ `scripts/kb/build_kb.py`(--dry-run/--kb-dir)+ `app/service/rag_service.py` 落地(search_knowledge→chunks+source_refs,异常上抛防 LLM 编造)+ `app/tool/kb_tools.py` 挂注册表第三层(**ToolSpec 新增 skip_access_check**:公开知识无归属语义,advisor 无绑定客户可查;意图层限定 customer/advisor,risk 不开放——用户拍板)+ tool_node 按 spec 白名单注入 query + summarize 溯源口径。**真库验收:24 块入库,search_knowledge("基金申购") Top3 命中申赎规则(score 0.73+),溯源完整**。三坑收口:Milvus Lite 跨进程重开须显式 load / faiss 不支持中文路径(本机 .env 改 C:/Users/YUAN/.jinrong/milvus/)/ build_kb sys.path 引导。知识库 API(上传/重建端点)一期不做(knowledge.py 仍空壳,用户拍板),425 绿
|
- [x] T-21 Milvus Lite + kb_product_rules 首批入库 —— **完成(2026-09-07,commits e34973f~535c8a0 共 6 个 + 评审闭环 9cc2e59)**:`app/service/embedding.py`(Ollama bge-m3 批量 /api/embed 1024 维,四类失败一律 EmbeddingError 不静默降级)+ `app/service/milvus_service.py`(kb_product_rules 幂等建集合+upsert+search_kb 溯源/effective_date 合规过滤)+ `data/kb/` 6 只种子产品手册(prospectus/fee/rule/risk 四节 24 块)+ `scripts/kb/build_kb.py`(--dry-run/--kb-dir)+ `app/service/rag_service.py` 落地(search_knowledge→chunks+source_refs,异常上抛防 LLM 编造)+ `app/tool/kb_tools.py` 挂注册表第三层(**ToolSpec 新增 skip_access_check**:公开知识无归属语义,advisor 无绑定客户可查;意图层限定 customer/advisor,risk 不开放——用户拍板)+ tool_node 按 spec 白名单注入 query + summarize 溯源口径。**真库验收:24 块入库,search_knowledge("基金申购") Top3 命中申赎规则(score 0.73+),溯源完整**。三坑收口:Milvus Lite 跨进程重开须显式 load / faiss 不支持中文路径(本机 .env 改 C:/Users/YUAN/.jinrong/milvus/)/ build_kb sys.path 引导。知识库 API(上传/重建端点)一期不做(knowledge.py 仍空壳,用户拍板),425 绿
|
||||||
- [x] T-03 输入防护规则(F-03:prompt_injection/oversize/限流)—— **完成(2026-09-07,commits 497554d/65b45aa/cc6f34f/207fc79)**:`app/service/input_guard.py`(注入短语词表 42 条四类纯函数检测 + `inspect_message` oversize 4000 先于 injection + `check_rate_limit` Redis INCR 固定窗口 actor 级 30 次/分 fail-open)+ chat 路由接入(顺序:鉴权→准入→空白→限流 429→注入/超长 400→归属→会话;被拒 fail-fast 不建会话不落消息,blocked 落 input_guard_log,留痕降级不改拒绝语义;Pydantic 硬顶 20000,业务限 4000 移 guard 层换留痕)+ redis_gateway.incr + settings.guard_rate_limit_*;拍板:命中即拒不清洗、仅 blocked 留痕、词表代码常量可审计。**独立 AI 评审 PASS with findings(P0=0;P2×3 已收口:词表断言修正/补 7 条同构变体/窗口 TTL 断言+EXPIRE 失败取舍锁定;P3 已收 session_id 截断,挂账对抗变体扩表)**,378 绿
|
- [x] T-03 输入防护规则(F-03:prompt_injection/oversize/限流)—— **完成(2026-09-07,commits 497554d/65b45aa/cc6f34f/207fc79)**:`app/service/input_guard.py`(注入短语词表 42 条四类纯函数检测 + `inspect_message` oversize 4000 先于 injection + `check_rate_limit` Redis INCR 固定窗口 actor 级 30 次/分 fail-open)+ chat 路由接入(顺序:鉴权→准入→空白→限流 429→注入/超长 400→归属→会话;被拒 fail-fast 不建会话不落消息,blocked 落 input_guard_log,留痕降级不改拒绝语义;Pydantic 硬顶 20000,业务限 4000 移 guard 层换留痕)+ redis_gateway.incr + settings.guard_rate_limit_*;拍板:命中即拒不清洗、仅 blocked 留痕、词表代码常量可审计。**独立 AI 评审 PASS with findings(P0=0;P2×3 已收口:词表断言修正/补 7 条同构变体/窗口 TTL 断言+EXPIRE 失败取舍锁定;P3 已收 session_id 截断,挂账对抗变体扩表)**,378 绿
|
||||||
- [x] 风控阶段 C(C0 pytest-asyncio / C1 chat_tools / C2 risk 分支 StateGraph / C3 A-6 验收)—— **完成(2026-09-07)**:`app/service/risk/chat_tools.py` 四只读 Tool(alert_query/customer_context/suitability_check/aml_lookup)挂 `RISK_TOOL_REGISTRY`;`tool_service.run_tool` 改查 core+risk 统一注册表 `get_registered_tool` 且恒传 `risk_repo`;`_normalize_params` 读 spec 白名单;`match_intent` 按 agent 分组扩 risk 关键词;`agent_service.tool_node` 守卫放宽(`requires_customer=False` 允许无绑定客户,支撑 A-6 全量待审);A-6 验收+诱导处置边界(无处置 Tool、系统提示禁自动处置、诱导只触发只读且预警状态不变);**独立 AI 评审 PASS(P0=0,P2 补 advisor 归属/空 product_id 单测已收口),345 绿,tag `risk-m3`**
|
- [x] 风控阶段 C(C0 pytest-asyncio / C1 chat_tools / C2 risk 分支 StateGraph / C3 A-6 验收)—— **完成(2026-09-07)**:`app/service/risk/chat_tools.py` 四只读 Tool(alert_query/customer_context/suitability_check/aml_lookup)挂 `RISK_TOOL_REGISTRY`;`tool_service.run_tool` 改查 core+risk 统一注册表 `get_registered_tool` 且恒传 `risk_repo`;`_normalize_params` 读 spec 白名单;`match_intent` 按 agent 分组扩 risk 关键词;`agent_service.tool_node` 守卫放宽(`requires_customer=False` 允许无绑定客户,支撑 A-6 全量待审);A-6 验收+诱导处置边界(无处置 Tool、系统提示禁自动处置、诱导只触发只读且预警状态不变);**独立 AI 评审 PASS(P0=0,P2 补 advisor 归属/空 product_id 单测已收口),345 绿,tag `risk-m3`**
|
||||||
- [ ] 前端 React 多 Agent 入口(HashRouter,`web/` init)
|
|
||||||
|
|
||||||
### 风控模块(PRD v1.0 已冻结 · `docs/PRD/PRD-风控监测Agent.md`,事件驱动线不依赖 T-07 可先行)
|
### 风控模块(PRD v1.0 已冻结 · `docs/PRD/PRD-风控监测Agent.md`,事件驱动线不依赖 T-07 可先行)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# 合并注意事项 · 风控 Agent 模块并入 main(AL-09 执行手册)
|
||||||
|
|
||||||
|
> 版本:2026-09-07 v1.0(基于 `risk-control-agent` 分支 HEAD `cfbd056` 实测编制)
|
||||||
|
> 用途:**给合并执行人**——风控模块开发方已交付(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 = 追加需求)
|
||||||
Reference in New Issue
Block a user