Files
group_fqcd_jr/开发文档/D4.3-客服模块清除执行报告-2026-09-16.md
T

159 lines
13 KiB
Markdown
Raw Normal View History

# 客服 Agent 模块清除执行报告(形态A:模块级全清)
> **体系编号**:`D4.3` · 域:四、清除与重建留痕 · 编号体系见 `D1.1` §4.0
> **编号**:CS-PURGE-2026-008
> **日期**:2026-09-16
> **依据**:`开发文档/D4.2-客服模块清除影响面清单.md`(CS-PURGE-2026-007)§4 「形态A」+ 用户指令「按你的建议在本地项目进行删除或修改操作,先删客服模块」
> **范围**:`group_fqcd_jr/`(分支 `qyqy_develop`)
> **结论**:**删除 34 个客服专属文件 + 修改 17 个共享文件引用;610 个 .py 语法零错误、悬空 import 零条。**
---
## 一、为什么是形态A(一句话)
`svc_handover_ticket` 工单表、员工端工单队列 7 个端点、访客端「转人工」链路、Portal 外壳、
`sanitize_customer_service_message` 隐私函数**都是跨模块共享资产**。字面全清会把投顾/风控/员工端
一起打挂,且直接违反 `AGENTS.md` 规则 1/4/7 与 Todolist A-09「既有接口路径与签名不可改」。
形态A = 清掉客服**专属**资产,摘掉共享文件里的客服引用,**保留共享表与共享链路**。
---
## 二、已删除(34 个文件,可回退)
| 类别 | 数量 | 文件 |
|---|---|---|
| 后端核心实现 | 4 | `app/service/agent/implementations/customer_service.py`(748 行主逻辑)、`app/service/agent/customer_service_routing.py`(一期路由)、`app/core/customer_service_rules.py`(二期安全路由)、`app/service/customer_service_session_memory_service.py`(Redis 短期记忆) |
| 前端挂件 | 3 | `app/static/portal/common/customer-service-widget/widget.js`、`widget.css`、`app/static/index.html`(客服测试页) |
| 运维/发布脚本 | 8 | `tools/ask_customer_service.py`、`customer_service_check.py`、`grant_customer_service_phase2_permissions.py`、`publish_customer_service_config.py`、`publish_customer_service_knowledge.py`、`verify_customer_service_phase1.py`、`publish_chitchat_prompt.py`、`publish_profile_tool_whitelist.py` |
| 测试 | 9 | `tests/unit/api/test_customer_service_test_page.py`、`tests/unit/core/test_customer_service_rules.py`、`tests/unit/service/test_customer_service_{agent,chitchat_metadata,search_query,session_memory_service,suitability,topic_matrix}.py`、`tests/unit/tools/test_publish_customer_service_knowledge.py` |
| 文档 | 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-{工作报告,交接文档}-客服Agent与RAG收尾.md`、`docs/evidence/20260910-customer-service-knowledge-preflight.json` |
| 过期字节码 | 6 | `tools/__pycache__/` 下 5 个已删脚本 + 其余已删模块的 `.pyc`(源码已不存在者一律清除) |
完整路径清单:`_cs_delete_list.txt`(工作区根)。**回退副本:`_cs_purge_backup/`(34/34 个文件,已核对)**。
---
## 三、已修改(17 个共享文件,逐处说明)
| # | 文件 | 改了什么 | 为什么必须改 |
|---|---|---|---|
| 1 | `app/main.py` | 删掉 `/customer-service-test` 静态挂载 | 挂载目录已删,留着 = 启动即 404/异常 |
| 2 | `app/service/agent/bootstrap.py` | 删 `CustomerServiceAgent` import + `factory.register(...)` | 不删 = **整个 Agent 注册入口 import 失败**,全部 7 个 Agent 一起挂 |
| 3 | `app/service/agent_run_application_service.py` | 删 5 处客服 import、`CustomerServicePriorContext`、`_read_customer_service_short_context`/`_load_mysql_prior_context`/`_load_customer_service_prior_context`、`session_memory` 构造参数;`accept()` 改为直接用 `request.message`;`build_outbox_metadata()` 退化为纯序列化 | 客服专属方法寄居在**全 Agent 共用**的受理链路里 |
| 4 | `app/worker/runtime.py` | 删客服 session_memory import/字段/构造参数、`should_request_memory_extraction` 的客服短路、`should_request_profile_candidate` 的 `agent_type != "customer_service"`、`_append_customer_service_session_memory()`;新增 `PROFILE_CANDIDATE_AGENT_TYPES`(见 §六) | Worker 分发全部 Agent |
| 5 | `app/static/portal/common/layout/app-shell.js` | 删 widget import + 挂载/样式注入块 | `app-shell.js` 是全 Portal 外壳 → 不删 = **所有页面 import 报错白屏** |
| 6 | `app/static/portal/common/visitor-token.js` | 更新注释(不再指向已删的 widget 路径) | 悬空路径引用 |
| 7 | `app/service/agent/governance.py` | 2 处注释:热线同步说明改写;`CUSTOMER_FACING_AGENT_TYPES` 加「客服仍在名单内」的理由 | 原文引用已删模块 `customer_service_rules.CONTACT_PHONE` |
| 8 | `app/service/auth_service.py` | docstring 里 `CustomerServiceAgent` → 「面向客户的 Agent」 | 引用已删类名 |
| 9 | `tools/check_rbac_seed_consistency.py` | `GRANT_SCRIPTS` 移除客服二期条目 | 该条目指向已删脚本 → 一致性校验脚本会 `RuntimeError` |
| 10 | `tools/seed_demo_data.py` | `STEPS` 移除「客服配置白名单」「客服闲聊提示词」两步 | 两步指向已删脚本 |
| 11 | `tools/api_console.py` | 移除 `/customer-service-test` 路径分组项 | 与 #1 同因 |
| 12 | `tests/unit/service/test_knowledge_granularity.py` | 删 import + 4 条 `CustomerServiceAgent._prefer_section` 用例 | import 已删模块 |
| 13 | `tests/unit/service/test_agent_governance.py` | 删 import + `test_authenticated_customer_service_does_not_recall_customer_memory` | 同上 |
| 14 | `tests/unit/service/test_knowledge_keyword_recall.py` | `test_gate_value_matches_agent_high_score` 改为锁定 `VECTOR_CONFIDENT_SCORE == 0.75` | 原用例比较的 `HIGH_SCORE` 只存在于已删模块 |
| 15 | `tests/unit/worker/test_runtime_worker_dispatch.py` | 删 `CustomerServiceSessionTurn` import + 3 条客服用例;2 条访客用例的 `agent_type` 改为存活 Agent | 已删模块 import / 已删方法调用 |
| 16 | `tests/unit/tools/test_foundation_migration_preflight.py` | 替身 Git 输出里的 `customer-service-rag` / `customer_service_agent.py` 改为中性路径 | 纯命名残留 |
| 17 | `docs/customer-service-routing-legacy-keywords.md` | 顶部加「已被形态A推翻」告示块 | 该文档原写「`chitchat_streak()` 保留未删」,现整个文件已删除 |
---
## 四、有意保留(**不是漏删**,逐条给理由)
| 保留项 | 理由 |
|---|---|
| `app/api/controllers/admin.py` 的 7 个 `/api/v1/admin/customer-service/handover-tickets*` 端点 | **员工端工单队列**。删除即改变既有接口面(违反 A-09),且 `svc_handover_ticket` 是平台核心表 |
| `app/service/customer_service_handover_{context,action,admin}_service.py` | 同上;`customer_service_handover_context` 还被**共享的** `agent_persistence_service.py:15` 导入 |
| `svc_handover_ticket` / `agent_run` / `request_idempotency` / `domain_event_outbox` / `outbox_delivery` / `agent_negative_word` | 平台核心表,服务全部 Agent |
| `app/core/conversation_privacy.py::sanitize_customer_service_message` | **公共**隐私函数,还被 `memory_extraction_worker` + 2 个画像投影 + `public_platform_service` 使用 |
| `app/service/public_platform_service.py` 的访客转人工写单 | 公共平台链路(访客入口),非客服模块私有 |
| `app/service/customer_profile_candidate_service.py` 的 `customer_service_preferences` 快照键 | 画像快照**已落库字段名**,改名 = 数据迁移 |
| `app/service/agent/governance.py::CUSTOMER_FACING_AGENT_TYPES` 中的 `"customer_service"` | **合规门禁 F5**(面向客户输出必须附免责声明)。留着 → 重建后自动继承;摘掉 → 重建后出现合规缺口 |
| `docs/客服Agent一期_合规红队与业务评测集_v1.md`、`docs/customer-service-routing-legacy-keywords.md` | 重建的**验收基线 / 词表唯一副本**(见 §六) |
---
## 五、验证结果(本机可做的上限)
| 项 | 结果 |
|---|---|
| `py_compile` 全量语法校验 | **610 个 .py,0 错误** |
| AST 静态扫描:指向不存在文件的 import | **0 条** |
| `__pycache__` 过期字节码 | 已清(仅保留源码仍在的 570 个) |
| 文本残留 | 68 个 .py / 215 处(全部为**数据值、共享表名、保留模块名、历史注释**,见下) |
| pytest / ruff / mypy / 集成测试 | ❌ **跑不了**:本机无项目依赖(pytest/fastapi/sqlalchemy/pydantic/redis/pymilvus/alembic 全部 ModuleNotFoundError),仓库内无 venv |
验证脚本:`_purge_verify.py`;原始报告:`_purge_verify_out.json`。
(`alembic.*` 是第三方包,首轮扫描把它误判成悬空 import,已在脚本里修正口径。)
**残留分类(68 个文件)**:
- `app/`(15 个):全部为**有意保留**项(handover 三件套 + 工单端点 + 公共隐私函数 + 核心表名 + 历史注释)。
- `tests/`(28 个):`agent_type="customer_service"` / `customer_service:faq` 等**测试夹具与配置键的字符串值**;`acceptance_registry` 夹具自己注册替身 Agent,故这些用例仍然自洽。
- `tools/`(11 个):见 §六.3。
- `alembic/`(1 个):基线迁移里的表注释。
---
## 六、需要你拍板 / 重建时必须补齐(6 项)
### 6.1 已随模块消失的安全能力(**最重要**)
删除的不只是"客服话术",还包括三套拦截能力,现在**在生效路径上不存在**:
| 能力 | 原位置 | 现状 |
|---|---|---|
| 提示词注入拦截(8 条词) | 先期迁入 `customer_service_rules.py` | 随模块删除 → **红队 RT-009/010 必然失败** |
| 凭据披露拦截(`_SECURITY_DISCLOSURE_PHRASES`) | 同上 | 同上 |
| 安全关键词路由 + 零容忍词(11 条,与库内 `agent_negative_word` 镜像) | `route_message()` / `ZERO_TOLERANCE_WORDS` | 同上 |
**词表唯一副本已存于** `docs/customer-service-routing-legacy-keywords.md`(我已在该文档顶部加了告示块)。
重建时按它的迁移对照表恢复,否则这批词会**彻底丢失**。
### 6.2 `PROFILE_CANDIDATE_AGENT_TYPES` 目前为空集合(需确认)
`app/worker/runtime.py` 新增该常量,`frozenset()`。**行为与删除前完全等价**(此前也只有客服命中)。
我**故意没有**把它改成"任何非访客 Agent 都可产出候选"——因为候选里含 `preference:risk_level`,
放开会让投顾对话也能产出风险等级候选,**触碰 MVP 红线①「风险等级唯一来源是问卷测评」**。
重建客服 Agent 后,把它的 `agent_type` 填回该集合即可接通候选链路。
### 6.3 11 个开发脚本仍指向已注销的 `agent_type="customer_service"`
`tools/`:`smoke_check.py`(7)、`e2e_smoke_test.py`(4)、`acceptance_check.py`(3)、`portal.py`(3)、
`portal_api_check.py`(2)、`memory_demo_chain.py`(2)、`chat_console.py`(1)、`drop_table_header_vectors.py`(1)、
`publish_risk_agent_config.py`(1)、`seed_compliance_baseline.py`(1)、`seed_knowledge_r1r5_faq.py`(1)。
这些脚本**不是构建依赖**(`app/` 不 import 它们),但连上服务后会因为 Agent 未注册而失败。
**替换成哪个存活 Agent(`advisor`?`fund_query_demo`?)会改变脚本演示的语义,我不替你做这个决定。**
请给一个口径,我一次改完。
### 6.4 文档层残留(约 30 处,在 `docs/` 站内)
分两类,处理方式不同:
- **历史记录**(交付说明、评审回复、合并记录、验收报告等):按其写作日期引用当时的文件,**建议原文不动**(改历史=伪造记录)。
- **在用运行手册**(`AGENTS.md:163`、`docs/05-接口文档.md`(10)、`docs/09-底座使用文档.md`(9)、`docs/32-平台侧交接与联调准备.md`(3)、`docs/11/14/15-接入说明书`):命令/脚本已不存在,**建议回写**。要我做就说一声。
### 6.5 Advisory:`AGENTS.md:163` 引用了已删的发布脚本
`AGENTS.md` 是项目的规则文件(Rule Priority 载体)。它把「同 key 继承项必须被覆盖」这条教训
挂在 `tools/publish_customer_service_config.py` 上,而该脚本已删 → 教训的载体消失。
**我没有擅自改 `AGENTS.md`**(规范性文件),请你决定是改引用还是换载体。
### 6.6 重建时必须带回的测试(我已在原位留注释)
- `tests/unit/service/test_agent_governance.py`:客服不得触发通用长期/画像记忆读取。
- `tests/unit/service/test_knowledge_granularity.py`:整节块 vs 行级子块的取舍(`_prefer_section`)。
- `tests/unit/service/test_knowledge_keyword_recall.py`:检索层门槛与客服高置信门槛的**跨模块对齐**。
---
## 七、回退方式
```bash
# git 写入被本机沙箱拦截(git branch 返回 0 但分支未创建),故用文件级备份:
# D:\桌面\金融\_cs_purge_backup\ 34/34 个被删文件的副本(保持原目录结构)
# 恢复:按原相对路径复制回 group_fqcd_jr\ 即可;
# 17 个被改文件请用 git diff 逐处回退(改动都是"删引用",无逻辑重写)。
```