Files
group_fqcd_jr/开发文档/D4.4-投顾模块清除范围与影响面清单-2026-09-17.md
张胜宇 bc61d5c579 docs: 入库权威文档目录(客服agent/ 24 份 + 开发文档/ 50 份,替换旧命名的过期副本)
## 为什么做这一步

权威文档 74 份此前**只在本机**,评审者 clone 分支后看不到任何设计文档;而仓库里那两份同名目录
是 **2026-09-16 之前的过期副本,连文件名都是旧的**(无体系编号)。本次按「**权威覆盖过期**」入库。

## 入库内容

| 目录 | 文件数 | 体积 | 说明 |
|---|---|---|---|
| `客服agent/` | 24 | 0.77 MB | `D2.1`~`D2.6` 对外交付四件套 + 演示脚本/答辩报告 + `_build` 构建工具 |
| `开发文档/` | 50 | 2.16 MB | `D1.x` 索引与决策、`D3.x` 方案、`D4.x` 清除与重构留痕、`D5.x` 业务流程、`D6.x` 业务事实基座、`D7.x` 交付物、`D8.x` 规范 |

**旧的过期副本整体移除**(`客服Agent执行Todolist.md` → `D2.1-客服Agent执行Todolist.md` 之类
的改名 + 新增 `D2.5`/`D2.6`),入库后目录内容与权威副本**逐文件一致(零差异,已复核)**。

## 入库前的安全扫描(必须留痕)

- 扫描规则:`sk-` 类密钥 / `Bearer` 长串 / `password=`、`api_key=` 赋值 / 会话中出现过的两把明文 key 片段。
- 结论:**真实密钥只出现在 `.env`**(已被 `.gitignore` 命中,未入库);`.env.example` 与
  `config/risk.env.example` 只有**空占位**。
- 文档内唯一命中是 `D3.1` 里一处**截断的示例 JWT**(`Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...`),
  末尾带省略号,是接口文档的示意值,**不是可用凭据**。
2026-09-20 15:03:15 +08:00

18 KiB
Raw Permalink Blame History

投顾模块清除:范围与影响面清单

体系编号:D4.4 · 域:四、清除与重建留痕 · 编号体系见 D1.1 §4.0

编号:CS-PURGE-2026-012 日期:2026-09-17 触发:用户要求「参考《客服与投顾模块重构前代码清理建议-2026-09-15.md》,将『投顾』模块从项目中完整清除」 性质:只读清点 + 范围界定。尚未执行任何删除——因为清点过程中发现按名字删会拆掉 MVP 的硬阻断,须先与你确认边界 被参考的文档:开发文档/客服与投顾模块重构前代码清理建议-2026-09-15.md(下称《清理建议》)


0. 结论前置(请先看这三条)

① 你给的这份文档,不支持「整模块删除」

《清理建议》的性质是「死代码清理」,不是「模块拆除方案」。它的 §二「建议移除清单」里真正属于投顾的只有 C1(灰度闸门 63 行);而它对投顾另外两项的结论是:

《清理建议》条目 对投顾的结论
C1 投顾灰度闸门(advisor_rollout_service.py) 可删,但风险中,须先确认「灰度是已结束还是尚未开始」
C2 投顾本地演示引擎(advisor-engine.js + ?demo=1) 明确「不建议直接删」——「仍在活跃使用,不是死代码」;且它兼任「未登录/无 dbId 时的回退」
C3 前端 ?v= 版本号 「保留」——是 ESM 缓存破坏机制,不是冗余
§四.7 「投顾前端(2045 行)建议单独立项」

它真正对本任务有用的部分,是 §一 的模块清单(后端 7 文件 / 前端 9 文件)——本文档就是用这份清单做的起点。

② 🔴 头号风险:「投顾」这个名字在代码里对应两类完全不同的东西

按名字删(删掉一切带 advisor 的文件)会同时删掉产品数据底座,其中包括 MVP 的硬阻断实现。详见 §3。

