0. 文档定位与前提
0.1 目的与范围
本文档回答「分几步做、按什么顺序、谁做什么、做到什么算完成」。它是四份交付文档中的「计划」分册:上游接《客服 Agent 需求文档》(做什么),下游发《客服 Agent 执行 Todolist》(逐项任务与验收动作)。
| 覆盖 | 不覆盖(归属) |
| 前置条件与准入、测试环境要求、纪律基线 | 需求条目与验收标准 → 《需求文档》§1.4/§1.5/§2.2 |
| 工程落位(原位改造 / 最小新增 / 最小挂载) | 逐项任务的 DoD 与验证命令 → 《执行 Todolist》 |
| 批次划分、里程碑、关键路径、串行约束、并行通道 | 集合划分、分块、检索参数 → 《知识库设计方案》 |
| 底座接触面与两组会签、质量门禁、完工判据、交付物 | 溯源取证与理由 → D4.1-客服Agent重构报告-2026-09-16.md |
0.2 与其他三份文档的关系
| 文档 | 在这套体系中的角色 | 与本文档的接口 |
| 《需求文档》 | 要做什么、边界在哪、验收标准 | 本文档的每个批次都指向它的一组 FR / NFR / 红线 |
| 本文档 | 分几步、什么顺序、谁做、何时算完 | — |
| 《执行 Todolist》 | 逐项任务与验收动作(开工只看那一份) | 本文档定批次与顺序,Todolist 定每项的 DoD |
| 《知识库设计方案》 | 知识库专项设计 | D 批次(检索护栏)与 B 批次(语料)的规格来源 |
📌 四份交付文档的配套关系
① D2.2-客服Agent需求文档.html——需求与验收标准:功能需求 48 条(FR-CS-001~048)+ 非功能需求 21 条(NFR-CS-001~021),含 三条业务红线(风险等级唯一来源=问卷测评 / 先风险揭示后客户确认 / 不生成交易指令)与范围边界;
② D2.3-客服Agent开发计划.html(本文档)——51 项 / 7 个批次 / 12 步关键路径;
③ D2.1-客服Agent执行Todolist.md——逐项 DoD 与验证动作(开工只看那一份);
④ D2.4-客服Agent知识库设计方案.html——知识库专项。
0.3 当前状态与两处重大变化
| 项 | 状态 |
| 客服 Agent 模块 | 已按形态 A 整体清除(2026-09-16,删 34 文件 + 摘 17 个共享文件引用,回退副本 _cs_purge_backup/)——下一步是重建 |
| 投顾模块 | 已于 2026-09-17 整体清除(后端 21 文件 + 前端 employee-advisor/ 9 文件 + /api/v1/advisor 全部端点 + 5 个脚本 + 14 个测试 + 相关权限码)。验证:0 语法错误、0 悬空 import;备份 _advisor_purge_backup/ |
| 身份与鉴权方向 | 已拍板:「方案乙(收敛)现在做 → 方案甲(拆轴)MVP 后」 |
| 工程纪律 | 19 项决策已全部定案;底座接触面已逐文件取证 |
⚠️ 投顾清除带来一个必须正视的后果:投顾原是第二条回归业务线,用于验证 6 个底座公共件的改动。清除后,底座改动的回归验证只剩客服一条线。因此本计划把「测试环境就位(G-00)」列为最优先的前置——没有可运行的门禁时改底座,等于盲改。
1. 前置条件与准入
1.1 开工前必须闭环的五项
| # | 事项 | 不闭环的后果 | 谁确认 |
| T-01 | Embedding 模型与维度(底座实况) | 维度不一致 → 检索结果无意义(静默错误);建集合的动作需重做 | 后端架构师 |
| T-02 | 三集合是否已存在及其 Schema | 决定「首次建集合」还是「改造既有」——影响 D 批次全部落点 | 后端架构师 |
| T-03 | RAG 基础设施的落位与签名 | 影响面最大:决定检索是「改造既有签名」还是「新建入口」;新建入口=产生第二条可能漏过滤的路径 | 后端架构师 |
| T-04 | 一期安全路由是否被二期完整覆盖(含关键词 diff) | 唯一带安全性的删除:若覆盖不全,删一期路由会造成安全回归 | 安全/合规负责人 |
| T-05 | 底座接触面授权(组 2 的 4 个文件) | 不做则访客权限无法实时收紧、受理与执行身份可能不一致(RK-20) | 项目负责人 + 底座 owner |
1.2 测试环境就位(G-00 · 最优先)
⚠️ G-00 不是形式要求:当前本机依赖零安装、无 venv,只能做语法层验证(py_compile + AST 悬空 import 扫描)。而 G-01 要改鉴权入口与 Worker 执行路径、D 批次要改检索层——没有可运行的测试套件时,这些改动等于盲改。
| 动作 | DoD |
| 依赖与 venv 就位 | pip install -e . 成功;python -c "import fastapi, sqlalchemy, asyncmy, pydantic" 通过(须实测能 import 依赖,不能只看 --version) |
| 门禁基线 | 按 docs/14 命令集跑通并记录原始数字:ruff check app tests tools alembic / mypy app / pytest tests/unit tests/contract / pytest tests/integration / python tools/audit_schema.py(预期 90 张表 = 89 业务表 + alembic_version) |
| 跑前纪律 | 跑验收脚本前先停常驻 Worker(否则抢队列);集成测试前先 seed_test_rbac.py + set_user_password.py |
1.3 纪律基线
| # | 纪律 | 说明 |
| 1 | 零 DDL | 本期不改表结构、不加字段;`tools/audit_schema.py` 前后一致是硬证据 |
| 2 | 分层判据 | 「被多个 Agent 使用 / 在 ToolRegistry 注册为公共只读工具 / 承载鉴权·记忆·意图·模型·工具·合规·审计·持久化 8 项中任一项」→ 底座层,须会签;否则业务层,自主重构 |
| 3 | 会签门(先提案后动手) | 未获受理的项按降级方案执行,不得静默绕过;也不得为「绕过会签」而在业务层重造同一能力 |
| 4 | 禁止新建检索入口 | 两个入口=两条可能漏过滤的路径;只能改造既有签名 |
| 5 | 证据留痕 | 每项任务须给出「改了哪些文件 / 为什么 / 验证方式 / 未验部分」 |
2. 工程落位
2.1 三类落位的纪律
本次为重构既有实现,且底座原则上不可修改,因此遵循「原位改造 + 最小新增 + 最小挂载」。
| 类型 | 内容 | 纪律 |
| 原位改造 | 客服 Agent 主体、会话记忆、转人工三件套 | 不改文件名、不改对外签名、不迁移目录;改造前先确认既有行为的验证方式 |
| 最小新增 | 档位过滤、档位标注器、主体判定、访客令牌、访客限流、合规词库、actor.py、knowledge_tier.py | 不新增架构层;文件名与既有命名风格一致 |
| 最小挂载 | 路由注册、Agent 工厂分支、配置项追加 | 只追加不改既有逻辑;每处追加在评审中单独说明理由 |
| 不触碰 | 投顾已清除(无对象);其余公共基座只调用不改写 | 例外见 §4.2(组 2 的本轮扩张) |
2.2 目录落位(按既有真实结构)
app/
├── api/
│ ├── controllers/
│ │ ├── agent_runs.py # 既有 · 扩展:承载客服对话路由
│ │ ├── conversations.py # 既有 · 复用:会话消息与反馈
│ │ └── knowledge.py # 既有 · 复用:知识库 upload/list/search/delete
│ └── dependencies/
│ ├── auth.py # ★组2 · 改:跳过身份解析的条件语义化(G-01b)
│ └── rate_limit.py # 既有 · 复用:登录与访客令牌的 IP 闸门
├── service/
│ ├── agent/
│ │ ├── base.py # ★组2 · 改:访客不召回的「谓词」替换(G-01b)
│ │ ├── authorizer.py # 既有 · 复用(方案甲落地时才改)
│ │ ├── bootstrap.py # 既有 · 扩展:注册重发后的客服 Agent 与工具
│ │ └── implementations/
│ │ └── customer_service.py # ★ 重建主体(原 748 行已随形态A清除)
│ ├── agent_run_application_service.py # 既有 · 扩展:补身份装配
│ ├── customer_service_session_memory_service.py # 既有 · 复用 + 扩展访客会话
│ ├── customer_service_handover_{context,admin,action}_service.py # 既有 · 复用(486 行)
│ ├── knowledge_search_service.py # 既有 · 改造:检索签名 fail-closed(D-01)
│ ├── knowledge_tool.py # 既有 · 改造:删 `del context`(D-04)
│ ├── tool_executor.py # 既有 · 复用(方案甲落地时才改)
│ └── visibility_tagger.py # 新增:档位标注器(含 internal 剔除)
├── core/
│ ├── config.py # 既有 · 追加配置项
│ ├── compliance_context.py # 既有 · 改造:补短否定式(C-04)
│ ├── customer_service_rules.py # 既有 · 复用:唯一安全路由 route_message()
│ ├── knowledge_schema.py # 既有 · 复用:运行时字段探测(禁字面量)
│ ├── memory_scope.py # 既有 · 复用:记忆范围唯一口径
│ ├── actor.py # ★新增(G-01):访客判定与三元组唯一来源
│ ├── knowledge_tier.py # ★新增(G-03):档位推导,调 actor
│ └── security.py # ★组2 · 改:访客分支改调 actor(G-01)
├── worker/
│ └── runtime.py # ★组2 · 改:三元组第二份副本改调 actor(G-01)
└── static/portal/common/customer-service-widget/ # 既有 · 复用:客服挂件
⚠️ 标 ★组2 的 4 个文件是本轮唯一主动扩张的底座接触面(core/security.py、worker/runtime.py、api/dependencies/auth.py、service/agent/base.py)。其中 3 个原本写在「底座零改动清单」里。必须单独会签、单独 PR,不得与组 1 混提交。
3. 执行计划
3.1 批次总览(7 个批次 · 51 项)
| 批次 | 主题 | 项数 | 目标 | 是否碰底座 |
| A | 冻结与准备 | 10 | 把「当前是什么样」钉死,后续任何「红了」都能区分是我改坏的还是本来就有的 | 否(产出会签材料) |
| B | 语料与话术 | 5 | 把客户可见的跨层不一致一次清干净;串行,只重跑一次灌库 | 1 处(governance.py) |
| C | 规则重构与安全 | 9 | 补齐安全缺口与访客侧推介边界;一次定稿关键词表、一次双向验证 | 2 处(compliance_context / governance) |
| D | 架构护栏 | 7 | 为「加档位 / 加身份」备前置;D-02 是静默降级,静态扫描抓不到 | 2 处(knowledge_search_service / knowledge_tool) |
| E | 业务闭环与出口 | 8 | 建单白名单、priority、reason_code 枚举化(含 1 项挂起) | 1 处(agent_persistence_service) |
| F | 演示与收口 | 7 | 文档回写、演示准备、dry-run | 否 |
| G | 访客与鉴权(新增) | 5 | 把「访客与角色分离」落为可执行任务 | 4 处(主动扩张) |
3.2 批次 A · 冻结与准备(10 项,立即开动)
| ID | 任务 | 关键 DoD | 风险 |
| A-01 | 安全用例集基线复现 | 逐条记录通过/失败;改为「只登记预期、不跑实测」——被测对象已不存在,实测后移至 C-06 之后 | LOW |
| A-02 | 门禁数字基线 | 5 项命令 + 日期 + 解释器路径 + SQLAlchemy 补丁版;跑前先停 Worker | LOW |
| A-03 | 配置与环境快照 | active 版本 id + 条数 + agent_tools 白名单全文(须同时含「客户侧」与「游客侧」知识工具);三集合字段名 + 行数;embedding 模型名 + 维度 | LOW |
| A-04 | 业务一致性三查基线 | 品牌名 / 占位符 / 界面名差集 + 旧热线号码全部位置(清单里只要求 4 份清单) | LOW |
| A-05 | 演示前检查清单固化 | 五项:Docker Desktop → Milvus → Worker → 行情未过期 → MILVUS_LOCAL_URI 为空 | LOW |
| A-06 | 分支与 PR 策略 | 每批次一个 PR;底座会签项单独一个 PR(便于 owner 只审那一份 diff) | LOW |
| A-07 | 访客链路可用性实测 | 实跑一次访客请求;确认「游客侧知识工具」在白名单内;记录访客 context.user_id 形态(须为数字串) | 中 |
| A-08 | 前端约束与配合点复核 | 产出「需前端配合项清单」;结论可以是 0 项,但必须是核对后的 0 项 | LOW |
| A-09 | 《可改文件白名单》落文 | 四类:纯新增 / 允许修改 / 提案后由底座方修改 / 禁止修改;附「零 DDL」声明与基线截图 | LOW |
| A-10 | 底座会签申请单落文 | 对组 1 六处 + 组 2 四处逐项写清六件事:改什么 / 为什么是公共缺陷 / 最小化边界 / 规范依据 / 影响面 / 降级方案 | LOW |
3.3 批次 B ~ F 摘要
| 批次 | 关键任务 | 必须记住的一条 |
| B(5) | B-01 语料入库门禁四查 → B-02 语料一次性修正 → B-03 界面指代修正 → B-04 重跑灌库(唯一一次) → B-05 热线与服务时间单点化(五组落点) | 顺序不可调:门禁 → 改语料 → 定值 → 重跑 + 三查。B-05 含 1 处底座改动须会签;验收口径为 app/ tests/ tools/ knowledge/ 范围内 grep 旧值 = 0(docs/** 历史记载不改) |
| C(9) | C-01 零容忍集语义纠错 → C-03 安全词表取回 → C-04 补短否定式 → C-06 四向验证 → C-07 删除一期路由 | C-03 必须从留痕文档逐条抄,不许凭记忆重写(词条缩水不报错);C-06 → C-07,直接删一期路由=提示词注入拦截消失 |
| D(7) | D-01 检索签名 fail-closed → D-02 按集合逐个拼过滤表达式 → D-03 over-fetch → D-04 删 del context、按身份推导档位 → D-06 访客主体口径 | D-02 的落点有三处(主检索 + 产品名召回 + 父块召回),必须同批改;漏改后两处 → 概括型问句继续静默转人工 |
| E(8) | E-01 建单白名单 + priority + reason_code 枚举化 → E-02 日志按 reason 区分 → E-03 出口 → E-04 审计(含 1 项挂起) | 建单白名单必须限定 run.agent_type == "customer_service"——否则改动其它 Agent 的既有建单行为 |
| F(7) | F-01 重建含主体过滤的历史读取 → F-05 文档回写 → F-06 dry-run | F-01 禁止从备份恢复旧实现——那份正是「只按 session_id 取历史、跨主体可读」的缺陷本体;须在新链路重写并调用 memory_scope |
3.4 批次 G · 访客与鉴权(5 项 · 独立会签组)
| ID | 任务 | DoD 要点 | 依赖 | 风险 |
| G-00 | 测试环境就位 | 门禁可运行并记录基线(见 §1.2) | — | LOW |
| G-01 | 访客权威单点化(方案乙) | ① 三元组只有一个构造来源;② security.py 与 runtime.py 均调用它;③ 对外行为零变化(问答、限流、令牌 TTL 全部不变);④ 新增接缝单测:同一输入下两侧产出必须相等(这正是当前缺失的测试) | G-00 | 中 |
| G-01b | 判定口径单点化 | 6 处访客判断全部改走统一谓词;⚠️ Agent 基类那处的「位置与层级」不得变(仍留在基类、仍不依赖 Agent 声明位) | G-01 | 中 |
| G-02(挂起) | 身份轴(方案甲) | roles 回归纯 RBAC;20 余处 allowed_roles 中的 "visitor" 迁至身份轴声明 | G-01b、MVP 演示跑通 | 高 |
| G-03 | 档位推导单点化 | 档位由统一谓词推导,不由工具层自行判身份字段;⇒ 将来 G-02 落地时只需改 1 个文件 | G-01b、D-01 | LOW |
3.5 里程碑
flowchart LR
M1["M1 冻结完成
批次 A + G-00 完成"] --> M2["M2 语料与话术一致
批次 B 完成"]
M2 --> M3["M3 安全与规则就绪
批次 C 完成"]
M3 --> M4["M4 身份与护栏就位
批次 G-01/G-01b/G-03 + D 批次完成"]
M4 --> M5["M5 业务闭环
批次 E 完成"]
M5 --> M6["M6 演示跑通
批次 F 完成(最终验收)"]
style M1 fill:#e3f2fd,stroke:#1976d2
style M4 fill:#fff3e0,stroke:#f57c00
style M6 fill:#c8e6c9,stroke:#388e3c
4. 底座接触面与两组会签
4.1 组 1 · 六文件八处(原计划内,须会签)
| # | 文件 | 触碰项 | 改什么 |
| 1 | service/knowledge_search_service.py | D-01 | include_internal: bool → tiers: frozenset[str](必填、无默认值);_visibility_filter 同步按 tiers 拼表达式;非法值收敛为 {"public"} |
| 2 | 同上 | D-02 | 表达式按集合逐个拼(filter=expression if schema.has("visibility") else None);缺字段时不再回落 public;增加「因缺字段跳过过滤」的独立计数 |
| 3 | service/knowledge_tool.py | D-04 | 删 del context;按身份推导档位后传入检索 |
| 4 | core/compliance_context.py | C-04 | NEGATION_CUES 补短否定式:不保本 / 不保收益 / 非保本 / 并非保本 / 不确保 / 不担保 |
| 5 | service/agent/governance.py | B-05 | 删旧热线常量与只对旧号生效的脱敏白名单分支 → 内联为固定脱敏返回(该分支已成为不可达死代码) |
| 6 | service/agent_run_application_service.py | D-06 + F-01 | ① 访客消息的 customer_id 按身份取值(访客为空);② 重写历史读取并调用记忆范围模块做主体过滤 |
| 7 | service/agent_persistence_service.py | E-01 | 建单白名单(限定客服 Agent)+ 赋 priority + reason_code 枚举化 |
4.2 组 2 · 访客与鉴权四文件(本轮主动扩张)
⚠️ 为什么必须单列:这 4 个文件不在组 1 名单内,其中 3 个还写在「底座零改动清单」里。单列的目的是让「本次主动扩张了底座接触面」这件事可见、可审、可单独回滚,而不是藏在某处顺手改掉。
| # | 文件 | 触碰项 | 改什么 | 最小化边界 |
| 2-1 | core/security.py | G-01 | 访客分支改为调用新增的 actor.anonymous_context()(行为逐字不变,只改「值从哪来」) | 不动 jwt.decode 参数、不动 sub 校验、不动 visitor claim 语义 |
| 2-2 | worker/runtime.py | G-01 | 同上——第二份副本改为调用同一构造点 | 不动 restore_context() 签名、不动身份解析分支 |
| 2-3 | api/dependencies/auth.py | G-01b | 「跳过身份解析」的条件改为语义化谓词 | 不动鉴权入口结构、不动 401 口径、不新增任何路由 |
| 2-4 | service/agent/base.py | G-01b | 访客不召回的谓词替换 | ⚠️ 仍留在基类、仍不依赖 Agent 声明位——这是底线,不是可选项(不变量②) |
与「零改动清单」的关系:原清单把 app/api/**、app/worker/**、service/agent/base.py 列为「本次明确不碰」。本轮明确修订该声明——上述 4 项由批次 G 触碰,依据是《需求文档》FR-CS-043 / FR-CS-044。除这 4 个文件外,零改动清单的其余条目继续有效。
📌 额外复核项:docs/33/docs/34 对 security.py 做过逐行实证(涉及 sub 生成、decode 参数、sub 校验、访客分支位置等若干行)。本组改动会使这些行号漂移,因此 G-01 完成后必须复核那些逐行结论是否仍成立,并在会签单里说明。
4.3 会签流程
| 步 | 动作 | 产物 |
| 1 | A-09 落文《可改文件白名单》(四类) | 纪律凭据 + 零 DDL 声明 |
| 2 | A-10 落文会签申请单(组 1 与组 2 各一份) | 可抄送底座 owner 的正式申请 |
| 3 | 提交 → 等待受理(唯一的外部队列) | 受理记录 |
| 4 | 受理后由底座方修改(或授权后自改) | 单独 PR,只含该组 diff |
| 5 | 未获受理 → 走降级方案并文档标注 | 降级登记 |
5. 关键路径与约束
5.1 关键路径(12 步 + 1 个会签等待窗口)
[会签窗口:A-10 提交 → 底座方受理 组1 六处 + 组2 四处] ──┐
↓
A-02 → A-07 → G-01 → G-01b → D-01 → D-02 → G-03 → D-04
→ D-06 → E-01 → E-03 → F-03 ──→ 演示跑通
↑
B-01 → B-02 → B-05 → B-04 ───┤
│
C-01 → C-03 → C-09 → C-06 ───┘
最长链 = 12 步(含 G 链)。会签往返不影响步数,但是唯一的外部队列——越早提交越早有回音,故 A-10 排在 A 批次内优先执行。
5.2 十二条硬串行约束(违反即返工)
| # | 约束 | 违反后果 |
| S-1 | B-01 门禁 → B-02 改语料 → B-04 重跑 | 顺序颠倒会把问题再灌一遍 |
| S-2 | B-05 热线定值 → B-02 填值 | 语料里会填进旧的/占位的号码 |
| S-3 | C-06 验证 → C-07 删除 | 直接删一期路由 → 提示词注入拦截消失(唯一带安全性的删除) |
| S-4 | D-02 修过滤表达式 → 任何集合加 visibility / 改字段名 | 缺字段的集合被同一表达式打挂 → 被吞成 failure → degraded=True → 客服全员「引导人工」且不报错 |
| S-5 | D-01 fail-closed → D-04 传身份 | 身份传进没有 fail-closed 语义的签名 = 把「记得过滤」交回调用方 |
| S-6 | D-03 over-fetch 与 D-01/D-02 同批 | 只有过滤没有 over-fetch → 过滤后 TopK 不足 → 上层误判「无答案」 |
| S-7 | 集合 schema 变更后必须重启 API + Worker | 检索服务是进程级单例,schema 缓存永不失效 |
| S-8 | 禁止在知识出口启用未完成的来源引用链路 | 治理层只认 memory/tool 来源 → 返回 knowledge 引用会让整个 run 失败 |
| S-9 | 底座两组未获会签前不得动手 | 绕过 = 形成第二套实现,其中一套必然漏掉隔离 |
| S-10 | 访客侧开关未做严禁开始出口与演示第 1 步 | 服务访客的 Agent 声明缺失 → 游客线永久失效,且失败表现为「请登录」,与设计如此无法区分 |
| S-11 | G-00 → G-01 → G-01b → G-03 → D-04 | ① 无测试环境改鉴权链路=盲改;② G-01 不做就改 D-04,档位会依赖两份可能不一致的身份定义;③ D-04 若自行判身份字段,则 G-02 落地时必须改两处,分离收益归零 |
| S-12 | 三处交叉点顺序固定:G-01b → D-06 → F-01(同一文件不同段) | 倒序会互相覆盖;且访客主体口径依赖身份判定已单点化 |
5.3 若多人并行:按「文件不相交」切四路
| 通道 | 负责批次 | 独占文件 |
| 通道 1 · 语料 | 批次 B 全部 + F-06 | knowledge/*、语料构建脚本 |
| 通道 2 · 规则与数据层 | 批次 C 全部 + E-01(业务侧) | core/customer_service_rules.py、禁用词种子 |
| 通道 3 · 检索护栏 | 批次 D 全部 + F-01 | knowledge_search_service.py、knowledge_tool.py、core/knowledge_tier.py |
| 通道 4 · 出口与文档 | 批次 A + E-02/E-04 + F 文档类 | implementations/customer_service.py、docs/* |
| 通道 0 · 底座会签 | 组 1 六处 + 组 2 四处 | 各自单独一个 PR,由底座 owner 审 |
三处交叉点需串行:① agent_run_application_service.py 由通道 3(D-06)与通道 4(F-01)先后改,且现在又加入 G-01b——顺序固定 G-01b → D-06 → F-01;② agent_persistence_service.py 只由通道 2(E-01)改;③ tool_executor.py 仅由条件触发项碰,且排在其后。
6. 质量门禁与完工判据
6.1 质量门禁
| 门禁 | 命令 / 判据 |
| 代码检查 | ruff check app tests tools alembic → 0 错 |
| 类型检查 | mypy app → 0 错。注意 SQLAlchemy 补丁版差异会造成量级差异(曾出现「一边上百个错、另一边 0 错」) |
| 单测 + 契约测 | pytest tests/unit tests/contract → 0 failed(绝对用例数会随开发增减,判据是 0 failed) |
| 集成测 | pytest tests/integration → 0 failed。前置:先跑 RBAC 种子与口令脚本 |
| 零 DDL | python tools/audit_schema.py → 90 张表(89 业务表 + alembic_version),前后一致 |
| 文档守卫 | python tools/check_authoritative_docs.py 通过 |
| 离线兜底 | 无依赖环境下的替代验证:全量 py_compile 0 错 + AST 悬空 import 0 条 |
6.2 整体完工判据(12 条)
| # | 判据 | 怎么验 |
| 1 | 业务一致性三查全绿 | 语料 0 占位符、0 旧品牌;热线/服务时间代码与语料一致;界面名全在站内链接表内 |
| 2 | 安全只增不减 | 红队用例与 A-01 基线逐条对比,无一条变松 |
| 3 | 规则三个方向都对 | 概念题可答 + 诱导性问法仍拒答 + 访客推荐类请求不产生推介 |
| 4 | 护栏生效 | 访客检索 registered 返回空、客户同期正常;公开问题召回量与基线一致;「缺字段的集合」有独立计数、不再污染降级标记 |
| 5 | 访客主体一致 | 访客消息 customer_id 为空;工单侧同为 NULL;历史读取走记忆范围模块 |
| 6 | 工单分类正确 | 「答不上来」不建单;反诈工单 P0;投诉 P1;主动要人工 P2;其它 Agent 建单行为未变 |
| 7 | 门禁干净 | §6.1 全部通过 |
| 8 | 演示跑通 | MVP 演示步骤全部可见,含「无投资建议类内容」 |
| 9 | 红线可举证 | 适当性不匹配场景可在消息表与审计表中还原「揭示 → 确认」顺序 |
| 10 | 底座纪律达标 | 实际改动文件 ⊆ A-09 白名单;两组每一处都有会签记录(或走降级并文档标注);零 DDL 证据;未绕过统一鉴权/工具/合规/审计流程 |
| 11 | 访客与角色已分离 | 访客三元组只有一个构造来源;访客链路端到端行为与动手前逐项一致;身份判定已全部走单点模块;档位由档位模块推导;三条不变量逐条可举证 |
| 12 | 文档一致 | 四份文档交叉引用无冲突;docs/** 历史记载已按 F-05 回写标记 |
7. 风险与分工
7.1 头号风险:投顾清除后失去第二条回归业务线
⚠️ 本条必须置顶:投顾原本是 6 个底座公共件改动时的对照组——它是唯一完好的业务线,能在改底座时暴露跨模块回归。它在 2026-09-17 被整体清除后:底座改动的回归验证只剩客服一条线。
应对三条:① G-00(测试环境就位)优先级上调为最前置;② 底座两组改动必须全量跑 §6.1 门禁,不得只跑单测;③ 组 2 单独 PR,便于独立回滚。
7.2 风险重排(前 8 项)
| 排名 | 风险 | 最高风险点 | 对策 |
| 1 | 失去对照组(投顾已清除) | 底座改动无第二条线兜底 | G-00 前置 + 全量门禁 + 组 2 单独 PR |
| 2 | D-02 过滤器按集合逐个拼 | 改错会让客服全员转人工且不报错 | 先补两类替身测试(部分集合有/部分没有、字段名不同)再改实现;上线后立刻验召回量不变;保留独立计数 |
| 3 | G-01/G-01b 身份单点化 | 改鉴权入口与 Worker 执行路径,无测试环境时是盲改 | G-00 必须先完成;新增接缝单测(两侧产出必须相等);对外行为零变化的验收方式 |
| 4 | C-06 四向验证 / C-03 词表取回 | 词表缩水不报错;补偿式修改会放过真实承诺 | 从留痕文档逐条抄;四个方向用例都必须有;反例守卫 |
| 5 | C-09 访客推介边界 | 按主体分化输出规则时可能误伤客户侧(或反之) | 客户侧必须做回归验证;按身份分支而非合并词表 |
| 6 | E-01 建单白名单 | 若不限定 agent_type,会改动其它 Agent 的建单行为 | DoD 明确「仅对客服 Agent 生效」;把其它 Agent 的既有建单用例纳入回归 |
| 7 | A-07 访客链路实测 | 若游客侧工具未在白名单,全线失败表现为「请登录」 | 实测 + 日志按 reason 区分;A-03 快照留白名单全文 |
| 8 | B-04 / F-06 两次连外部服务 | 环境问题伪装成功能缺陷 | 先跑 A-03/A-05 快照与自检;B-04 前停 Worker;F-06 先 dry-run |
7.3 分工与交付物
| 角色 | 职责 | 对应批次 |
| 后端架构师 | 骨架、鉴权与身份、DB、统一响应、知识库接口、会话记忆、合规子模块、转人工、工单 | A / G / E / 部分 B·C |
| AI 工程师 | 文档解析、向量化、集合与检索、意图分类、主流程、事件 | D / 部分 B·C |
| 业务开发(咨询) | 合规词库、适当性规则、客群分层口径 | 评审 C / E |
| 全员 | 演示准备与最终验收 | F |
| # | 交付物 | 形态 | 验收人 |
| 1 | 四份文档(需求 / 开发计划 / 执行 Todolist / 知识库设计方案) | HTML ×3 + Markdown ×1 | 团队 + 讲师 |
| 2 | 客服 Agent 源码 | .py | 代码评审人 |
| 3 | 接口文档(自动生成 + 补充说明) | 在线 + Markdown | 全栈/集成 |
| 4 | 知识库入库清单与来源映射表 | Markdown | AI 工程师 |
| 5 | 测试报告(按 §6.1 门禁实际执行结果) | Markdown | 全员 |
| 6 | 演示脚本 | Markdown | 主讲人 |
| 7 | 开发过程会议纪要(≥ 5 份) | Markdown | 团队 |
| 8 | 会签材料(可改文件白名单 + 会签申请单 ×2) | Markdown | 底座 owner |
| 9 | 清除留痕(客服形态A + 投顾清除的执行报告与回退备份说明) | Markdown | 项目负责人 |
文档结束 —— 本文档为《南方基金·智能服务系统》智能客服 Agent 的开发计划 v1.0,是四份交付文档的「计划」分册。开工时以《客服 Agent 执行 Todolist》为唯一入口;本文档定顺序与约束,Todolist 定每项的 DoD 与验证动作。