Files
group_fqcd_jr/开发文档/D4.2-客服模块清除影响面清单.md
T

173 lines
13 KiB
Markdown
Raw Normal View History

# 客服 Agent 模块清除影响面清单
> **体系编号**:`D4.2` · 域:四、清除与重建留痕 · 编号体系见 `D1.1` §4.0
> **文档编号**:CS-PURGE-2026-007
> **日期**:2026-09-16
> **用途**:对「彻底清除客服 Agent 模块」指令做的逐文件影响面取证。**本次未执行任何删除**。
> **结论(一句话)**:客服模块的**专属资产约 40 个文件可删**;但「含表与迁移」的**字面全清与「项目能正常构建运行」在技术上互斥**——有 **3 条级联**会同时打挂员工端、公共平台端与整个 Portal 外壳。
---
## 0. 为什么先出清单而不直接删
本轮侦察发现三项事实,任何一项都足以要求先确认再动手:
| # | 事实 | 影响 |
|---|---|---|
| 1 | 客服 Agent 是**需求文档 §4 Phase 1 F1.3 的交付物本身**,也是 MVP 三条业务线之一 | 「清除」= 放弃交付物,与「重构」相反 |
| 2 | `svc_handover_ticket` 与前端挂件被**投顾/风控/员工端/公共平台**共用 | 删它 = 打挂另外几个模块,违反 `AGENTS.md` 规则 1/4 与 `docs/00` 不可变基线 |
| 3 | **本机无法验证**:Managed Python 3.13.14 未安装任何项目依赖,仓库无 venv | 你要求的「构建正常 + 验证结果」当前无法真实执行 |
---
## 1. 客服专属资产(可删除,约 40 项 / ≈1900 行)
### 1.1 后端实现(8 文件 / 1743 行)
| 文件 | 行数 | 说明 |
|---|---|---|
| `app/service/agent/implementations/customer_service.py` | **748** | `CustomerServiceAgent` 主逻辑 |
| `app/service/customer_service_handover_action_service.py` | 289 | 转人工动作(assign/accept/resolve/close/cancel) |
| `app/service/customer_service_session_memory_service.py` | 209 | Redis 短期记忆 |
| `app/core/customer_service_rules.py` | 208 | 路由规则、热线、零容忍词 |
| `app/service/customer_service_handover_admin_service.py` | 124 | 工单队列查询 |
| `app/service/agent/customer_service_routing.py` | 87 | 一期路由(含 8 条注入拦截,**当前无生产调用方**) |
| `app/service/customer_service_handover_context.py` | 73 | 工单上下文 |
| `app/service/agent/customer_service_agent.py` | 5 | 向后兼容桩 |
### 1.2 前端(2 文件 / 173 行)
| 文件 | 行数 |
|---|---|
| `app/static/portal/common/customer-service-widget/widget.js` | 146 |
| `app/static/portal/common/customer-service-widget/widget.css` | 27 |
### 1.3 工具脚本(6 文件)
`tools/ask_customer_service.py`、`tools/customer_service_check.py`、`tools/grant_customer_service_phase2_permissions.py`、`tools/publish_customer_service_config.py`、`tools/publish_customer_service_knowledge.py`、`tools/verify_customer_service_phase1.py`
### 1.4 测试用例(14 文件)
集成 2:`test_customer_service_handover_actions_mysql.py`、`test_customer_service_handover_admin_mysql.py`
单元 12:`test_customer_service_test_page.py`、`test_customer_service_rules.py`、`test_customer_service_agent.py`、`test_customer_service_chitchat_metadata.py`、`test_customer_service_handover_actions.py`、`test_customer_service_handover_admin_service.py`、`test_customer_service_handover_context.py`、`test_customer_service_search_query.py`、`test_customer_service_session_memory_service.py`、`test_customer_service_suitability.py`、`test_customer_service_topic_matrix.py`、`test_publish_customer_service_knowledge.py`
### 1.5 文档与静态资产(约 10 项)
`docs/24-客服Agent阶段性总结与下阶段计划.md`、`docs/41-客服Agent前端开发约束_v1.md`、`docs/客服Agent二期_画像投影协议_v1.md`、`docs/客服Agent接入底座扩展说明_v1.md`、`docs/客服Agent一期远程整合测试手册.md`、`docs/superpowers/specs/2026-09-10-customer-service-agent-design.md`、`docs/superpowers/plans/2026-09-10-客服Agent与RAG实施计划-qyqy版.md`、`docs/superpowers/handoff/2026-09-11-*.md`(2)、`docs/evidence/20260910-customer-service-knowledge-preflight.json`
另有 `app/static/index.html`(客服联调专用页)。
> **注**:`docs/**` 中还有约 40 个文件**顺带提及**客服(如 `docs/05-接口文档.md`、`docs/14`、`docs/06` 测试报告)。这些是**历史记录**,删除会破坏文档体系的完整性,不建议动。
---
## 2. 共享资产(**不可删**,只能「摘除客服引用」)
| # | 共享文件 / 表 | 客服相关行 | 同时服务谁(证据) | 为什么不能删 |
|---|---|---|---|---|
| 1 | `app/service/agent/bootstrap.py` | L28 import、L431-434 注册 | 7 个 Agent 的统一注册入口(L416 `register_business_agents`) | 删文件 = 全部 Agent 注册失效 |
| 2 | `app/service/agent_run_application_service.py` | L13/26/28/30 import、L55/77/80/118/126/147/154 客服分支 | 受理链路服务**全部** Agent(HTTP + Worker 共用) | 客服专属方法(`_load_customer_service_prior_context`)寄生在底座文件内,须**摘方法**而非删文件 |
| 3 | `app/service/agent_persistence_service.py` | 建单段 L116-153 | `worker/runtime.py` 全 Agent 共用 | 同上 |
| 4 | `app/worker/runtime.py` | L38-41 import、L134/196/228/930-940 客服分支、L303-363 工单 outbox 消费 | Worker 分发**全部** Agent | 摘分支,不删文件 |
| 5 | `app/core/conversation_privacy.py` | `sanitize_customer_service_message` | `public_platform_service.py:10,149` **也**在用 | 公共隐私函数,删了打挂公共平台 |
| 6 | `app/core/compliance_context.py` | `NEGATION_CUES` 等 | `governance.review_output` 对全部 Agent 生效 | 公共合规件 |
| 7 | `app/model/platform.py` | L95 `svc_handover_ticket` 表定义 | 见下 §3.1 | 改表 = 违反 `AGENTS.md` 规则 4 |
| 8 | `app/repository/platform_repository.py` | L16 表名白名单 | 平台通用仓储 | 公共件 |
| 9 | `tools/seed_test_rbac.py` | 9008 `handover:create`、9046 `handover:read`、9069 `handover:write` | RBAC 权限码唯一来源(DELETE 重建) | 权限码需保留给员工端 |
| 10 | `app/static/portal/common/layout/app-shell.js` | **L8 import、L178 挂载 widget.css** | **整个 Portal 的布局外壳**(公开首页 / 基金产品页 / 客户工作台) | 删 widget 会让 shell 立刻 import 失败 |
| 11 | `app/static/portal/common/api-client.js` | L50-59 共 **7 个** admin 工单端点 | 员工端 API 客户端 | 摘端点,不删文件 |
| 12 | `app/static/portal/employee-console/workspace/workspace.js` | L198 工单队列渲染 | 员工工作台 | 摘 UI 区块 |
---
## 3. 三个硬阻断
### 3.1 阻断一:`svc_handover_ticket` 被 3 个模块读写,删表即打挂员工端与访客端
```
app/model/platform.py:95 __tablename__ = "svc_handover_ticket" ← 表定义
app/api/controllers/admin.py:230-361 7 个 HTTP 端点 /admin/customer-service/handover-tickets*
app/api/schemas/admin.py 工单出入参模型
app/service/public_platform_service.py:140 访客提交转人工时 直接 INSERT HandoverTicket
app/service/public_platform_service.py:43 按 ticket_no + customer_id 查询(客户自查)
app/repository/platform_repository.py:16 进平台仓储表名白名单
app/worker/runtime.py:311 outbox 消费者 SELECT HandoverTicket
```
**后果**:删除该表 → 员工端工单队列 7 个端点全部 500;访客端「转人工」写入失败;`conversation.transfer_requested` outbox 消费者抛 `OutboxHandlerError`。
**规范冲突**:`AGENTS.md` 规则 1「`docs/00` 为不可变业务基线」+ 规则 4「禁止重命名/删除已有表」+ `docs/14` §12;**并直接违反你在 Todolist v5.0 A-09 中立的纪律「既有接口路径与签名不可改」**——删除上述 7 个 `/api/v1/admin/customer-service/handover-tickets*` 端点,即改变既有接口面。
**同样不可删的共享表**:`agent_run`、`request_idempotency`、`domain_event_outbox`、`outbox_delivery`(服务全部 Agent)、`agent_negative_word`(按 `applicable_agents` 分租,表服务全部 Agent)。
### 3.2 阻断二:前端挂件是全 Portal 的公共依赖
```
app/static/portal/common/layout/app-shell.js:8 import { mountCustomerServiceWidget } from '.../customer-service-widget/widget.js'
app/static/portal/common/layout/app-shell.js:178 widget.css?v=20260913 挂载
```
**后果**:`app-shell.js` 是公开首页、基金产品页、客户工作台的公共外壳。删除 widget 目录 → 所有 Portal 页面在浏览器端 **import 报错、白屏**。
**连带**:`visitor-token.js:2,7` 的注释记录「访客令牌逻辑原先只写在客服浮窗里,产品页接入后抽出」——即该共享模块是从客服侧抽出来的,**源文件不能删**。
### 3.3 阻断三:「字面全清」与「构建通过」互斥
你的验收要求是「不出现因删除该模块而导致的报错、死代码或未使用依赖」。但按 §3.1/§3.2:
- 要让构建通过,就必须**同步修改** `admin.py`、`api/schemas/admin.py`、`public_platform_service.py`、`platform_repository.py`、`worker/runtime.py`、`app-shell.js`、`api-client.js`、`workspace.js`、`seed_test_rbac.py` 共 **9 个服务于其它模块的文件**;
- 而修改这些文件 = **动投顾/风控/员工端**,恰是 `AGENTS.md` 规则 7 与 `docs/14` §12 明令禁止的。
→ **两条要求不能同时成立**,必须由你在 §4 中二选一。
---
## 4. 两种可执行的收敛形态
| 维度 | **形态 A:模块级全清**(可执行、构建可通过) | **形态 B:字面全清**(你当前所选) |
|---|---|---|
| 删除范围 | §1 全部客服专属资产(约 40 文件) | §1 + §2 中 9 个共享文件的客服引用 + 3 张共享表 |
| 共享表 | **保留**(`svc_handover_ticket` 等不动) | **删除** `svc_handover_ticket`、`agent_negative_word` |
| 员工端工单队列 | 保留(7 端点不动) | **失效**(须一并删端点/UI/权限码/前端客户端) |
| 访客端转人工 | 保留(公共平台链路不动) | **失效** |
| Portal 外壳 | 保留(摘掉 widget 挂载) | 保留(无法删,它是布局外壳) |
| 构建结果 | **可通过**(须按依赖顺序摘引用 + 重跑门禁) | **无法通过**,除非改 9 个跨模块文件 |
| 规范合规 | 合规(不碰不可变基线) | **违反** `AGENTS.md` 规则 1/4/7 |
| 可回退性 | git 分支可回退 | 表结构变更不可回退(Alembic downgrade 亦需重灌数据) |
| 工作量 | 约 40 文件删除 + 9 文件摘引用 + 全量门禁 | A 的全部 + 员工端/公共平台功能移除 + 迁移脚本 + 权限码重排 |
> **说明**:即便选形态 B,`app-shell.js`(Portal 外壳)、`conversation_privacy.py`(公共隐私)、`compliance_context.py`(公共合规)、`agent_run`/`request_idempotency`/`domain_event_outbox`/`outbox_delivery`(平台核心表)**仍然不能删**——「彻底」在这个仓库里存在物理上限。
---
## 5. 环境验证能力现状(重要)
按 `docs/14` §13 验收命令集实测本机环境:
| 项 | 实测结果 |
|---|---|
| git | ✅ 可用,当前分支 `qyqy_develop` |
| Managed Python | ✅ `3.13.14` 可执行 |
| 项目依赖(pytest / fastapi / sqlalchemy / pydantic / redis / pymilvus / alembic / httpx / dashscope) | ❌ **全部 ModuleNotFoundError** |
| 仓库内 venv(`.venv` / `venv` / `env`) | ❌ 不存在 |
| `pyproject.toml` / `requirements.txt` | ✅ 存在 |
**结论**:`pytest tests/...`、`ruff check`、`mypy app`、`tools/audit_schema.py` **当前均无法运行**。
若要满足你要求的「验证结果」,需先补齐依赖(且 `tests/integration/**` 还需要 MySQL + Redis + Milvus 服务在线)。
**当前可做的验证上限**:
- `python -m py_compile` 全量语法校验(不依赖第三方包)
- 静态引用扫描(确认无悬空 import / 未被引用的删除目标)
- `git status` / `git diff --stat` 变更核对
---
## 6. 待你拍板(1 件事)
**在形态 A 与形态 B 之间选定一个。**
- 选 **A** → 我立即开工:先建备份分支 → 按 §2 依赖顺序摘除 12 处共享引用 → 删 §1 约 40 文件 → `py_compile` + 静态扫描验证 → 出变更清单。
- 选 **B** → 我必须先书面告知:**项目将无法构建**,且会改动见 §3.3 的 9 个跨模块文件(含投顾/风控/员工端);同时你需要确认放弃「客服 Agent」这条 MVP 业务线与 `需求文档` F1.3 交付物。**请回复「确认执行形态B,接受项目无法构建与放弃F1.3」**,我才会动手。
> 若你的真实意图是「**清理重构前的死代码**」(`客服与投顾模块重构前代码清理建议-2026-09-15.md` 的范围),那是另一个量级:约 6-9 个文件、构建不受影响,告诉我即可,我按那个范围一次做完。
---
**附:本次侦察未产生任何文件改动。** 仅创建了本清单与 2 个临时探测文件(已删除)。