③ ⚠️ 与 10 分钟前刚拍板的一项决策冲突

D3.4-客服Agent重构Todolist.md v5.1 §9-3(今日 10:00 前已拍板、且已写进三份文档)明确:

「先重建客服、投顾留到最后」——投顾是唯一完好业务线,是改 6 个底座文件时的对照组。

现在删掉投顾,等于在动 6 个底座文件之前先拆掉唯一的对照组。详见 §8。

⇒ 我的建议:先确认边界(§4)+ 决定时点(§8),再动手。删除不可逆(本机 git 写被沙箱拦截,无 git revert 可用)。


1. 投顾模块的真实规模(清点结果,比你给的清单更大)

类别 数量 说明
后端业务文件 约 20 个 《清理建议》列了 7 个;实际清单见 §4
前端文件 9 个 app/static/portal/employee-advisor/dashboard/**(整目录)
alembic 迁移 15 个 20260910_advisor_*.py × 12、20260911_advisor_*.py × 2、merge_advisor_risk_heads.py
数据库表 21 张 advisor_* 见 AGENTS.md §E(投顾 21 张,不进 docs/00 基线)
tools 脚本 7 个 bootstrap_advisor_demo / grant_advisor_role / publish_advisor_demo_config / seed_advisor_demo / sync_advisor_market_data / sync_advisor_market_quotes / (+ check_portal_modules.py 内引用)
测试文件 7 个 见 §5.4
RBAC 权限码 4 段 9020-9034、9041-9043、9057-9059、9066-9068
HTTP 端点前缀 1 个 /api/v1/advisor(另有 /api/v1/admin 与投顾共处一个文件)
前端跳转/导航 2 处 auth.js 角色跳转表、app-shell.js 导航表
配置项 2 个 advisor_rollout_enabled、advisor_rollout_customer_ids

2. 我实际是怎么清点的(方法)

不是只看《清理建议》,而是自己做了全仓扫描:

  1. Glob **/*advisor* → 拿到全部同名文件(含 __pycache__ 与迁移);
  2. Grep -i "advisor" --glob *.py 逐文件计数 → app/ 下 48 个文件命中;
  3. 对关键符号(AdvisorProductRepository / app.model.advisor_product)做导入方追踪,区分「投顾业务」与「产品数据底座」;
  4. 检查路由注册(app/main.py)、前端挂载(auth.js / app-shell.js)、工具与测试引用。

关键判据:一个文件是否属于投顾,不取决于它名字里有没有 advisor,取决于「谁在消费它」。


3. 🔴 名字骗人:advisor_* 的两类含义

3.1 第一类:投顾业务层(可删)

真正只服务投顾业务、删掉不影响别人的文件(见 §4.1)。

3.2 第二类:产品数据底座(必须保留)

以下文件名字里都有 advisor,但它们是产品主数据底座,被非投顾模块消费:

文件 谁在消费(非投顾)
app/model/advisor_product.py 产品指标 / 行情 / 对比 / 治理 / 组合分析
app/repository/advisor_product_repository.py 同上,且含 MVP 硬阻断
app/service/product_metric_service.py 产品指标
app/service/product_history_sync_service.py 产品历史同步
app/service/product_governance_monitor_service.py 产品治理(运营线)
app/service/market_quote_sync_service.py 行情同步(交易线也依赖)
app/service/product_comparison_service.py 客户侧产品对比(见 §3.4)
app/service/portfolio_analysis_service.py / portfolio_analysis_repository.py 组合分析

🔴 advisor_product_repository.py 里有 MVP 的唯一硬阻断

candidates = await AdvisorProductRepository(session).authoritative_tradable_products(...)
candidates, _excluded = AdvisorProductRepository.hard_suitability_filter(...)

authoritative_tradable_products() 就是产品证据链门——而 MVP 业务基线的唯一硬阻断正是「产品证据链为空」。 删掉它 = MVP 的硬阻断没有实现者。

3.3 混合文件:一个文件里既有投顾又有别人

