Dev login no longer honors injected roles; self-service simulate/convert blocks R4 disclosure grades like the UI and chat already do. Reuse of a convert idempotency key with a different body returns 409. CT6 redeem qty is derived from T+2 lots instead of a fixed 35000; CT7-05 and CT10-07 assertions follow. Update project memory and v1.1 post-fix test artifacts.
282 lines
34 KiB
Markdown
282 lines
34 KiB
Markdown
# 项目记忆(人 + Agent 共用)
|
||
|
||
> 各阶段的**简化快照**(门闸索引)。只留基础信息,不写源文件正文。
|
||
> **新 Agent 无上下文:先读本节 → 第 0 节交接清单 → 按需打开源文件。**
|
||
|
||
------
|
||
|
||
## 0. 新 Agent 交接(5 分钟)
|
||
|
||
**项目是什么:** 金融四 Agent(客户财富 / 代理人 / 数据分析 / 风控)共用数据层与合规底座;**不**互调 LLM,跨 Agent 走 L1/L2/L3 画像与预警表。
|
||
|
||
**当前进度:** 需求与表设计已定 · **926 pytest passed**(全量 · **65 failed** 均为顾问 `test_sprint*` 集成)· **896 passed**(排除 `test_sprint*` · 仅 **`test_agent_kb_eval`** 红)· **27 Vitest** · **Redis @ 6380** · **`merger` 未 commit** · **前端设计栈补强未 commit(2026-09-13:Inter 自托管 + Radix 状态阶)** · **客户线交易 + 选购清单 + 持仓快照/行情快捷交易未 commit(2026-09-13)** · **顾问线已 fast-forward 合入 `merger`** · **端到端第三轮(真浏览器 + 真 HTTP)174 用例 161 PASS / 12 FAIL / 1 SKIP → 6 缺陷待修**([FE-001](tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md) · **D1 已关闭** ✅ · D2 KYC `created_at` · D3 Milvus 集合 `released` · ~~F1 转换页预置跨主体必失败~~ ✅ **第四轮复跑已转绿** · ~~F2 `alert_id`/`alert_ids` 字段名不匹配~~ ✅ **已转绿** · ~~F3 无路由级角色守卫~~ ✅ **已转绿** · F4 确认日默认越界)
|
||
|
||
**端到端第四轮(客户线交易 · 真浏览器 + 真 HTTP + 真库对账)**([CT-001](tests/2026-09-13-customer-trade-e2e/TEST-LOG-2026-09-13-CT-001.md) v1.2 · 初稿 203 用例 **162 PASS / 6 FAIL** → **同日复跑取证:Part A 161 行 135 PASS / 0 FAIL / 1 SKIP / 25 INFO(退出码 0)· Part B 48 行 41 PASS / 0 FAIL / 0 SKIP / 7 INFO(退出码 0)**)
|
||
- ✅ **P0 已修**:`jwt_service.infer_roles()` **忽略外部 `roles`**,只认 `DEFAULT_ROLES_BY_ACTOR`;未知 actor 登录 → 401。单测 `test_wave0_auth.py`
|
||
- ✅ **P1 已修**:自助通道 `simulate_self_service_blocked()`(`allowed_with_disclosure` / `requires_disclosure` / `needs_branch_confirm` 视同阻断)· `trade_gateway` + `convert_service` 转入端 · 单测 `test_trade_gateway` / `test_convert_accept`
|
||
- ✅ **L1 已修**:同 `client_request_id`、不同 body → **409 `IDEMPOTENCY_CONFLICT`**(`accept_convert` 比对四元组 · `CT7-05` 硬断言)
|
||
- ✅ **CT6 脚本已修**:`derive_redeem_qty()` 由 T+2 批次推导申报量(优先 FIFO 跨档),不再写死 `35000` · `CT10-07` 无赎回时 **SKIP**(避免空 PASS)
|
||
- ✅ **复跑已取证(2026-09-13 19:26)**:P0/P1/L1 三条**同期望值转绿**(退出码 1 → 0),**CT6 赎回覆盖缺口关闭**(组中止 SKIP → 7 PASS,含 FIFO 跨档 `30000+150` 与金额复算 `44922.38`);5 表还原核对 `95 / 59 / 73 / 19 / 0`
|
||
- ⚠️ **复跑新发现(需拍板)**:① **P0 只堵了方向①** —— `infer_roles` 已不信任入参,但 `/api/auth/login` 仍无 `app_env` 门禁、`main.py:103` 仍无条件挂载;② **P1 可能收窄业务能力** —— `allowed_with_disclosure` 被并入阻断 ⇒ R4 产品自助通道**完全不可下单**(原设计是「弹揭示书后可买」),需业务确认是否补揭示书续接流程;③ **`CT3-05` 顺序敏感** —— 15 分钟墙钟窗口 + `jinrong_agent` 永不还原 ⇒ 距上一轮 <15 min 复跑会假 FAIL(本轮踩过,已声明复跑口径)
|
||
- ⚠️ **仍开放**:**B1** 持仓 vs 批次和基线不一致(种子/历史态,非本轮引入)· **T1** `run_demo_smoke.ps1` 仅登录改 canonical(后续 `/api/v1/*` 仍 404)· 仓库外 `11-cross-role.mjs` **`C1.6` 陈旧断言** · **Redis 降级路径**(两轮均未跑,唯一未覆盖的功能路径)
|
||
- ⚠️ **证据链缺口(如实声明)**:`_raw/shots/` 的 11 张截图被 v1.1 复跑**就地覆盖**,v1.0 的修复前截图**不可恢复**;v1.0 结论仅有报告文本与 JSON 可查
|
||
- ✅ 初轮已证口径:前端渲染与后端 raw **核对到分** · 数据副作用可回滚 · 对话/挂单红线全绿
|
||
|
||
**工作分支:** 主线 **`merger`**(已纳入顾问线 + 基金转换线 · HEAD **`c09b987`**);保留 **`integrate/advisor-agent`** 作历史指针;历史 `risk-control-agent` 交付冻结。
|
||
|
||
**仓库地图:**
|
||
|
||
| 路径 | 状态 | 说明 |
|
||
| --- | --- | --- |
|
||
| `app/main.py` | **已集成(AL-09)** | 宿主 TraceMiddleware + 模块 audit/trace + 路由(auth/**platform**/chat/risk/simulate)+ lifespan |
|
||
| `app/api/auth.py` | **已实现(AL-09)** | Mock 登录;签发走 `auth_service.issue_dev_token`(与模块 API 同一 issuer) |
|
||
| `app/api/auth_adapter.py` | **已接线(S2)** | `module_auth_from_host()`:宿主 AuthContext → 模块 AuthContext |
|
||
| `app/gateway/` | **宿主 Wave 0(并存)** | jwt_service(**`infer_roles` 忽略 body.roles · 2026-09-13 CT-001 P0**)/ auth_deps / rbac / ownership;模块 API 走 `deps.py`,禁止模块 import gateway |
|
||
| `app/api/risk.py` `simulate.py` `deps.py` | **已实现** | 风控 4 API + 模拟网关 · **compliance/service_risk 矩阵(F2/F3)** · 台账 **`stats` 待审计数(F7)** |
|
||
| `app/api/chat.py` `audit_middleware.py` | **已实现** | POST /api/chat · **POST /api/chat/stream(customer 分流 → prepare_customer_stream)** · visitor · sessions 三端点 |
|
||
| `app/api/customers.py` `products.py` `advisors.py` `staff.py` `compliance.py` | **已实现(v0.1 + 行情历史)** | 代销平台 REST;`get_platform_auth_context`;**`GET /api/products/{id}/nav/history`**(RBAC · compliance 拒) |
|
||
| `app/api/analyst.py` `analyst_auth_adapter.py` | **已实现(S3+D-06 + N-03/N-07 + analyze)** | 问数/chat · **`POST /analyze`** · interpret · sample · escalate · dashboard |
|
||
| `app/api/advisor_*.py` `kyc.py` `market.py` `copy.py` 等 | **已合入 `merger`** | 对外 **`/api/advisor-agent/*`**(合规 · 话术 · 异动 · KYC · 复制门闸 · guard · dashboard/allocation ping);鉴权 **`advisor_auth_adapter`** + `get_platform_auth_context`;**不迁** `/api/v1` · demo_ui · `admin/audit-logs`。**端到端实测(v1.1):鉴权/合规/门闸/模板/防护/跨线回归全绿;市场异动 D1 已修转绿(10/10 + 浏览器 4/4);KYC 采集(D2)仍 500,语义检索(D3)仍静默降级**——[ADV-001](tests/2026-09-12-advisor-agent-e2e/TEST-LOG-2026-09-12-ADV-001.md) · [FE-001](tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md) |
|
||
| `app/advisor_db.py` `entities_advisor.py` `advisor_schemas.py` | **接缝已挂** | 顾问 ORM/会话工厂 · 与 merger `entities.AgentSession` 共用 `metadata_` 列名 |
|
||
| `scripts/agent/migrate-advisor-agent-sprint1-3.sql` | **已新增(待本机执行)** | 顾问专用表(compliance_rule · kyc_session · market_alert · script_template 等) |
|
||
| `app/api/ready.py` | **已实现(2026-09-11)** | `GET /api/ready`:Redis + 关键路由自检;前端 `DevReadyBanner` |
|
||
| `app/service/analyst_agent.py` `template_service.py` `cache_service.py` `analyst_chart.py` | **已实现(S3+D-06 + D-11)** | NL2SQL · **published few-shot 仅库** · `_nl_sql_hints` 双极值 UNION · 模板 · **`reload_published_assets`** · **`clarify` 结构化** · analyze 图表 |
|
||
| `app/api/knowledge.py` `admin.py` | 空壳 | 待审计查询台与知识库 API(T-21 拍板一期只做脚本入库,上传/重建端点不做) |
|
||
| `app/service/platform/` | **已实现(v0.1)** | 封装 core_ro + `PLATFORM_RESPONSE_DESENSITIZE` 脱敏开关 |
|
||
| `app/service/embedding.py` `milvus_service.py` `rag_service.py` | **已实现(T21-1/2/4)** | Ollama bge-m3 1024 维(失败不静默降级)/ kb_product_rules 建集合+upsert+合规过滤检索 / search_knowledge→chunks+source_refs 溯源 |
|
||
| `app/tool/kb_tools.py` | **已实现(T21-5)** | search_knowledge 对话 Tool(skip_access_check 公开知识;仅 customer/advisor 意图开放,risk 不开放);kb_product_rules 首批 24 块已入库(data/kb 6 产品手册,scripts/kb/build_kb.py 可重灌) |
|
||
| `app/service/auth_service.py` | **已实现(T-01)** | Auth SDK:JWT 验签(HS256 dev/RS256 生产)、必填 claims、jti 吊销(Redis fail-open);签发 CLI `scripts/dev/issue_dev_token.py` |
|
||
| `app/service/risk/*` + `service/suitability.py` | **已实现** | RISK-001~005 规则 / 预警聚合 / L3 写入 / AML / 引擎编排 / suitability(**阶段一换核:内核改调 core_ro.check_suitability,SUIT-001~008 已退役**)/ locks+redis_gateway 公共原语(B7) |
|
||
| `app/service/agent_service.py` `memory_service.py` | **已实现(T-07/T-06/T-04/C2 + 方案 C)** | LangGraph StateGraph(tool→llm→guard)+ DeepSeek(无 key 降级);T-04 tool 节点(关键词意图 customer/advisor/risk 分组 + tool_service.run_tool);C2 tool_node 守卫放宽(requires_customer=False 允许无绑定客户,支撑 A-6 全量待审);Redis 会话窗口 + MySQL 回源。**方案 C:`stream_chat` 生成器(Tool 同步跑完→逐块推 LLM 文本)+ `needs_disclaimer`(首帧 meta 与落库尾部共用口径)** |
|
||
| `app/service/tool_service.py` `app/tool/core_tools.py` `service/risk/chat_tools.py` | **已实现(T-04/C1)** | 对话 Tool 编排(统一注册表 get_registered_tool:core+risk / 归属校验 / agent_tool_call 落库)+ Core RO 三只读 Tool(L0/持仓/流水)+ C1 风控四只读 Tool(alert_query/customer_context/suitability_check/aml_lookup,RISK_TOOL_REGISTRY) |
|
||
| `app/repository/session_repository.py` | **已实现(T-06/T-04 + 前端接入 B/C)** | agent_session / agent_message / agent_tool_call 读写;**方案 B 增 `list_sessions`(分页+total)/ `list_messages_page`(seq 升序分页,勿与 LLM 窗口的 `list_messages` 混用)/ `close_session`(条件更新防并发)**;**方案 C 增 `insert_turn`(user+assistant 同事务落库 + 事务内取 seq,修评审 P0/P1)** |
|
||
| `app/gateway/gateway_repository.py` `trade_gateway.py` | **已实现(2026-09-13 持仓同步 + 自助适当性)** | 模拟交易网关 · **R4 揭示类自助阻断**(`simulate_self_service_blocked`)· 申赎 `_maintain_lots` 同步 `core_holding` |
|
||
| `app/repository/core_ro.py` | **已实现(2026-09-13 持仓补偿读)** | Core 只读 SELECT;**`list_holdings`(qty>0)** · **`list_holdings_from_lots_gap`**(批次有余量但快照未体现 · 历史只写 lot 的演示修复)· check_suitability / list_products_for_customer / list_trades / get_customer_l0 |
|
||
| `app/service/platform/customer_service.py` | **已实现(v0.1 + 持仓合并)** | `list_holdings` 合并 gap 行并按净值估市值 · L0/流水/可购产品 |
|
||
| `app/repository/risk_repository.py` | **已实现** | risk_alert / … · **`list_alerts` 须 `RiskListAccess`(F1)** · **`status=handled` 聚合筛选** · `count_pending_stats` |
|
||
| `app/repository/repo_access.py` | **已实现(2026-09-11)** | `RiskListAccess` / `ThresholdWriteAccess` 仓储调用凭证 |
|
||
| `app/repository/threshold_repository.py` | **已实现** | 阈值配置 · **`upsert_portfolio` 须 `ThresholdWriteAccess`** |
|
||
| `app/utils/` | **基本就绪** | trace(trace_id+request_id 双 contextvar)/ desensitize / db(引擎工厂)/ response(统一错误体+4xx/500 handler)/ exceptions(含 ApiError)已实现;logger 占位 |
|
||
| `app/config/database.py` | **已实现** | MySQL 双引擎 + **Redis 单例**(`REDIS_URL` · **RESP2 `protocol=2`** 兼容 Docker Redis 7 / 旧 Windows Redis 3) |
|
||
| `app/config/settings.py` | **已实现** | 双库 + risk_* 阈值 + JWT + **customer/visitor/profile** 字段 + `kb_root_dir` |
|
||
| `app/service/customer_service.py` `visitor_service.py` | **已实现(S2 + Wave3 + 交易 + 问候快路由)** | 客服 14 节点 + **`trade_prepare`/`process_trade_turn`** · **C-04/C-05/C-11** · **选购清单 `fact_text` 不经 LLM 改写**(防压成「能买几只」)· **`trade_dialogue_should_continue` 续轮** · 问候 `chit_chat` · 游客 9 节点;`sanitize_postprocess`(1B);RAG **fin_* 三库** |
|
||
| `app/service/trade_flow_service.py` `trade_action_service.py` | **已实现(2026-09-13 · 未 commit)** | Redis 交易抽槽 · 菜单序号解析 · **`restore_flow_from_context`**(Redis 丢态从助手菜单恢复)· 申购/赎回/转换草稿 · **C3×R4 揭示类 `subscribe_suitability_block`** · 与 `simulate` 字段对齐 |
|
||
| `app/tool/trade_tools.py` `app/tool/core_ro_tool.py` | **已实现(扩展)** | 顾问 `prepare_simulate_trade` · **适当性:多 R 列清单** · **无参「我能买什么」→ `_list_purchasable_product_catalog`(【R1】… 全局序号 + PROD 编号 · 回复序号进申购)** |
|
||
| `web/src/pages/customer/CustomerTradePage.tsx` `CustomerTradesPage.tsx` `TradeConfirmModal.tsx` `tradeEligibility.ts` `tradeEvents.ts` | **已实现(2026-09-13 · 未 commit)** | 交易中心三 Tab · 适当性标签 · **`simulate` 须 CUST-* 客户 JWT**(非客户顶栏警示)· 确认成功 **`jr:trade-completed`** → **首页/持仓/交易明细** 刷新 · Modal 成功态自关(父页不再抢先关窗)· Chat **`pending_trade`**(spec [customer-trade-design](../superpowers/specs/2026-09-13-customer-trade-design.md)) |
|
||
| `web/src/components/trade/TradeProductActions.tsx` · `ProductNavDetailPage` · `MarketQuotesPage` | **已实现(2026-09-13 · 未 commit)** | **客户角色**:净值详情「快捷交易」三按钮(申购/赎回/转换)· 行情列表列 **申购·走势/赎回·转换**(赎回建议在详情看持仓份数) |
|
||
| `scripts/dev/restart-dev.ps1` `restart-dev.bat` | **已增强(2026-09-13)** | 重启 uvicorn + Vite · **不启动 Redis**(须先 `start-redis.ps1` 或 `docker compose up -d redis`)· 结束时 **探测 `api/ready` checks.redis** 并黄字提醒 · `.bat` 可双击 |
|
||
| `scripts/dev/start-redis.ps1` | **已实现** | Docker `jinrong-redis` · **6380→6379** · `.env REDIS_URL=redis://127.0.0.1:6380/0` |
|
||
| `app/service/threshold_service.py` | **已实现(C-04)** | L1 `threshold_pref_summary` → `customer_threshold_config`;持仓查询加权盈亏 vs 阈值 → `customer_notify_log` |
|
||
| `app/utils/sanitize_postprocess.py` | **已实现(1B 共用)** | 数据查询 intent(含 nav_query)违禁 → 回退 fact_text;RAG/闲聊 → COMPLIANCE_REJECT;均不自动 transfer |
|
||
| `scripts/core/*.sql` + `reset.ps1` | **已实现** | Core 模拟库 DDL + 种子 · **`07-seed-nav-history.sql`(14 产品 ×364 日)** · 再生 `seed_nav_history.py --export-sql` |
|
||
| `scripts/agent/` `scripts/demo/` `scripts/dev/` | **已实现** | **`prepare_all.ps1`** · **`push_threshold_alerts.py`** · **`seed_analyst.ps1`** · **`sandbox_risk_test.py`** · `run_query_battery.py`(**不入库**) |
|
||
| `scripts/sync/*.py` | **已实现** | 归属同步 + Neo4j 全图 |
|
||
| `tests/` | **已实现** | **926+ 用例**(含顾问 sprint)· merger 回归 **896 绿**(`-k 'not test_sprint'` 口径:`--ignore-glob=test_sprint*.py`)· 问数 [AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md) |
|
||
| `docs/项目框架设计/理财顾问Agent-合并说明.md` | **实施中** | D1–D9 拍板 · 接缝清单 · 与 `docs/superpowers/plans/2026-09-12-advisor-agent-merge.md` 对齐 |
|
||
| `docs/答辩/` | **答辩手册 + Demo SOP + 幻灯片 + 答辩稿 + 功能测试** | [`README.md`](答辩/README.md) · 知识点清单 · `DEMO-SOP-*` · `presentation/index.html` · `答辩稿.md` · `DEMO-功能测试流程.md` |
|
||
| `docs/course/` | **交互课程集** | 导览中心 + 总览 **8 模块** + 问数 **5 模块**(D-06)+ 风控深潜 **7 模块** · 与答辩清单同步 |
|
||
| `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/项目框架设计/合并注意事项-风控模块并入main.md` | **AL-09 已执行(2026-09-08)** | 合并接线完成;接缝见《风控Agent模块边界与合并接缝标注.md》 |
|
||
| `docs/项目管理/04-从需求到公共API开发方法.md` | **已定(2026-09-08)** | 需求→矩阵→存储→Service→API→Agent 主线;Phase A 清单 |
|
||
| `docs/项目框架设计/接口契约-代销平台API-v0.1.md` | **已定(2026-09-08)** | 代销平台 REST canonical 路径、命名规范、Agent 迁移表 |
|
||
| `docs/项目框架设计/C-05-行情数据源选型对比.md` | **已定(2026-09-09)** | C-05 净值数据源分阶段选型;禁止爬虫/前端直连第三方 |
|
||
| `docs/项目框架设计/接口契约-代销平台API-v0.2-行情扩展草案.md` | **草案(2026-09-09)** | `nav-snapshot` · `sync_market_nav` · 前端产品行情 Phase B |
|
||
| `docs/项目框架设计/表设计/` | 已定 | Agent 共用 11 表 + agent 专用 SQL |
|
||
| `docs/项目框架设计/Core模拟底座/` | 已定 | 无真实 Core 时的 L0 方案 |
|
||
| `web/` | **P0 + 行情详情图表 + 客户快捷交易(2026-09-11/13)** | **`/app/market/:productId`**:走势图表 + **TradeProductActions** · 列表客户列三链 · **DevReadyBanner** · `restart-dev.ps1` 校验 `nav/history` |
|
||
| `web/src/styles/tokens.css` `src/theme.ts` | **字体/状态阶(2026-09-13)** | **Inter Variable 自托管**(`@fontsource-variable/inter` · 字体栈已提到最前 · **字族名带 ` Variable` 后缀**,写 `"Inter"` 匹配不上)· **Radix Colors 只引 `slate`/`jade`**,补 6 个状态阶 token(**11 个品牌色一律未替换**)· 选用依据与「色温陷阱」见 [TODO 2026-09-13](TODO.md) |
|
||
|
||
**本地 bootstrap(首次):** 完整步骤与前置说明见 `FLOW.md` §0(权威),速览:
|
||
|
||
```text
|
||
1. cp .env.example .env → 填 MYSQL_PASSWORD、NEO4J_PASSWORD、DEEPSEEK_API_KEY
|
||
2. pip install -r requirements.txt
|
||
3. .\scripts\core\reset.ps1 # 建 jinrong_core(含 07 净值历史 ~365 日/产品)
|
||
4. mysql … < 01-mysql-共用底座.sql # jinrong_agent 共用 11 表
|
||
mysql … < 02-mysql-agent专用.sql # 风控四表 + risk_aml_list
|
||
mysql … < scripts/agent/migrate-advisor-agent-sprint1-3.sql # 投资顾问专用表(合并后必跑)
|
||
5. mysql … < scripts/agent/seed-aml-list.sql # AML 名单(Windows 乱码:`python scripts/dev/fix_utf8_seed.py`)
|
||
python scripts/seed/import_compliance_rules.py # 顾问合规规则(源:`docs/开发文档/20-Sprint1首批合规规则数据集.md`)
|
||
.\scripts\demo\seed_advisor_agent.ps1 # 一键:迁移 + 规则 + 话术 + 演示审核(推荐)
|
||
.\scripts\demo\seed_advisor_agent.ps1 # 一键:迁移 + 规则 + 话术 + 演示审核(推荐)
|
||
(风控演示:`.\scripts\demo\prepare_all.ps1` 或 `prepare_risk_demo.sql` · PRD §10.2)
|
||
6. python scripts/sync/sync_advisor_rel.py && python scripts/sync/sync_neo4j.py
|
||
7. `docker compose up -d redis`(或 `.\scripts\dev\start-redis.ps1`)→ **REDIS_URL=redis://127.0.0.1:6380/0**(Docker Redis 7;避开本机 Windows Redis 占 6379)
|
||
8. uvicorn … · python -m pytest(**merger 回归 ~896 绿**;全量含 sprint **926 passed / 65 failed**);问数答辩:`docs/答辩/DEMO-SOP-问数.md` · 模板种子 **`scripts/agent/seed-analyst-query-templates.sql`**
|
||
```
|
||
|
||
**AL-09 合并后架构(一句话):** 宿主 `gateway/` + 模块 `deps.py` **双栈并存**;对外登录/token **统一**;chat/risk 均走模块鉴权;接缝 S2 用 `auth_adapter`。
|
||
|
||
**下一步(见 TODO):** **修 F1/F2**(演示可见 · 改动面极小)→ D2 → F4 → F3 → D3 · git commit `merger` · battery · 客服验收 · D-12 往后排
|
||
|
||
**⚠️ 前端 E2E 覆盖现状:** **2026-09-12 第三轮已完成顾问前端四页 + 风控前端六页的逐功能点按**(真浏览器 · 47 用例,见 [FE-001](tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md)),**两个 SSE 对话页与客户线仍属 2026-09-10 的「仅能渲染」口径** —— 接口错误态、对话多轮/会话管理、数据与后端 raw 对账、排序分页正确性等**仍未验证**(CHAT-1~4 就是这样漏掉的)。**未跑清单见 `TODO.md` §「前端 E2E · 未跑测试」**,旧报告见 `docs/整体测试/前端整体测试交接.md`。
|
||
**⚠️ 本轮已知复现性缺口:** 浏览器脚本(`09/10/11-*.mjs`)在**仓库外** `C:/Users/Windows/e2e-jinrong/`,他人 clone 拿不到 → 已挂 `TODO.md`「E2E 最小集进仓库」P0。
|
||
|
||
**Redis(2026-09-09):** 推荐 **Docker** `jinrong-redis`(`redis:7-alpine`)· 宿主机 **6380** → 容器 6379 · `.env` `REDIS_URL=redis://127.0.0.1:6380/0` · 客户端 **RESP2**(`database.py` / `redis_gateway.py`)。
|
||
|
||
**Redis 不加速页面看板(2026-09-10 澄清):** Redis 管 **Chat 会话窗口 / 问数 D-06 结果 / 限流 / L3 热读**;**平台 GET(持仓/净值/预警列表)与 Dashboard hooks 每次进页仍打 MySQL**,前端无跨路由缓存 · 净值 **`fetchNavMap` 按产品 N 次 HTTP** → 体感「每页都转圈」见 `TODO.md` §2026-09-11 · `FRONTEND-HANDOFF.md` §10。
|
||
|
||
**前端启动(`web/`):** `npm install` → `npm run dev`(`5173`,`/api` 代理 `8000`)· 验收四 demo 账号见 **`docs/frontend/FRONTEND-HANDOFF.md` §8** · 改 UI 后跑 `npm run build && npm run test && npm run lint`。
|
||
|
||
**平台 API 硬规则(2026-09-08 拍板):** 路由 **A · 按业务域**(`/api/customers` 等);与 Agent 功能重复时 **以本平台 API 为准**;命名见契约 §2;合并时统一改 canonical 路径。
|
||
|
||
**禁止(改代码前必记):** Core 正式 C1~C5 不可被画像覆盖 · 审计表只 INSERT · 代理人草稿不外发 · 仅 R-02 可阻断交易 · 四 Agent 不互调 LLM。
|
||
|
||
**里程碑 tag 中文对照(tag 本体保留英文原名——git 技术标识符需跨平台/脚本稳定引用,符合「技术字面量保留英文」约定;中文名经对照表统一):**
|
||
|
||
| tag | 中文名 | 状态 |
|
||
| --- | --- | --- |
|
||
| `risk-m1` | 阶段A · 适当性校验可用 | 已补打(2026-09-07,指向阶段 A 完成提交 `3c07de6`,历史归档) |
|
||
| `risk-m2` | 阶段B · 事件线全链路 | 已打(2026-09-07,附注含验收走查记录) |
|
||
| `risk-m3` | 阶段C前半 · 对话线闭环 | 已打(2026-09-07,指向 C1~C3 完成提交) |
|
||
| `risk-m4` | 追加需求 · C4~C6(FR-8/9/10) | 已打(2026-09-07,annoted tag 指向 `323d98b`,仅本地未 push;C4 `fe4801b`/C5 `90d0660`/C6 `66ec7eb` 三提交 + 文档落账 `323d98b`,全量 482 绿,挂账 #1~#9 核对无违规) |
|
||
| `risk-align1`(拟) | 阶段一 · 对齐 main 基准 | 待定(AL-01~08 已完成,是否为此打 tag 由用户拍板;当前仅 AL 逐项 commit) |
|
||
|
||
------
|
||
|
||
## 1. 项目简介
|
||
|
||
- **名称:** JinRong 金融四 Agent 智能管家
|
||
- **当前阶段:** **代销平台 v0.1 + AL-09 + 客服 Wave3 + 客户交易/选购清单(2026-09-13)+ 问数 D-06/D-11 + 投资顾问 Agent 接缝(2026-09-12)**
|
||
- **当前优先级:** **CT-001 复跑已完成** ✅ · **merger commit**(客户线 + CT 收口 + 字体栈 —— 现在可以提交了对某个确定 SHA 负责)· 复跑新发现三条待拍板(P0 补方向②③ / P1 业务口径 / `CT3-05` 顺序敏感)· F4/D2/D3 · battery · sprint pytest
|
||
|
||
------
|
||
|
||
## 2. 阶段快照
|
||
|
||
| 阶段 | 当前一句话 | 源文件 |
|
||
| --- | --- | --- |
|
||
| 服务对象大环境 | 公募四类角色;**无真实 Core**,L0 由 `jinrong_core` 模拟库供给 | `ENVIRONMENT.md` |
|
||
| 需求目的 | 四 Agent + 统一数据层 + 合规可审计;Wave 0~3 P0 见 REQUIREMENTS | `REQUIREMENTS.md` |
|
||
| 项目框架 | FastAPI 分层 + LangGraph + MySQL 双库/Redis/Milvus Lite/Neo4j + React | `FRAMEWORK.md` |
|
||
| 实现流程 | Gateway JWT → chat → LangGraph → Tool → 审计;bootstrap 见 FLOW §0 | `FLOW.md` |
|
||
|
||
------
|
||
|
||
## 3. 约束
|
||
|
||
**硬阀门:技术选型**
|
||
|
||
`docs/项目框架设计/技术选型和版本/01-技术栈与版本.md` 中已标「已定」视为用户确认;新增依赖须再确认。
|
||
|
||
**禁止触碰:**
|
||
|
||
```text
|
||
Core 正式 C1~C5、持仓/交易真账(Agent 只读;当前为模拟库)
|
||
audit_log 等审计表(只 INSERT)
|
||
代理人草稿自动外发客户
|
||
风控自动冻户 / 改正式风险等级
|
||
各 Agent 自建第二套 JWT/RBAC
|
||
```
|
||
|
||
**高风险(改前需确认):** 数据库表结构、JWT/RBAC、部署密钥、删生产数据。
|
||
|
||
**开发开关:**
|
||
|
||
| 项 | YES / NO |
|
||
| --- | --- |
|
||
| 允许新增依赖 | YES(对齐技术选型文档) |
|
||
| 允许重构 | YES(最小范围) |
|
||
| 允许改表 / schema | 需确认 |
|
||
| 允许改接口协议 | 需确认 |
|
||
|
||
**特殊规则:**
|
||
|
||
```text
|
||
四 Agent 不互调 LLM;跨 Agent 走 L1/L2/L3 画像与预警表
|
||
客户 Agent:无投资建议/收益承诺/自动下单
|
||
代理人:不对 C 端直发
|
||
数据分析:仅 SELECT,不处置预警
|
||
画像不得覆盖 L0 正式测评
|
||
```
|
||
|
||
**客服合规拍板(2026-09-10 · 已落地):**
|
||
|
||
| ID | 决策 | 代码落点 |
|
||
| --- | --- | --- |
|
||
| **1B** | 数据查询 intent(持仓/流水/风评/适当性/**净值**)经 `sanitize_reply` 命中违禁词 → **回退 `fact_text`,不转人工**;RAG/闲聊命中 → `COMPLIANCE_REJECT`,**也不自动 transfer**;**customer + visitor 共用** | `app/utils/sanitize_postprocess.py` · `finalize_sanitized_reply` |
|
||
| **R1** | L1 `product_preferences` / `excluded_products` 合并时写 `items_meta`;注入 prompt **Top-K + 时间衰减 + TTL**(K=3 · TTL=90d · 半衰 30d) | `profile_service` · `settings.profile_preference_*` |
|
||
| **C-04** | 持仓内联提醒 + **演示 push**:`POST /api/customers/{id}/threshold-check?push=` · `push_threshold_alerts.py` · 持仓页按钮(**无定时 cron**) | `threshold_service` · `customers.py` |
|
||
| **C-05** | 「最新净值/单位净值」→ Core `get_latest_nav`(快照,非实时盘口);**「实时净值」仍 reject** | `core_ro_tool.query_product_nav` · intent `nav_query` |
|
||
| **C-11** | 「我能买什么/有什么可以买」→ `suitability_check` · **按 R1–R5 列产品名 + 全局序号 + `PROD-*` 编号**(非各档「能买 N 只」计数);回复序号接交易菜单(仅 **可直接申购** 进金额;**揭示/双录** 引导代理人;**forbidden** 拦截)· **「推荐稳赚/买什么好」仍 reject** | `core_ro_tool._list_purchasable_product_catalog` · `customer_prompts._ELIGIBLE_PRODUCTS_KW` · `trade_flow_service.parse_product_menu_from_context` |
|
||
| **客户交易(2026-09-13)** | 助手内 **不** 聊天打字确认下单 · **Modal + POST simulate**;多轮抽槽 Redis + 上下文恢复;见 spec | `docs/superpowers/specs/2026-09-13-customer-trade-design.md` · `trade_action_service` · `chat` SSE `pending_trade` |
|
||
| **客户交易 · 持仓与 UI(2026-09-13)** | **展示口径**:`GET .../holdings` = `core_holding`(qty>0)**∪** 批次 gap 补偿(`list_holdings_from_lots_gap`)· 新单网关 **`apply_holding_*`** 写快照 · 前端 **`subscribeEligibility`**(`requires_disclosure` 按 0/1)· **`jr:trade-completed`** 刷新看板+**交易明细** · 演示须 **CUST-\*** 登录否则 simulate 403、流水不会出现 | `customer_service.list_holdings` · `gateway_repository` · `CustomerTradesPage` · `tradeEvents.ts` |
|
||
| **C-07** | 风评查询走 Core;**「重新测评/重做风评」** → 引导 App/网点(Agent 内不做问卷) | `customer_prompts._RISK_KW` |
|
||
| **C-08** | 仅 L1 槽位 `investment.allocation_target`(13 槽);**无自动偏离检测/调仓** | `profile_slots.py` |
|
||
| **问数 vs 分析对话** | 问数页 · **`/interpret`** · **`/analyze` 对话框(文/图)** · N-03/N-07 · 分析对话 URL 重定向问数 | spec `2026-09-11-query-interpret-split` · `2026-09-12-analyst-query-visualization` |
|
||
| **问数 Demo(2026-09-12)** | **`match_phrases` 原句命中** · `GET /template-prompts` · 问数页标星/最近(**localStorage,非模板**)· UNION 括号 · 分析 **`POST /analyze`** | spec + [TEST-LOG-AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md) |
|
||
| **问数 NL2SQL(2026-09-12)** | **复合问不走模板** · **published few-shot / dict** · 模板 **published + match_phrases** · 问数 **clarify 可点选** | MEMORY §D-11 · `metric_ambiguity.py` |
|
||
| **客户「趋势/走势」** | **平台行情详情**:`nav/history` + **区间(1M~ALL)/粒度(日周)/图型(走势/涨跌柱/组合)** · Chat 仍无历史 Tool · Phase B 外部 sync 未做 | 见 `web/src/utils/navChartSeries.ts` |
|
||
| **L0 优先** | 抽槽与 L0 撞车**永远听 L0**;L1 只 enrich 措辞 | `profile_slots` D7 |
|
||
|
||
------
|
||
|
||
## 4. 入口与运行
|
||
|
||
```text
|
||
后端入口:app/main.py · 配置 app/config/settings.py · Core 只读 app/repository/core_ro.py
|
||
Agent 库 SQL:docs/项目框架设计/表设计/01-mysql-共用底座.sql · 02-mysql-agent专用.sql(含 risk_aml_list)
|
||
Core 模拟:scripts/core/reset.ps1 · 文档 docs/项目框架设计/Core模拟底座/
|
||
种子:scripts/agent/seed-aml-list.sql(AML 名单)· scripts/demo/prepare_risk_demo.sql(reset 后重跑)
|
||
依赖:requirements.txt(LangGraph + langchain-core/openai + FastAPI + SQLAlchemy)
|
||
启动:uvicorn app.main:app --reload → GET /health · **GET /api/ready**(环境自检)
|
||
Redis:`docker compose up -d redis` · `REDIS_URL=redis://127.0.0.1:6380/0` · `scripts/dev/start-redis.ps1`
|
||
测试:python -m pytest(**926 passed / 65 failed / 1 skipped** 全量 · **896 passed** 不含 `test_sprint*`;集成需 MySQL + 顾问迁移 SQL + AML + 风控演示数据)
|
||
风控沙盘:`python scripts/dev/sandbox_risk_test.py`(TEST-RISK-001 · **`:325-326` 断言已腐化**:仍期 `convert` → 400,`03fce88` 后合法受理为 202)
|
||
真实 HTTP E2E:`python scripts/dev/advisor_e2e_smoke.py` · `python scripts/dev/risk_e2e_smoke.py`(**需 uvicorn 已起** · 退出码 0 全过 / 1 有 FAIL / 2 前置失败 · `--only R6` 单组 · `--report <path>`)
|
||
浏览器 E2E(**仓库外**):`cd C:/Users/Windows/e2e-jinrong && node 09-advisor-pages.mjs && node 10-risk-pages.mjs && node 11-cross-role.mjs`(**须先起 Vite 5173**)
|
||
前端:cd web && npm run dev · npm run build/test/lint(**27** Vitest)· 四角色 Demo 见 **`docs/frontend/FRONTEND-HANDOFF.md` §8** · 本地后端 **`scripts/dev/restart-dev.ps1 -Backend Local`**
|
||
问数模板:mysql … < scripts/agent/seed-analyst-query-templates.sql
|
||
风控一键灌库:.\scripts\demo\prepare_all.ps1
|
||
运维/演示脚本:scripts/demo/subscribe_alerts.py(订阅推送演示)· rebuild_alerts.py TRD-xxx(引擎异常补偿重放)
|
||
JWT 联调:python scripts/dev/issue_dev_token.py --sub STAFF-30001 --roles risk_officer(+ Authorization: Bearer + X-Agent-Type)
|
||
配置:.env(见 .env.example)
|
||
RBAC 联调账号:scripts/dev/rbac-seed-reference.md
|
||
```
|
||
|
||
------
|
||
|
||
## 5. 文档资产约定
|
||
|
||
| 文件 | 何时读 |
|
||
| --- | --- |
|
||
| `docs/memory/MEMORY.md` | **每次任务先读**(本文件) |
|
||
| `docs/memory/REQUIREMENTS.md` | 对照场景 ID(F/C/A/D/R)与 Wave |
|
||
| `docs/memory/FRAMEWORK.md` | 分层、选型、模块、**实现状态表** |
|
||
| `docs/memory/FLOW.md` | 端到端链路 + 本地 bootstrap |
|
||
| `docs/memory/ENVIRONMENT.md` | As-Is 业务环境与 Core 模拟说明 |
|
||
| `docs/memory/TODO.md` | 当前待办与已完成 |
|
||
| `docs/PRD/PRD-风控监测Agent.md` | 风控 PRD v1.0(已冻结;FR-1~FR-7 + §8 验收表) |
|
||
| `docs/PRD/附-风控规则表.md` | RISK-001~005 / SUIT-001~008 / AML 规则权威 |
|
||
| `docs/项目框架设计/开发计划-风控模块.md` | 风控分阶段计划(阶段 A/B/C + 挂账登记 + B7~B9b 复审记录)**风控开发必读** |
|
||
| `docs/项目框架设计/演示SOP-风控模块.md` | 演示/走查操作手册(重灌 + A-1~A-9 步骤 + 核查单结论);**跑集成测试前先按 §2 重灌** |
|
||
| `docs/项目框架设计/架构设计-风控模块.md` | 风控模块架构(§3.1 编排 / §5 service 职责) |
|
||
| `docs/需求拆解/` | 业务原文(场景、矩阵、合规) |
|
||
| `docs/项目框架设计/` | 表结构、JWT 手册、Core 模拟、技术版本 |
|
||
| `docs/项目管理/04-从需求到公共API开发方法.md` | 搭公共底座/API 前;新人 onboarding |
|
||
| `docs/项目框架设计/接口契约-代销平台API-v0.1.md` | 写/Review 代销平台 REST;Agent 合并对照 canonical 路径 |
|
||
| `docs/项目框架设计/C-05-行情数据源选型对比.md` | C-05 行情/净值数据源拍板与禁止项 |
|
||
| `docs/项目框架设计/接口契约-代销平台API-v0.2-行情扩展草案.md` | Phase B `nav-snapshot` 与 sync 脚本契约(未实现) |
|
||
| `docs/frontend/FRONTEND-HANDOFF.md` | **改 `web/` 必读**:启动/分层/设计令牌/组件边界/浏览器验收清单 |
|
||
|
||
缺 `docs/memory/*` 文件:按 project-memory-kit 同名补回,**禁止空模板盖进度**。
|
||
|
||
------
|
||
|
||
## 6. 协作口令
|
||
|
||
【大环境】→ ENVIRONMENT · 【需求讨论】→ REQUIREMENTS · 【框架讨论】→ FRAMEWORK · 【实现流程】→ FLOW · 【Plan】→ TODO
|
||
|
||
------
|
||
|
||
## 7. 阅读完成门闸(Agent)
|
||
|
||
1. 四个 Agent 服务谁、禁止什么?
|
||
2. 改动属于 api / service / tool / repository 哪一层?
|
||
3. 是否需 customer_id 归属与 JWT RBAC?
|
||
4. Core 是模拟库只读还是 agent 库读写?
|
||
5. 如何验证?(`python -m pytest` · 顾问冒烟 **`tests/test_sprint0_foundation.py`** · **`from app.main import app`** → OpenAPI **62** 路径 · `cd web && npm run test` **27 绿** · Redis **6380** · `/api/ready` · 问数 [AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md) · **真实 HTTP E2E `python scripts/dev/{advisor,risk}_e2e_smoke.py`**(需 uvicorn 起着 · 退出码 0/1/2)· 浏览器 E2E 见 [FE-001](tests/2026-09-12-agent-frontend-e2e/TEST-LOG-2026-09-12-FE-001.md) · 合并说明 **`docs/项目框架设计/理财顾问Agent-合并说明.md`**)
|
||
|
||
大任务:FRAMEWORK/FLOW 与实现状态不符时先更新 memory 再编码(用户确认跳过除外)。
|