文件 混合内容
app/api/controllers/recommendations.py 同时导出 advisor_router(/api/v1/advisor)与 admin_router(/api/v1/admin)→ 不能整文件删,只删前者
app/api/controllers/admin.py 含投顾治理端点,与其它管理端点混装
app/service/agent/bootstrap.py 注册投顾 Agent 与投顾工具,与其它 7 个 Agent 的注册混在一个函数里

3.4 ⚠️ 部分「投顾域」功能其实是客户角色在用

tools/seed_test_rbac.py:187-193 显示 customer 角色持有这些权限:

9020 investment-goal:write:self      9021 investment-goal:confirm:self
9022 investment-goal:read:self       9023 product-recommendation:generate:self
9024 product-recommendation:read:self 9025 portfolio-analysis:read:self
9026 asset-allocation:generate:self   9034 product-comparison:read:self

⇒ 投资目标、组合分析、产品对比、资产配置这些「投顾域」能力,客户侧也在用。 删除前必须区分「投顾工作台(员工用它给客户出方案)」与「客户自助的投顾域功能」——这两者不是一回事,混删会打断客户线。


4. 清除范围(三层边界,逐项)

4.1 ✅ 可删:投顾业务层(建议确认后执行)

# 文件 类型
1 app/service/agent/implementations/advisor.py 投顾 Agent(AdvisorAgent,189 行)
2 app/service/advisor_rollout_service.py 灰度闸门(63 行,当前空转,【待确认灰度状态】)
3 app/service/product_recommendation_service.py 推荐生成(470 行,含证据门调用)
4 app/service/investment_goal_service.py 投资目标与方案书(384 行)
5 app/service/goal_conversation_service.py 目标对话抽取(228 行)
6 app/service/asset_allocation_service.py 资产配置(201 行)
7 app/service/allocation_backtest_service.py 配置回测
8 app/core/advisor_allocation_contracts.py 配置契约
9 app/core/advisor_backtest_contracts.py 回测契约
10 app/api/controllers/investment_goals.py 投资目标端点
11 app/api/controllers/asset_allocation.py 资产配置端点
12 app/api/controllers/portfolio_analysis.py 组合分析端点
13 app/api/schemas/asset_allocation.py 契约
14 app/static/portal/employee-advisor/** 前端整目录(9 文件 / 约 2045 行)
15 tools/{bootstrap_advisor_demo, grant_advisor_role, publish_advisor_demo_config, seed_advisor_demo}.py 投顾专属脚本(4 个)

4.2 ❌ 不可删:产品数据底座(7 个文件)

app/model/advisor_product.py、app/repository/advisor_product_repository.py、 product_metric_service.py、product_history_sync_service.py、product_governance_monitor_service.py、 market_quote_sync_service.py、product_comparison_service.py(+ tools/sync_advisor_market_{data,quotes}.py)

理由:被产品治理 / 行情 / 客户侧对比消费;且 advisor_product_repository 承载 MVP 唯一硬阻断。

4.3 ❓ 需你决策:边界上的三项

# 事项 两种处理 我的建议
D-1 21 张 advisor_* 表 ① 保留表、只删代码;② 连表一起删 ① 保留表。AGENTS.md 规则 3 明令「禁止重命名或删除已有表」,规则 8 也把场外/投顾那 38 张表列为「不进基线但存在」。删表须改 .env 与基线文档,且违反项目级强制约束
D-2 15 个 alembic 迁移 ① 保留(历史记录);② 写新迁移 DROP ① 保留。迁移是历史,删它会让「新环境 alembic upgrade head」与老环境 schema 不一致。不新增 DROP 迁移(与 D-1 同源)
D-3 投顾域但客户在用的能力(投资目标 / 组合分析 / 资产配置 / 产品对比的客户侧端点) ① 全删(含客户侧);② 只删投顾工作台侧 需你明确。若目标是「去掉投顾这个角色」,则应保留客户自助能力;若目标包含「连投顾域业务一起下架」,则客户侧权限码(9020-9026/9034)也要从 seed_test_rbac.py 撤掉——那会改变客户线功能

4.4 ❓ 需你决策:RBAC 与环境数据

事项 影响 建议
sys_role 的 advisor 角色(9004,由 grant_advisor_role.py 建) 登录跳转、sys_user_role 绑定 保留角色行(环境数据;删了会影响既有账号),仅删代码侧引用
权限码 9020-9034 / 9041-9043 / 9057-9059 / 9066-9068 seed_test_rbac.py 是 DELETE 重建语义——号码段内不并进去的权限码「重建一次就没了」 保留定义(避免重跑种子时连带删除客户侧权限),由文档登记「投顾专属权限码暂留」
config_release 的投顾白名单 环境数据,本机 active 里有没有投顾 key 尚未实测(A-03 待做) 与 A-03 合并实测后再定

5. 全部引用与依赖清单(删除时的改动清单)

5.1 后端引用(app/,必须逐处摘除)

文件 要改什么
app/main.py:29,137 摘 recommendation_advisor_router 的 import 与 include_router(保留 recommendation_admin_router)
app/api/controllers/recommendations.py 删 advisor_router(/api/v1/advisor),保留 admin_router
app/service/agent/bootstrap.py 摘 AdvisorAgent 注册 + 投顾工具注册(query_investment_goal / analyze_portfolio / 等),其余 Agent 注册不动
app/service/agent/governance.py:1 处 摘投顾相关分支
app/service/agent_run_application_service.py:3 处 摘 AdvisorRolloutService 调用(accept() 内 if request.agent_type == "advisor" 分支)
app/core/config.py:2 处 摘 advisor_rollout_enabled / advisor_rollout_customer_ids
app/api/controllers/admin.py:5 处 摘投顾治理端点
app/api/schemas/promotion_material.py、app/core/nl2sql_catalog.py、app/service/financial_nl2sql_service.py 各 1 处投顾引用
app/model/{investment_goal, goal_conversation, profile_tag}.py、app/repository/{investment_goal,portfolio_analysis}_repository.py 视 D-3 决策:若客户侧也要下架则随之处理;否则保留
app/service/{risk_questionnaire_service, suitability_service, risk_query_service}.py、app/model/{risk,fund,promotion_material}.py 疑似同名字符串误命中,须逐处人工核对后再动(不要按 grep 结果批量删)

5.2 前端引用(3 处)

位置 要改什么
app/static/portal/common/auth.js:261 roles.includes('advisor') 的跳转分支(删该分支 → 投顾账号登录后无处可去,须给兜底)
app/static/portal/common/layout/app-shell.js:29 导航表条目 ['advisor-dashboard', '投顾工作台', ...]
app/static/portal/README.md:21 文档中的角色目录表

5.3 tools 引用(2 处)

tools/check_portal_modules.py:38(DASHBOARD_DIR 指向 employee-advisor)、 tools/publish_advisor_demo_config.py、tools/grant_advisor_role.py、tools/seed_advisor_demo.py、tools/bootstrap_advisor_demo.py(随 4.1 一起删)。

5.4 测试引用(3 个文件,必改否则红)

测试 影响
tests/unit/api/test_portal_frontend.py:171,184,189 读 employee-advisor/dashboard/{index.html, dashboard.js, advisor-config.js} → 文件删了必红。(含 AGENTS.md 记录的既有失败用例 test_advisor_workspace_registers_documented_operation_endpoints)
tests/unit/service/test_advisor_rollout_service.py 随灰度闸门一起删
tests/{unit/service/test_advisor_asset_allocation, test_advisor_base_adapter}.py、tests/unit/repository/test_advisor_product_repository.py、tests/integration/test_advisor_review_queue_mysql.py、tests/unit/test_advisor_migration_contract.py、tests/unit/tools/test_bootstrap_advisor_demo.py 分别随对应实现处置;⚠️ test_advisor_product_repository 测的是底座,必须保留

5.5 文档引用

AGENTS.md:37,40(角色目录表)、docs/40-前端验收清单.md、docs/44-演示流程.md:275、docs/05-接口文档.md §19、 docs/演示用/*(4 份)、group_fqcd_jr/docs/验收与审计/advisor-e2e-acceptance-20260912.md。 处理口径:docs/** 属历史记载,按项目既有惯例(见 Todolist §9 校正 12)不改,只在 F-05 回写时登记。


6. 受影响的关键关联

关联 影响 严重度
MVP 演示 9 步 投顾是 MVP 三条业务线之一;删了演示脚本要相应下架投顾场景 🔴 高
MVP 唯一硬阻断(产品证据链) 阻断实现位于底座,按 §4.2 保留 → 不受影响 🟡 中(若误删则变 🔴)
改 6 个底座文件时的对照组(Todolist §9-3) 对照组消失 → 底座改动的回归验证少了一条独立业务线 🔴 高
客户侧投顾域功能 投资目标 / 组合分析 / 产品对比 / 资产配置的客户自助能力(权限码 9020-9026/9034)可能一并受影响 🔴 高(取决于 D-3)
运营线 / 产品治理 依赖 advisor_product 底座 → 按 §4.2 保留则不受影响 🟡 中
数据侧 21 张表保留 → 数据不丢;但代码删除后这些表无人写入/读取(成为孤儿表) 🟢 低(可接受)
前端账号 advisor_t(9020)登录后跳转目标消失 🟡 中

7. 与既有决策的冲突(必须先解决)

决策 出处 与本次的关系
「先重建客服、投顾留到最后」——投顾是对照组 Todolist v5.1 §9-3(2026-09-17 已拍板、已写入三份文档) 直接冲突。今天刚定,现在要拆对照组
「投顾模块用户将自行删除」 项目长期记忆(2026-09-16) 与本次方向一致,但时点是「最后」
「投顾前端建议单独立项」 《清理建议》§四.7 支持「分阶段、不并进本次」

8. 建议的执行方案(确认边界后即可执行)

8.1 建议分两批,不并进客服重构

批 内容 时点
第 1 批·低风险 删 tools/ 4 个投顾脚本 + employee-advisor/ 前端整目录 + 2 处前端引用 + test_portal_frontend.py 相应用例 可现在做(与底座零交集)
第 2 批·需决策 后端 13 个业务文件 + 路由/工厂/config 摘除 + 测试调整 待 D-1~D-3 定后,且建议排在客服重建之后(保住对照组)

8.2 执行纪律(沿用形态A 清除的既有做法)

  1. 先备份:文件级复制到 _advisor_purge_backup/(本机 git 写被拦截,无 git revert);
  2. 不删表、不写 DROP 迁移(AGENTS.md 规则 3);
  3. 不按 grep 批量删——§5.1 里标「疑似误命中」的 8 个文件必须逐处人工核对;
  4. 验证手段(本机依赖零安装,只能做语法层):
    • 全部 .py 跑 py_compile,要求 0 错误;
    • AST 扫悬空 import,要求 0 条(沿用 _purge_verify.py 的做法);
    • 清过期 __pycache__(本次涉及 13 个投顾相关 .pyc);
    • 复核 main.py 能 import(python -c "import app.main" 需依赖,做不到则退化为 AST 检查)。

9. 待你拍板(4 项)

# 事项 我的建议
1 边界确认:§4.1 的 15 项为「清除范围」,§4.2 的 7 个底座文件保留 按此边界(否则会拆掉 MVP 硬阻断)
2 D-3:客户侧的投顾域能力(投资目标/组合分析/资产配置/产品对比)是否一并下架? 保留下架范围 = 仅投顾工作台侧;客户侧能力暂留(避免改变客户线功能)
3 时点:现在做,还是等客服重建完(保住对照组)? 第 1 批现在做;第 2 批排客服重建之后
4 表与迁移:21 张表 + 15 个迁移保留(不写 DROP) 保留(AGENTS.md 规则 3 强制)