@@ -671,7 +671,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
@@ -877,7 +877,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
diff --git a/客服agent/D2.3-客服Agent开发计划.html b/客服agent/D2.3-客服Agent开发计划.html
index aecdea9..8fcd7fb 100644
--- a/客服agent/D2.3-客服Agent开发计划.html
+++ b/客服agent/D2.3-客服Agent开发计划.html
@@ -316,7 +316,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
@@ -394,13 +394,13 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
| 项 | 状态 |
| 客服 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/ |
+| 投顾模块 | 已于 2026-09-17 整体清除(后端 21 文件 + 前端 employee-advisor/ 9 文件 + /api/v1/advisor 全部端点 + 5 个脚本 + 14 个测试 + 相关权限码)。验证:0 语法错误、0 悬空 import;备份 _advisor_purge_backup/ ⚠️ 2026-09-20 状态更新:投顾模块已随合并恢复(W12;远端组员 3 个提交反向依赖被清除的模块,裁定「组员新功能 > 本地清除」)。本轮客服侧工作不受影响:本计划的批次、接触面与门禁均针对客服 Agent,投顾恢复只是把「第二条回归业务线」还了回来。见 D1.6 §4.37 / D4.7。 |
| 身份与鉴权方向 | 已拍板:「方案乙(收敛)现在做 → 方案甲(拆轴)MVP 后」 |
| 工程纪律 | 19 项决策已全部定案;底座接触面已逐文件取证 |
-⚠️ 投顾清除带来一个必须正视的后果:投顾原是第二条回归业务线,用于验证 6 个底座公共件的改动。清除后,底座改动的回归验证只剩客服一条线。因此本计划把「测试环境就位(G-00)」列为最优先的前置——没有可运行的门禁时改底座,等于盲改。
+⚠️ 投顾清除带来一个必须正视的后果:投顾原是第二条回归业务线,用于验证 6 个底座公共件的改动。清除后,底座改动的回归验证只剩客服一条线。因此本计划把「测试环境就位(G-00)」列为最优先的前置——没有可运行的门禁时改底座,等于盲改。
⚠️ 2026-09-20 状态更新:投顾已随合并恢复 ⇒ 对照组回归,本条降级为「历史上曾存在的风险」;G-00 的优先级结论不变(本轮实测全量回归 1909 passed,已由事实替代推断)。
@@ -461,7 +461,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
| 原位改造 | 客服 Agent 主体、会话记忆、转人工三件套 | 不改文件名、不改对外签名、不迁移目录;改造前先确认既有行为的验证方式 |
| 最小新增 | 档位过滤、档位标注器、主体判定、访客令牌、访客限流、合规词库、actor.py、knowledge_tier.py | 不新增架构层;文件名与既有命名风格一致 |
| 最小挂载 | 路由注册、Agent 工厂分支、配置项追加 | 只追加不改既有逻辑;每处追加在评审中单独说明理由 |
-| 不触碰 | 投顾已清除(无对象);其余公共基座只调用不改写 | 例外见 §4.2(组 2 的本轮扩张) |
+| 不触碰 | 投顾模块(2026-09-17 曾清除、2026-09-20 已恢复,但本轮仍不触碰);其余公共基座只调用不改写 | 例外见 §4.2(组 2 的本轮扩张) |
@@ -759,7 +759,7 @@ A-02 → A-07 → G-01 → G-01b → D-01 → D-02 → G-03 → D-04
7. 风险与分工
-7.1 头号风险:投顾清除后失去第二条回归业务线
+7.1 头号风险:投顾清除后失去第二条回归业务线(⚠️ 2026-09-20 已随合并恢复 ⇒ 本条降级)
⚠️ 本条必须置顶:投顾原本是 6 个底座公共件改动时的对照组——它是唯一完好的业务线,能在改底座时暴露跨模块回归。它在 2026-09-17 被整体清除后:底座改动的回归验证只剩客服一条线。
应对三条:① G-00(测试环境就位)优先级上调为最前置;② 底座两组改动必须全量跑 §6.1 门禁,不得只跑单测;③ 组 2 单独 PR,便于独立回滚。
@@ -768,7 +768,7 @@ A-02 → A-07 → G-01 → G-01b → D-01 → D-02 → G-03 → D-04
| 排名 | 风险 | 最高风险点 | 对策 |
-| 1 | 失去对照组(投顾已清除) | 底座改动无第二条线兜底 | G-00 前置 + 全量门禁 + 组 2 单独 PR |
+| 1 | 失去对照组(投顾已清除 → 2026-09-20 已恢复,对照组回归) | 底座改动无第二条线兜底 | G-00 前置 + 全量门禁 + 组 2 单独 PR |
| 2 | D-02 过滤器按集合逐个拼 | 改错会让客服全员转人工且不报错 | 先补两类替身测试(部分集合有/部分没有、字段名不同)再改实现;上线后立刻验召回量不变;保留独立计数 |
| 3 | G-01/G-01b 身份单点化 | 改鉴权入口与 Worker 执行路径,无测试环境时是盲改 | G-00 必须先完成;新增接缝单测(两侧产出必须相等);对外行为零变化的验收方式 |
| 4 | C-06 四向验证 / C-03 词表取回 | 词表缩水不报错;补偿式修改会放过真实承诺 | 从留痕文档逐条抄;四个方向用例都必须有;反例守卫 |
diff --git a/客服agent/D2.4-客服Agent知识库设计方案.html b/客服agent/D2.4-客服Agent知识库设计方案.html
index dd9f661..135de81 100644
--- a/客服agent/D2.4-客服Agent知识库设计方案.html
+++ b/客服agent/D2.4-客服Agent知识库设计方案.html
@@ -487,7 +487,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
| v1.0 | 2026-09-16 | 首次发布:三集合 + 三档可见性 + 八项技术选型决策 |
| v1.1 | 2026-09-16 | 基线对齐:新增 §1.5 业务基线、§12 待确认;术语补「游客/访客」对照;落位修正为 app/core/config.py |
-| v1.2 | 2026-09-17 | 与身份模型对齐 + 自洽性修正:① 检索签名由布尔改为档位集合(原 include_internal: bool 表达不了三档);② 上游依据统一指向《客服 Agent 需求文档》v2.4(原 doc 内混用 v2.1/v2.2);③ 补「客户档位降级」的配置承载(原降级态在映射表与配置里均无表达方式);④ 明确「降级原因提示」的边界(可提示账号状态、不可提示内容存在性);⑤ 配置项全集补全 4 项;⑥ metadata.type 取值统一小写;⑦ 删除 registered 档中的「基金投顾策略详情」示例(投顾模块已于 2026-09-17 整体清除);⑧ 明确「事件名」与「指标名」两套命名;⑨ 补档位报告产物规格与签收机制;⑩ 补 fin_knowledge_meta 字段级建议;⑪ 修正备选方案数(8 项决策共 26 个备选,原写 24);⑫ 新增 §1.5 与身份轴的接口 |
+| v1.2 | 2026-09-17 | 与身份模型对齐 + 自洽性修正:① 检索签名由布尔改为档位集合(原 include_internal: bool 表达不了三档);② 上游依据统一指向《客服 Agent 需求文档》v2.4(原 doc 内混用 v2.1/v2.2);③ 补「客户档位降级」的配置承载(原降级态在映射表与配置里均无表达方式);④ 明确「降级原因提示」的边界(可提示账号状态、不可提示内容存在性);⑤ 配置项全集补全 4 项;⑥ metadata.type 取值统一小写;⑦ 删除 registered 档中的「基金投顾策略详情」示例(投顾模块已于 2026-09-17 整体清除;⚠️ 该模块 2026-09-20 已随合并恢复,但本设计方案不对投顾知识引入任何档位 —— 删除该示例的决定继续有效,见 D4.7);⑧ 明确「事件名」与「指标名」两套命名;⑨ 补档位报告产物规格与签收机制;⑩ 补 fin_knowledge_meta 字段级建议;⑪ 修正备选方案数(8 项决策共 26 个备选,原写 24);⑫ 新增 §1.5 与身份轴的接口 |
| v1.2.1 | 2026-09-17 | 品牌全量口径统一:旧值(XX科技 / 400-XXX-XXXX / 南方财富 / nanfangwm.com)统一为南方基金(热线 400-889-8899 · 官网 nffund.com),系统名统一为「智能服务系统」。 |
| v1.3 | 2026-09-17 | 档位隔离增强 + 检索能力对接五出口架构:① §7.2 决策 2 补强——新增「集合内分区」备选并采纳:visibility 声明为 partition key,隔离由分区承担、标量字段保留用于词法回退与审计(写入侧对空值拒绝 = fail-closed);② 取消 over-fetch ×3(分区裁剪后「TopK 被不可见条目占满」的场景不再存在,精度净提升);③ 附录A 增加 visibility NOT NULL、family_id、param_class 三个字段;④ 附录B 补机器可判的档位判据并裁定「服务分层门槛属 public」;⑤ 新增 附录F(术语字典层 / 同族合并 / 证据包 / 计算型参数位 / 评测门禁);⑥ §5.5 补「回退不得跨档位」。 |
| v1.4 | 2026-09-18 | 落地回写 · 三集合已重建重灌(628 块):① §7.2.1 修正——实测 partition key 模式下禁止手工 create_partition,「档位值变更 = 建分区」作废,改为「无需动作,引擎按哈希自动路由」(num_partitions = 16,创建后不可改);② 附录A 补「实库 vs 设计态」对照——doc_id 业务主键 + 14 个 VARCHAR + embedding,family_id / param_class / intent 本轮未落地;③ 语料口径由 617 块(2026-09-16 陈旧件)更新为 628 块(faq 149 / policy 288 / product 191;public 603 / registered 25);④ 附录F 块长实测按新语料复测(平均 101.5 字 / 528 块 < 200 字 / 最长 2828 字)。 |
@@ -547,7 +547,7 @@ hr { border: none; height: 1px; background: linear-gradient(90deg, transparent,
| 检索、过滤、回退、兜底、来源引用 | 意图分类与路由(需求文档 §1.4 域 A) |
| 知识库管理接口规格 | 管理端前端页面 |
| 词法回退(关系型库 LIKE)作为降级手段 | 图谱检索(依赖图数据库) |
-| 性能、安全、部署、监控、验收 | 投顾相关一切能力——已于 2026-09-17 整体清除 |
+| 性能、安全、部署、监控、验收 | 投顾相关一切能力——不属本知识库范围(2026-09-17 曾随模块整体清除;2026-09-20 模块已恢复,但投顾知识仍不进入本设计的三集合与三档) |
@@ -1434,7 +1434,7 @@ RAG_QUERY_CACHE_TTL=300 # 秒;缓存键必须含主体标识Q-06 | 未说明与既有 1535 行代码的关系 | 可能重复实现已有能力 | ✅ 已补(§3.2 / §10.1) |
| Q-07 | 检索签名用布尔表达不了三档(原设计 include_internal: bool) | 布尔只有「含/不含」,无法表达「访客只看 public、客户看 public+registered」,且默认值即 fail-open | ✅ v1.2 已修正(改为档位集合,§5.4) |
| Q-08 | 客户档位降级态无配置承载,实现时必然落回硬编码 | 降级行为不可配置、不可审计 | ✅ v1.2 已修正(新增降级档位配置) |
-| Q-09 | registered 档示例含「基金投顾策略详情」,而投顾已整体清除 | 指向已不存在的业务 | ✅ v1.2 已删除该示例 |
+| Q-09 | registered 档示例含「基金投顾策略详情」,而投顾已整体清除(该模块 2026-09-20 已恢复,但「投顾知识不进客服知识库」的裁定不变) | 指向已不存在的业务 | ✅ v1.2 已删除该示例 |
| Q-10 | 未命中规则默认放行依赖「应该会有人复核」,缺兜底约束 | 实践中会退化为「默认放行且无人复核」,与 P2 冲突 | ✅ v1.2 已补:报告未签收即视为入库无效(§4.4 / §5.2) |
| Q-11 | 档位报告格式与签收机制未定义 | 复核环节无产物规格,无法留痕 | ✅ v1.2 已补(§5.2) |
| Q-12 | 文档内上游版本号混用(v2.1 / v2.2) | 追溯困难 | ✅ v1.2 已统一为《需求文档》v2.4 |
diff --git a/客服agent/D2.5-客服Agent演示脚本与账号速查-2026-09-19.md b/客服agent/D2.5-客服Agent演示脚本与账号速查-2026-09-19.md
index f1d5d85..03c52b1 100644
--- a/客服agent/D2.5-客服Agent演示脚本与账号速查-2026-09-19.md
+++ b/客服agent/D2.5-客服Agent演示脚本与账号速查-2026-09-19.md
@@ -9,6 +9,10 @@
## 1. 演示前五项自检(`A-05` 清单 · 本文即产物)
+> ✅ **首选做法(2026-09-20 起):双击仓库根目录的 `启动演示.bat`**(等价于 `powershell -ExecutionPolicy Bypass -File .\demo.ps1`)。它一次做完:拉起服务(幂等)→ **刷新行情** → **自动跑下面五项自检** → 打开访客页与客户登录页。
+> 常用参数:`-SkipStart`(服务已起,只自检 + 开页面)、`-NoBrowser`、`-Port 8100`、`-KeepPrices`(不刷新行情)。
+> 下面的手工命令表是**同口径的备用路径**(一键脚本不可用 / 想逐项看细节时用)。
+
> 五项**全过**才开讲。第 4 项最容易翻车(行情有效期只有 15 分钟)。
| # | 检查项 | 命令(在 `group_fqcd_jr` 下) | 2026-09-19 实测 |
@@ -43,9 +47,11 @@
| 运营专员 | `offsite_t` | `offsite123` | 同上(→ 运营工作台) | **200** `roles=['operator']` |
| **边界账号** | `review_t` | —— | —— | **401** ✅**设计如此**:账号存在但**不绑角色、不设口令**(`seed_test_rbac.py` 的 `USERS` 注释) |
| 访客 | 无需账号 | —— | `POST /api/v1/visitor-tokens` | **201**,令牌 `sub` 是**数字串**(`D-06` 的前提成立) |
+| 投顾顾问 | `advisor_t` | `abc12345` | `/portal/employee-advisor/login/` | **可用**(2026-09-20 `W12` 随投顾模块恢复而重建;账号 `9020` + `advisor` 角色 34 权限) |
| 画像演示客户 | `profile_c5` / `profile_c3` / `profile_c1` / `profile_c2` / `profile_expired` | —— | —— | **仅数据层**(无口令);`profile_expired` 专门覆盖「测评过期 = 失败关闭」 |
-> ⚠️ **不要念 `advisor_t / abc12345`**:投顾模块已整体清除,该账号在库里**不存在**(`D4.5`)。该账号已于 2026-09-20 重建(`tools/grant_advisor_role.py` + `tools/create_test_user.py --id 9020`)⇒ `docs/44-演示流程.md` 与 `docs/40` 里的那一行**重新有效**。
+> 📌 **`advisor_t` 口径更正(2026-09-20)**:投顾模块**已于 2026-09-20 随合并恢复**(`W12`;「整体清除」被组员新功能取代,见 `D4.5` 顶部状态更新与 `D4.7`),该账号已重建、**可以登录**。但**本演示脚本仍只演「游客线 + 客服线」** —— 投顾线是组员的地盘,讲客服时不必替它背书;被问到时说明「投顾线已恢复,可单独演示」即可。
+> ⚠️ **注意一处未做**:投顾的 `config_release` 工具白名单(`advisor:*`)**当前未发布** ⇒ 投顾 Agent 的工具调用会 fail closed(2026-09-20 实测 `active_agent_tools` 只有 `customer_service:*` 与 `risk:*`)。要演投顾线,先跑 `tools/publish_advisor_demo_config.py --apply`。**与客服线无关。**
### 2.2 冷启动(换机器/重启后重建演示数据)
@@ -180,4 +186,6 @@ cd D:\桌面\金融\group_fqcd_jr
| 本文对应的 Todolist 项 | `D2.1` 批次 F:`F-03` / `F-04` / `A-05` |
| 台词证据(真 HTTP 原始答复) | `group_fqcd_jr/docs/evidence/20260919-t8-demo-lines.json`(17 条)、`20260919-t8-demo-lines2.json`(5 条) |
| 出口定义与判分规则 | `D3.7-客服Agent评测金标集与判分规则`、`D3.6-客服Agent智能增强架构建议` |
+| **演示一键启动** | `group_fqcd_jr\demo.ps1` + `group_fqcd_jr\启动演示.bat`(五项目检口径与本文 §1 **完全一致**) |
+| **答辩后立刻做**:模型密钥轮换 | `D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md`(工具 `tools/rotate_api_keys.py`) |
| 会话记录 | `D1.6-对话上下文提取与开工前补充决策` 对应轮次 |
diff --git a/客服agent/D2.6-客服Agent答辩报告-2026-09-19.md b/客服agent/D2.6-客服Agent答辩报告-2026-09-19.md
index 729cead..ca7279a 100644
--- a/客服agent/D2.6-客服Agent答辩报告-2026-09-19.md
+++ b/客服agent/D2.6-客服Agent答辩报告-2026-09-19.md
@@ -4,7 +4,8 @@
> **读者**:答辩评委 + 答辩当天操作演示的人 + 三个月后的自己。
> **性质**:本报告回答**一个**问题 —— 「答辩老师批评这个客服 Agent **不智能、动不动就转人工**,凭什么说现在改好了?」
> **口径**:本文所有数字均为**真机实测**(`_eval_harness` 46 条金标 + `http_probe` 全链路 + `e2e_smoke_test` 宽链路冒烟 + 12 条真机边界用例),**修复前基线如实并列**,不修饰。
-> **配套**:架构依据 `D3.6`(五出口 + 安全不变量);判分规则 `D3.7`(46 条金标 / 10 项指标 / 4 项零容忍);演示脚本与账号 `D2.5`;执行看板 `D2.1`;会话留痕 `D1.6` §4.36。
+> **配套**:架构依据 `D3.6`(五出口 + 安全不变量);判分规则 `D3.7`(46 条金标 / 10 项指标 / 4 项零容忍);演示脚本与账号 `D2.5`;执行看板 `D2.1`;密钥轮换 `D3.8`;会话留痕 `D1.6` §4.36 与 §4.37—§4.39。
+> **状态更新(2026-09-20 · `W12`/`W13`)**:本文的**结论与金标数字全部不变**(金标仍是同一套用例、同一台机器)。但有三处外部事实需要并读:① **投顾模块已随合并恢复**(组员新功能取代「整体清除」,见 `D4.5` 顶部状态更新与 `D4.7`)—— 对本客服 Agent 的能力与门禁**无影响**;② 权威文档目录(`客服agent\` 24 份 / `开发文档\` 52 份)**已入库**,全量回归在其后复跑(**1909 passed / 3 skipped**,见 §6.3);③ 增加了**模型密钥轮换工具** `tools/rotate_api_keys.py`(操作手册 `D3.8`),§10 第 4 项由「手工 4 步」升级为「跑一个脚本」。
---
@@ -181,11 +182,12 @@
| 门禁 | 结果 |
|---|---|
-| 全量单测 + 契约测 + 集成测 | **1856 passed / 2 skipped / 0 failed** |
+| 全量单测 + 契约测 + 集成测(`W12` 权威文档入库后复跑) | **1909 passed / 3 skipped / 0 failed**(`W11` 时为 1856 / 2 skipped —— 差额为本轮新增用例) |
| 宽链路 HTTP 冒烟(`e2e_smoke_test --read-only`) | **31/31 通过** |
| HTTP 全链路探针(`http_probe.py`,含访客线 + 客户线 + 反诈/账户/代办/画像/费率/多轮) | **11/11 succeeded** |
-| 静态检查 / 类型检查 | `ruff` **19**(持平基线)、`mypy` **2**(持平基线) |
+| 静态检查 / 类型检查 | `ruff` **20**(远端分支本身为 22;本地客服线基线 19,**未引入新债**)、`mypy` **2**(= 既有基线) |
| 跨文档一致性 | `_consistency.py` **GATE PASS** |
+| 门户接口清单 | `tools/portal_api_check.py` 40 项:**通过 35 / 失败 0 / 跳过 5**(空集按 `SKIP` 而非 `FAIL`) |
| 真机入参边界(12 条) | **12/12 符合预期**(超限一律 `422` + 字段级错误,不再落库 500) |
---
@@ -204,11 +206,11 @@
| 项 | 落点 |
|---|---|
-| 可改文件白名单(四类) | `group_fqcd_jr\docs\46-可改文件白名单.md`(`A-09`) |
-| 底座会签申请单(4 组,逐项最小化边界 + 降级方案) | `group_fqcd_jr\docs\47-底座会签申请单-2026-09-19.md`(`A-10`) |
+| 可改文件白名单(四类) | `group_fqcd_jr\docs\48-可改文件白名单.md`(`A-09`) |
+| 底座会签申请单(4 组,逐项最小化边界 + 降级方案) | `group_fqcd_jr\docs\49-底座会签申请单-2026-09-19.md`(`A-10`) |
| 零 DDL 声明 | 不新增/不修改任何表结构;`audit_schema.py` = 89 张业务表与基线一致 |
| 跨文档一致性 | 需求 ↔ 计划 ↔ Todolist ↔ 知识库 四份交叉引用无冲突 |
-| 会话留痕 | `D1.6` §4.1—§4.36(每轮"你说了什么 → 我做了什么 → 实测是什么") |
+| 会话留痕 | `D1.6` §4.1—§4.39(每轮"你说了什么 → 我做了什么 → 实测是什么";§4.37—§4.38 = `W12` 合并与文档入库,§4.39 = `W13` 密钥轮换工具 + 文档审计) |
---
@@ -231,8 +233,8 @@
| 1 | `G-02` 身份轴(方案甲) | **按裁定挂起**,等 MVP 演示通过后再做 | 访客角色仍走 RBAC 的 `visitor` 角色(`actor.py` 单点构造),当前行为正确,只是"身份轴"这一层抽象未引入 |
| 2 | `E-07` | 按裁定挂起 | — |
| 3 | `M-2` / `M-2b` 剩余近分(28/31、15/18) | 按裁定**不做家族加权** | 剩余未命中是"同族多块打平"类,属检索区分度问题,不影响出口与事实正确率(均 100%) |
-| 4 | 两把 API key 轮换 | 需登服务商控制台操作,且已在会话中出现过明文 | **答辩后当轮立刻轮换**(4 步见 `D1.6` §4.35 第五节第 2 项);任何文档不落 key 值 |
-| 5 | `A-10` 组 3 / 组 4 的**签字** | 需你本人签字(已一次性授权,本单为逐项留痕) | 不签字则"两组每一处都有会签记录"这条完工判据不完整 |
+| 4 | 两把 API key 轮换 | 需登服务商控制台操作(**控制台建新 key 这一步无法自动化**),且已在会话中出现过明文 | 🆕 **已就绪:跑一个脚本** —— `tools/rotate_api_keys.py`(先 `--check` 体检,再交互式输入;自动备份 + 三个 Qwen 变量同值 + 两个 DeepSeek 变量同值)。完整 5 步见 **`D3.8`** 操作手册;任何文档不落 key 值 |
+| 5 | `A-10` 组 3 / 组 4 的**签字** | ~~需你本人签字~~ → ✅ **2026-09-20 已补签受理**(`甲-3` 本人会签 + 逐项留痕;组 1—组 4 全部 ☑ 受理,见 `D2.1` v6.23 第 8 条与 `docs\49-底座会签申请单-2026-09-19.md`) | 本项**已闭环**,不再是未做项 |
| 6 | 长期记忆召回 / 画像写入 | `DEC-19` 合规裁定:短期会话记忆=开、**长期记忆召回=关**、画像=客户侧字段级只读 | 这是**合规要求不是缺陷**;被问到时按 `DEC-19` 口径回答 |
| 7 | `dependency_health_check.py` 把 neo4j 当硬前置 | 属底座工具,改动需另立会签 | 演示前五项自检用替代判据(`D2.5` §1),**不用它**判"环境没准备好" |
@@ -262,5 +264,5 @@
| 方案 | 出口 **2 → 5**(`E1` 澄清 / `E2` 计算 / `E3` 直返 / `E4` 证据约束生成 / `E5` 分级回退) |
| 安全 | 5 条不变量(`INV-1`—`INV-5`)+ 转人工白名单 4 类 + 档位物理隔离;**安全只增不减** |
| 效果 | 转人工率 **43.5% → 10.9%**;出口准确率 **45.7% → 100%**;事实正确率 **69.6% → 100%**;4 项零容忍**全 0** |
-| 验证 | 46 条金标 11 项全达标 + 1856 单测 0 failed + 31/31 宽链路冒烟 + 11/11 HTTP 探针 + 12/12 真机边界 |
+| 验证 | 46 条金标 11 项全达标 + **1909** 单测 0 failed + 31/31 宽链路冒烟 + 11/11 HTTP 探针 + 12/12 真机边界 + 门户接口 35 通过 / 0 失败 |
| 纪律 | 白名单(`A-09`)+ 会签单(`A-10`,4 组)+ 零 DDL + 跨文档一致性 GATE PASS |
diff --git a/开发文档/D1.1-文档索引与权威声明.md b/开发文档/D1.1-文档索引与权威声明.md
index 4e75509..c309e87 100644
--- a/开发文档/D1.1-文档索引与权威声明.md
+++ b/开发文档/D1.1-文档索引与权威声明.md
@@ -2,22 +2,22 @@
> **体系编号**:`D1.1` · 域:一、治理与索引 · 编号体系见 `D1.1` §4.0
-> **编号**:CS-DOC-2026-017 | **版本**:v1.4 | **日期**:2026-09-17 | **状态**:**现行(活文档,随文档区变动同步更新)**
+> **编号**:CS-DOC-2026-017 | **版本**:v1.5 | **日期**:2026-09-17 | **状态**:**现行(活文档,随文档区变动同步更新)**
> **性质**:本文件是 `开发文档\` 的**唯一入口**。任何人(含三个月后的自己)打开这一份,就应知道:先读什么、哪份为准、每份什么状态。
-> **盘点范围**:`开发文档\`(**50 个文件** = 49 份编号文档 + 1 份入口存根 `CLAUDE.md`,无归档子目录)+ `客服agent\`(**6 份**对外交付文档)。
+> **盘点范围**:`开发文档\`(**52 个文件** = 51 份编号文档 + 1 份入口存根 `CLAUDE.md`,无归档子目录)+ `客服agent\`(**6 份**对外交付文档)。
---
## 0. 一句话结论
-**56 份文档(55 份编号 + 1 份不占编号的入口存根 `CLAUDE.md`)已按 8 个域统一编号为 `D<域>.<序>`(规则见 §4.0,层级见 §3)。开工只读 5 份 = `D2.1` / `D2.2` / `D2.3` / `D2.4` / `D3.3`(见 §2)。**
+**58 份文档(57 份编号 + 1 份不占编号的入口存根 `CLAUDE.md`)已按 8 个域统一编号为 `D<域>.<序>`(规则见 §4.0,层级见 §3)。开工只读 5 份 = `D2.1` / `D2.2` / `D2.3` / `D2.4` / `D3.3`(见 §2)。**
| 域 | 名称 | 份数 | 定位 |
|---|---|---|---|
| **D1** | 一、治理与索引 | 6 | 先读 `D1.1`(本文件)——编号体系、权威链、开工只读集 |
| **D2** | 二、对外交付 | 6 | 🔴 **开工必读**(A1—A4;另含 `D2.5` 演示脚本、`D2.6` 答辩报告) |
-| **D3** | 三、现行权威·完整版与专项 | 7 | 查证据、查 FR 推导过程(含 A5 鉴权专项 `D3.3`;检索升级 `D3.5`;架构 `D3.6`;**评测金标 `D3.7`**) |
-| **D4** | 四、清除与重建留痕 | 6 | 追溯「删了什么、怎么恢复」;`D4.1` 即**重建指南**,`D4.6` 为验收基线留痕 |
+| **D3** | 三、现行权威·完整版与专项 | 8 | 查证据、查 FR 推导过程(含 A5 鉴权专项 `D3.3`;检索升级 `D3.5`;架构 `D3.6`;**评测金标 `D3.7`**;**密钥轮换 `D3.8`**) |
+| **D4** | 四、清除与重建留痕 | 7 | 追溯「删了什么、怎么恢复」;`D4.1` 即**重建指南**,`D4.6` 为验收基线留痕,`D4.7` 为**投顾恢复现状** |
| **D5** | 五、业务流程基线 | 1 | 两条业务线 / 三条红线 / 演示跑通验收 |
| **D6** | 六、公司事实与知识源 | 17 | 🔴 改写知识库、核对数据口径 |
| **D7** | 七、早期系统文档 | 5 | 状态待确认;仅在追查历史口径时读(**不可删**,见 §10) |
@@ -36,7 +36,7 @@
```
对外交付(客服agent\) 配套完整版 / 前身(开发文档\)
────────────────────────────────── ─────────────────────────────────────
-A1 [D2.1] D2.1-客服Agent执行Todolist.md v5.3 ←→ [D3.4] D3.4-客服Agent重构Todolist.md v5.1
+A1 [D2.1] D2.1-客服Agent执行Todolist.md v6.26 ←→ [D3.4] D3.4-客服Agent重构Todolist.md v5.1
A2 [D2.2] D2.2-客服Agent需求文档.html v2.5 ←→ [D3.1] D3.1-客服Agent需求开发文档与设计方案.html v2.4
A3 [D2.3] D2.3-客服Agent开发计划.html v1.1 ←→ (无旧版)
A4 [D2.4] D2.4-客服Agent知识库设计方案.html v1.3 ←→ [D3.2] D3.2-知识库设计方案.html v1.2
@@ -59,7 +59,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| # | 体系编号 | 文档 | 版本 | 作用 |
|---|---|---|---|---|
-| **A1** | **D2.1** | `客服agent\D2.1-客服Agent执行Todolist.md` | **v5.3** | **唯一开工入口**。**57 项 / 8 批次(A—H)** / 12 步关键路径 / 2 组会签 / **完工判据 13 条**。**新增批次 H · 智能增强**(`H-01`~`H-06`) |
+| **A1** | **D2.1** | `客服agent\D2.1-客服Agent执行Todolist.md` | **v6.26** | **唯一开工入口**。**57 项 / 8 批次(A—H)** / 12 步关键路径 / 2 组会签 / **完工判据 13 条**。**新增批次 H · 智能增强**(`H-01`~`H-06`) |
| **A2** | **D2.2** | `客服agent\D2.2-客服Agent需求文档.html` | **v2.5** | 对外需求:**FR-CS-001~052**(52 条,新增域 H)+ NFR-CS-001~021 全量、身份与鉴权模型、验收标准(**新增 AC-13 金标门禁**) |
| **A3** | **D2.3** | `客服agent\D2.3-客服Agent开发计划.html` | **v1.1** | 前置条件、测试环境就位(G-00)、会签流程、门禁、交付物、**批次 H(§3.4b)** |
| **A4** | **D2.4** | `客服agent\D2.4-客服Agent知识库设计方案.html` | **v1.3** | 三集合 / 三档可见性 / **集合内分区隔离(§7.2.1)** / 8 模块 / 7 步入库 8 步检索 / 8 项决策 / **附录F 五出口对接** |
@@ -75,7 +75,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
第 0 层 唯一入口 D1.1 D1.1-文档索引与权威声明.md
第 1 层 域(8 个) D1 ─ D8
第 2 层 子域(仅域 6 有) D6.1 ─ D6.5
-第 3 层 文档(56 份) D<域>.<序> / D<域>.<子域>.<序>
+第 3 层 文档(58 份) D<域>.<序> / D<域>.<子域>.<序>
```
### 3.2 八个域(=逻辑顺序=阅读优先级)
@@ -84,22 +84,22 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
|---|---|---|---|---|
| **D1** | 一、治理与索引 | 6 | 现行 | **先读 D1.1**(唯一入口,本文件) |
| **D2** | 二、对外交付 | 6 | 现行 | 🔴 **开工必读**(含「开工只读 5 份」的 4 份) |
-| **D3** | 三、现行权威·完整版与专项 | 7 | 现行 | 查证据、查 FR 推导过程时读 |
-| **D4** | 四、清除与重建留痕 | 6 | 已完成 | 追溯「删了什么、怎么恢复」时读(D4.1 是重建指南) |
+| **D3** | 三、现行权威·完整版与专项 | 8 | 现行 | 查证据、查 FR 推导过程时读 |
+| **D4** | 四、清除与重建留痕 | 7 | 已完成 | 追溯「删了什么、怎么恢复」时读(D4.1 是重建指南;D4.7 是投顾恢复现状) |
| **D5** | 五、业务流程基线 | 1 | 现行 | 核对业务范围与三条红线时读(**冲突时以它为准**) |
| **D6** | 六、公司事实与知识源 | 17 | 现行 | 🔴 改写知识库、核对数据口径时读 |
| **D7** | 七、早期系统文档 | 5 | **待确认** | 只在追查历史口径时读;已被上游依据表引用,**不可删**(见 §10) |
| **D8** | 八、AI 协作规则 | 8 | 现行 | 让 AI 接手时的规则文件(`D8.1`=语言规范正文;`CLAUDE.md`=入口存根,不占编号) |
-> 合计:6 + 6 + 7 + 6 + 1 + 17 + 5 + **8** = **56 份**(其中 `客服agent\` 的 6 份不计入 `开发文档\` 的 50 个文件;域 D8 的 8 份含 1 份**不占编号**的入口存根 `CLAUDE.md`)。
+> 合计:6 + 6 + 8 + 7 + 1 + 17 + 5 + **8** = **58 份**(其中 `客服agent\` 的 6 份不计入 `开发文档\` 的 52 个文件;域 D8 的 8 份含 1 份**不占编号**的入口存根 `CLAUDE.md`)。
---
## 4. 全量文档清单
-> **本节结构**:**§4.0 = 编号规则 + 全量编号总表(56 份,按编号顺序)——查找入口**;§4.1—§4.8 = 按类别展开的明细表(编号见 §4.0 总表,同一逻辑顺序)。
+> **本节结构**:**§4.0 = 编号规则 + 全量编号总表(58 份,按编号顺序)——查找入口**;§4.1—§4.8 = 按类别展开的明细表(编号见 §4.0 总表,同一逻辑顺序)。
-### 4.0 编号规则与全量编号总表(56 份)
+### 4.0 编号规则与全量编号总表(58 份)
**编号规则**
@@ -123,7 +123,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| **D1.4** | `开发文档\D1.4-知识源与品牌整改变更说明-2026-09-17.md` | CS-CONTENT-2026-016 | 现行 | 逐份变更说明(§3.1—§3.9 改写映射 + G-01~G-09) |
| **D1.5** | `开发文档\D1.5-开发前决策清单与阻塞项-2026-09-17.md` | CS-DOC-2026-018 v1.0 | 现行 | 🔴 **开工前唯一决策登记册**:28 项待你拍板 + 阻塞分级(P0 12 / P1 10 / P2 6)+ 需你提供的 7 项输入;§7 为回填表(增补项见 `D1.6` §4.3) |
| **D1.6** | `开发文档\D1.6-对话上下文提取与开工前补充决策-2026-09-17.md` | CS-DOC-2026-019 v1.0 | 现行 | 🔴 **本轮会话上下文提取件**:已读清单与权威链校正 / 可复用事实(含实测)/ 旧实现 **7 条转人工通路** / 文档缺陷 `Q-1.1`~`Q-1.6` / 前提风险 `K-01`~`K-08` / 待拍板 `N-01`~`N-09` |
-| **D2.1** | `客服agent\D2.1-客服Agent执行Todolist.md` | **v5.3** | 现行 | 🔴 **唯一开工入口**:**57 项 / 8 批次** / 12 步关键路径 / **批次 H 智能增强** |
+| **D2.1** | `客服agent\D2.1-客服Agent执行Todolist.md` | **v6.26** | 现行 | 🔴 **唯一开工入口**:**57 项 / 8 批次** / 12 步关键路径 / **批次 H 智能增强** |
| **D2.2** | `客服agent\D2.2-客服Agent需求文档.html` | **v2.5** | 现行 | 🔴 对外需求:**FR-CS-001~052** + NFR-CS-001~021 |
| **D2.3** | `客服agent\D2.3-客服Agent开发计划.html` | **v1.1** | 现行 | 🔴 前置条件 / 批次 / 会签 / 门禁 / 交付物 |
| **D2.4** | `客服agent\D2.4-客服Agent知识库设计方案.html` | **v1.3** | 现行 | 🔴 三集合 / 三档可见性 / **分区隔离** / 7 步入库 8 步检索 / **附录F** |
@@ -136,12 +136,14 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| **D3.5** | `开发文档\D3.5-知识库检索升级备选方案建议-2026-09-17.md` | CS-KB-2026-020 v1.0 | 现行 | 知识库检索升级**备选方案池**(**不是**任务来源):`K-01`~`K-08` 前提风险 / `§3-A`~`§3-H` 八个升级方向 / 与 `DEC-11` 耦合的推荐组合 / 对 `D2.4`·`D2.1` 的 10 条修订建议 / 可证伪验收判据 |
| **D3.6** | `开发文档\D3.6-客服Agent智能增强架构建议-2026-09-17.md` | CS-ARCH-2026-021 **v1.1** | 现行 | 🔴 **智能增强架构(**已裁定件**)**:诊断(10 条转人工通路 / 设计有澄清与生成但未实现)/ 「智能」7 条可验收定义 / **五出口决策链** E1—E5 / 安全不变量 `INV-1`~`INV-5` / 转人工白名单 4 类 / **§9 八项决策已拍板** |
| **D3.7** | `开发文档\D3.7-客服Agent评测金标集与判分规则-2026-09-17.md` | CS-EVAL-2026-022 v1.0 | 现行 | 🔴 **验收依据**:46 条金标(含四要素:期望出口 / 期望证据 / 期望关键事实 / 禁止出现)+ 10 项指标 + **4 项零容忍**(禁忌·越权·无出处数字·误拒)+ 前置阻塞 `B-1`~`B-4` + 问法分级(难例 32 条) |
+| **D3.8** | `开发文档\D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md` | CS-OPS-2026-023 v1.0 | 现行 | 🔴 **答辩后当轮执行**:为什么轮换 / `.env` 5 个变量与读取方取证 / **三个 Qwen 同值 + 两个 DeepSeek 同值** / 五步流程 / 3 个坑 / 复核清单(工具 `tools/rotate_api_keys.py`) |
| **D4.1** | `开发文档\D4.1-客服Agent重构报告-2026-09-16.md` | CS-REFACTOR-2026-010 | 底稿 | 🔴 **重建指南**:清除了什么 / 缺什么 / 按什么顺序装回去 |
| **D4.2** | `开发文档\D4.2-客服模块清除影响面清单.md` | CS-PURGE-2026-007 | 已完成 | 客服形态A 清除的影响面 |
| **D4.3** | `开发文档\D4.3-客服模块清除执行报告-2026-09-16.md` | CS-PURGE-2026-008 | 已完成 | 客服清除验证数据 + **安全能力损失清单**(重建须补回) |
| **D4.4** | `开发文档\D4.4-投顾模块清除范围与影响面清单-2026-09-17.md` | CS-PURGE-2026-012 | 已完成 | 投顾清除范围 |
| **D4.5** | `开发文档\D4.5-投顾模块清除执行报告-2026-09-17.md` | CS-PURGE-2026-013 | 已完成 | 投顾清除验证数据 + 恢复方式 |
| **D4.6** | `开发文档\D4.6-客服Agent一期合规红队与业务评测集-留痕-2026-09-18.md` | CS-DOC-2026-020 v1.0 | 留痕 | 🔴 **验收基线**:一期红队 `RT-001`~`018` 原文 + `C-06` 实测回填;`A-01`/`C-06`/`C-07` 的唯一对比基准 |
+| **D4.7** | `开发文档\D4.7-投顾模块恢复记录-2026-09-20.md` | CS-PURGE-2026-014 v1.0 | 现行 | 🔴 **投顾现状**:2026-09-17 清除 → 2026-09-20 随合并恢复的时间线 / 恢复动作清单 / 客服线不变的结论 / **一处必须更正的理由表述**(`DEC-19`)/ 遗留 1 项 |
| **D5.1** | `开发文档\D5.1-业务流程-MVP版-最终交付-2026-09-15.md` | — | 现行 | 🔴 MVP 业务基线:两条业务线 / 三条红线 / 演示跑通验收(**冲突时以它为准**) |
| **D6.1.1** | `开发文档\公司信息\D6.1.1-南方基金-企业信息.md` | **V2.0** | 现行 | 🔴 **母本**:品牌 / 工商 / 资质 / 组织 / 财务的唯一权威 |
| **D6.1.2** | `开发文档\公司信息\D6.1.2-南方基金-高频问答对.md` | NF-FAQ-2026-001 **V2.0** | 现行 | 64 组 FAQ(档位 public 54 / registered 10) |
@@ -174,20 +176,20 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| **D8.6** | `开发文档\ai\D8.6-04_OUTPUT_RULES.md` | — | 现行 | 产出规则(§5 高风险变更须先确认) |
| **D8.7** | `开发文档\ai\D8.7-05_PROJECT_CONTEXT.md` | — | 现行 | 项目背景速览 |
-> **注入校验**:**52 份**可注入文档(**42** `开发文档\*.md` + 5 `开发文档\*.html` + 3 `客服agent\*.html` + `客服agent\D2.5-…md` + `客服agent\D2.6-…md`)**已全部带「体系编号」行**;3 份 `.txt` 按上表例外处理。(原表述的 49 份**未计入** `客服agent\D2.1` 的 `.md` —— 该漏计是历史口径,本轮**只补新增件、不追改历史**。)「开工只读 5 份」对应 **D2.1 / D2.2 / D2.3 / D2.4 / D3.3**。
+> **注入校验**:**54 份**可注入文档(**44** `开发文档\*.md` + 5 `开发文档\*.html` + 3 `客服agent\*.html` + `客服agent\D2.5-…md` + `客服agent\D2.6-…md`)**已全部带「体系编号」行**;3 份 `.txt` 按上表例外处理。(原表述的 49 份**未计入** `客服agent\D2.1` 的 `.md` —— 该漏计是历史口径,本轮**只补新增件、不追改历史**。)「开工只读 5 份」对应 **D2.1 / D2.2 / D2.3 / D2.4 / D3.3**。
### 4.1 Ⅰ 对外交付 / 现行权威(`客服agent\`,6 份)
| 文件名 | 版本 | 日期 | 定位 | 关联 |
|---|---|---|---|---|
-| `D2.1-客服Agent执行Todolist.md` | **v5.3** | 2026-09-17 | 唯一开工入口 | 收敛自 `开发文档\D3.4-客服Agent重构Todolist.md` v5.1 |
+| `D2.1-客服Agent执行Todolist.md` | **v6.26** | 2026-09-17 | 唯一开工入口 | 收敛自 `开发文档\D3.4-客服Agent重构Todolist.md` v5.1 |
| `D2.2-客服Agent需求文档.html` | **v2.5** | 2026-09-17 | 对外需求(FR **52** / NFR 21) | 完整版见 §4.2 |
| `D2.3-客服Agent开发计划.html` | **v1.1** | 2026-09-17 | 批次 / 会签 / 门禁 | 与 A1 批次号一一对应 |
| `D2.4-客服Agent知识库设计方案.html` | **v1.3** | 2026-09-17 | 三集合 / 三档 / 入库检索流程 | 完整版见 §4.2 |
| `D2.5-客服Agent演示脚本与账号速查-2026-09-19.md` | — | 2026-09-19 | 演示脚本(`F-03`/`F-04`/`A-05` 三合一) | 台词证据:`group_fqcd_jr\docs\evidence\20260919-t8-demo-lines*.json` |
| `D2.6-客服Agent答辩报告-2026-09-19.md` | — | 2026-09-19 | 答辩报告(问题定义 / 根因 / 五出口 / 安全不变量 / 前后对比 / 现场速答) | 数字来源:46 条金标 `score_before` vs `score_w11b` + `e2e_smoke_test` + `http_probe` + 12 条真机边界 |
-### 4.2 Ⅱ 开发文档区内的现行权威(7 份)
+### 4.2 Ⅱ 开发文档区内的现行权威(8 份)
| 文件名 | 版本 | 定位 |
|---|---|---|
@@ -198,6 +200,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| `D3.5-知识库检索升级备选方案建议-2026-09-17.md` | CS-KB-2026-020 | 知识库检索升级**备选方案池**(**建议**,非需求/任务来源) |
| `D3.6-客服Agent智能增强架构建议-2026-09-17.md` | CS-ARCH-2026-021 **v1.1** | 智能增强架构(**§9 八项已拍板**):五出口决策链 / 安全不变量 / 转人工白名单 4 类 / 访客档计算型分项开放口径 |
| `D3.7-客服Agent评测金标集与判分规则-2026-09-17.md` | CS-EVAL-2026-022 | **评测输入件**:46 条金标 + 判分规则 + 门槛(**验收依据**,非需求/任务来源) |
+| `D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md` | CS-OPS-2026-023 | **操作手册**:模型密钥轮换(工具 `tools/rotate_api_keys.py`)+ 复核 + 回退;**不落任何 key 值** |
### 4.3 Ⅲ 内部复核底稿(2 份)
@@ -206,7 +209,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| `D4.1-客服Agent重构报告-2026-09-16.md` | CS-REFACTOR-2026-010 | 清除了什么 / 缺什么 / 按什么顺序装回;§9 决策记录 |
| `D5.1-业务流程-MVP版-最终交付-2026-09-15.md` | — | MVP 业务流程基线 |
-### 4.4 Ⅳ 清除执行记录与重建留痕(5 份)
+### 4.4 Ⅳ 清除执行记录与重建留痕(6 份)
| 文件名 | 编号 | 定位 |
|---|---|---|
@@ -215,6 +218,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| `D4.4-投顾模块清除范围与影响面清单-2026-09-17.md` | CS-PURGE-2026-012 | 投顾清除范围 |
| `D4.5-投顾模块清除执行报告-2026-09-17.md` | CS-PURGE-2026-013 | 投顾清除验证数据 + 恢复方式 |
| `D4.6-客服Agent一期合规红队与业务评测集-留痕-2026-09-18.md` | CS-DOC-2026-020 | 🔴 一期红队 `RT-001`~`018` 原文留痕 + `C-06` 实测回填(验收基线) |
+| `D4.7-投顾模块恢复记录-2026-09-20.md` | CS-PURGE-2026-014 | 🔴 **投顾的「现状」单据**:清除 → 恢复的时间线与动作清单;`D4.4`/`D4.5` 降级为历史留痕 |
### 4.5 Ⅴ 本次整改工作文档(5 份)
@@ -442,10 +446,10 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
| # | 事项 | 我的建议 | 影响 |
|---|---|---|---|
-| **D-5** | 前端 24 份 + 风控 Agent 5 处仍用 `南方财富`(G-02 / G-05) | 改(**评审唯一肉眼可见的品牌面**:文档再干净,打开页面仍显示「南方财富」) | 🔴 高 |
-| **D-6** 🆕 | **系统名不统一**:`开发文档\公司信息\D6.1.1-南方基金-企业信息.md`(母本)等用「**智能财富管家系统**」,而 `knowledge\` 镜像与四份交付文档用「**南方基金·智能服务系统**」。**同源两版再次打架**(约 13 处:母本 4 / 早期 HTML 8 / 开发引导 1),另有 `D6.1.4-公司新人指南.md` 4 处、`docs\` 3 处、`_flows\` 3 处 | **统一为「南方基金·智能服务系统」**(与四份交付文档、`knowledge\` 镜像一致);同时核对 `BRAND_SYSTEM_NAME` 配置位 | 🟡 中(命名不统一,且母本与镜像不一致) |
-| **D-7** 🆕 | **B-01 语料入库门禁(四查)并未实现** | 属 Todolist 批次 B 的代码工作;**实现时品牌白名单必须用 `南方基金` + `nffund.com`**(旧文档里的 `南方财富` + `nanfangwm.com` 会放行错误品牌) | 🔴 高(不改会误杀新知识源 / 或放行旧品牌) |
-| — | `_chunks.jsonl` 未重灌库;`开发文档\` 的仓库副本(`group_fqcd_jr\开发文档\`)未同步 | 属派生件与推送动作 | 中 |
+| **D-5** | 前端 24 份 + 风控 Agent 5 处曾用 `南方财富`(G-02 / G-05) | ✅ **2026-09-18 已执行**(`C-05` 品牌面清零);🔴 **2026-09-20 复查发现 2 处残留** —— 投顾组分支带回的 `employee-advisor/dashboard/index.html` 与 `customer/advisor-plans/index.html` 的 ``(`W12` 合并引入),**已于 `W13` 按 `DEC-27` 修正**;全仓 `app\` 复查 = 0 处 | ✅ 已闭环 |
+| **D-6** 🆕 | **系统名不统一**(母本曾用「智能财富管家系统」) | ✅ **2026-09-19 已执行**(`乙-25`):母本 `D6.1.1` / `D6.1.4` 与 `D6.5.x` / `D6.4.3` 已统一为「**南方基金·智能服务系统**」;本轮复查 `开发文档\公司信息|公司业务` = **0 处**。剩余命中全部为**合法语境**:① 变更说明(`D1.2`/`D1.4`/`D1.5`);② **早期文档**(`D7.1`/`D7.2`/`D7.4`)—— 按 §4.7「只标注不改品牌」裁定**有意保留**;③ 仓库 `docs\` / `_flows\`(另一套编号空间) | ✅ 已闭环 |
+| **D-7** 🆕 | **B-01 语料入库门禁(四查)并未实现** | ✅ **已实现**:`tools\knowledge_corpus_gate.py`(品牌白名单为 `南方基金` + `nffund.com`,旧值进了**黑名单**;单测 `tests\unit\tools\test_knowledge_corpus_gate.py`) | ✅ 已闭环 |
+| — | ~~`_chunks.jsonl` 未重灌库;`开发文档\` 的仓库副本未同步~~ | ✅ **均已闭环**:三集合已于 2026-09-18 `drop` 重建重灌(`DEC-29`「不用旧数据,全部用新数据」);`开发文档\`(50 份)+ `客服agent\`(24 份)已于 2026-09-20 随 `bc61d5c` **入库并与权威副本逐字节一致**(`D1.6` §4.38) | ✅ 已闭环 |
> ⚠️ **D-5 / D-7 属前端与代码改动**;本轮已按指令完成 D-2/D-3/D-4(其中 D-4 含 3 处代码改动)。
@@ -487,7 +491,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
**本轮不做删除。** 「只留协助开发的文档」这个目标由 **分类(§3)+ 状态标注(§4.7)+ 开工只读 5 份(§2)** 达成,而不是靠删文件——本区文档按「**文件名 + 编号**」互引(§9),删任何一份都会打折别人的依据链。
-若仍要物理瘦身,唯一不破坏引用的方式是**移动而非删除**(移入 `开发文档\_archive\`),但代价有三:① 路径型引用(如 §7.5 的 `开发文档\D4.5-投顾模块清除执行报告-2026-09-17.md`)失效;② `_archive\` 目录本身会被后续盘点再认作「待归档」;③ **本区不在任何 git 仓库内**,移动前必须先整包备份。
+若仍要物理瘦身,唯一不破坏引用的方式是**移动而非删除**(移入 `开发文档\_archive\`),但代价有三:① 路径型引用(如 §7.5 的 `开发文档\D4.5-投顾模块清除执行报告-2026-09-17.md`)失效;② `_archive\` 目录本身会被后续盘点再认作「待归档」;③ **本区**已于 2026-09-20 入库**(`group_fqcd_jr\开发文档\` / `group_fqcd_jr\客服agent\`,见 `D1.6` §4.38)
> 🔴 **本轮最重要的教训**:判断一份文档「有没有用」**不能凭体裁**("像通用教材"「像过程记录」),**必须按文件名反查引用**。本轮因此发现了 `D7.3-记忆架构设计.html` 被误归档(§7.1 纠正)、以及 5 份「看起来没用」的文档其实全部被上游依据表引用。
@@ -683,7 +687,7 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
|---|---|
| 新增文档 | `开发文档\D8.1-项目语言规范.md`(域 8「AI 协作规则」,**语言规范正文**:四条硬规则 + AI 入口协议 + 编号落位) |
| 改造文档 | `开发文档\CLAUDE.md` → **三行入口存根**(保留文件名以维持 AI 工具约定与既有引用锚点) |
-| 新增纪律凭据(写在仓库 `docs\`,**不占** `开发文档\` 编号) | `group_fqcd_jr\docs\46-可改文件白名单.md`(`A-09`:类 1 纯新增 / 类 2 客服业务层 / 类 3 须会签 / 类 4 禁止修改 + **零 DDL 声明** + 实际改动对照表);`group_fqcd_jr\docs\47-底座会签申请单-2026-09-19.md`(`A-10`:组 1 六文件八处 + 组 2 四文件 + 🆕 **组 3 组外扩张 2 文件(须补签)**) |
+| 新增纪律凭据(写在仓库 `docs\`,**不占** `开发文档\` 编号) | `group_fqcd_jr\docs\48-可改文件白名单.md`(`A-09`:类 1 纯新增 / 类 2 客服业务层 / 类 3 须会签 / 类 4 禁止修改 + **零 DDL 声明** + 实际改动对照表);`group_fqcd_jr\docs\49-底座会签申请单-2026-09-19.md`(`A-10`:组 1 六文件八处 + 组 2 四文件 + 🆕 **组 3 组外扩张 2 文件(须补签)**) |
| 计数同步 | §0 结论 54 → **55**;§0 盘点范围 49 → **50 个文件**;§0 域表与 §3.2 表 D8 **7 → 8**;§3.1 第 3 层 54 → **55**;「合计」行改 `… + 8 = 55`;§4.0 标题 / 说明 54 → **55**;§4.0 总表 `D8.1` 行改指新文件并**新增存根行**;§4.0 尾「注入校验」**50 → 51**(`开发文档\*.md` 41 → **42**) |
| 交叉引用 | `D1.6` 新增 §4.34(`W9`)/ §4.35(`W10`);`D2.1` 标题 **v6.20 → v6.22**(补 v6.21 / v6.22 两段) |
| **未做(诚实声明)** | ① 未改 `D7.1` / `D7.2` 的品牌,沿用 §4.7「只标注不改品牌」的既有裁定;② 未追改 §11.2 的历史计数(第八轮史实,不追溯);③ `CLAUDE.md` **未删除**(文件名被 A2/A4 与 `ai\D8.3` 引用);④ `docs\46` / `docs\47` **未计入**本节 55 份(它们是仓库 `docs\` 编号空间,与 `开发文档\` 编号体系两套) |
@@ -708,6 +712,40 @@ A5 [D3.3] 访客与角色分离的鉴权方案建议(仅此一份,无新旧
---
+## 22. 第十八轮:`W12` 合并与权威文档入库(2026-09-20)
+
+> **本轮做什么**:把投顾组 3 个远端提交并入 `qyqy_develop`(**「投顾整体清除」被取代**),并把权威文档目录**入库**。代码与门禁见 `D1.6` §4.37—§4.38。
+
+| 项 | 本轮落地 |
+|---|---|
+| 合并 | `e5b4d02`(parents = `5d0becb` + `74b7d00`):14 文件重叠 / 12 处冲突;**未用 `--force`** |
+| 🔴 **结论被取代** | `D4.4`/`D4.5` 的「投顾整体清除」**不再成立**(组员新功能反向依赖被删模块)⇒ `D4.5` 顶部加**状态更新**;`D4.4` 的范围清单**仍是有效的历史留痕** |
+| 新增文档 | 本轮**无**新编号文档(`D4.7` 为下一轮补记) |
+| 文档入库 | 仓库 `客服agent\` 21→**24** 文件、`开发文档\` 40→**50** 文件;**权威覆盖过期**,入库后逐文件零差异 |
+| 计数影响 | `W12` 当轮**未改本文件计数**(56 份不变)—— 本轮只做「替换过期副本」,未新增体系编号 |
+| ⚠️ 顺带登记 | `docs\46` / `docs\47` 编号撞车(我方与投顾组**同号**),当时未登记;**下一轮修正**(见 §23) |
+
+---
+
+## 23. 第十九轮:`W13` 密钥轮换工具 + 两份目录审计与口径校准(2026-09-20)
+
+> **本轮做什么**:新增模型密钥轮换工具与操作手册;对 `客服agent\` + `开发文档\` 做一次**逐份审计**,修掉 12 处事实漂移与 1 处门禁失败。会话留痕见 `D1.6` §4.39。
+
+| 项 | 本轮落地 |
+|---|---|
+| 新增文档 | `开发文档\D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md`(域 3 续号,**CS-OPS-2026-023**);`开发文档\D4.7-投顾模块恢复记录-2026-09-20.md`(域 4 续号,**CS-PURGE-2026-014**) |
+| 为什么单独成文(`D3.8`) | 工具 `tools/rotate_api_keys.py` 已在,但**没有任何文档说明它为什么存在、怎么复核、怎么回退**;`D2.6` §10-4 当时只指向 `D1.6` 的一个自然段。密钥轮换是**答辩后当轮就要执行**的动作,必须有可独立执行的 SOP |
+| 为什么单独成文(`D4.7`) | `D4.4`/`D4.5` 两份文档标题都叫「**清除**」,未来检索「投顾 恢复」**查不到**;而「你删了投顾又恢复了?」是答辩**必被追问**的一点。需要一个描述**仓库现状**的单据 |
+| 计数同步 | §0 结论 56 → **58**;§0 域表 D3 7 → **8**、D4 6 → **7**;§0 盘点范围 `开发文档\` 50 → **52 个文件**;§3.1 第 3 层 56 → **58**;§3.2 域表与「合计」行 → `6 + 6 + 8 + 7 + 1 + 17 + 5 + 8 = **58 份**`;§4.0 标题与说明 56 → **58**;§4.0 总表新增 `D3.8` / `D4.7` 两行;§4.2 标题(7 → **8 份**)与 §4.4 标题(5 → **6 份**)各新增一行;§4.0 尾「注入校验」52 → **54 份**(`开发文档\*.md` 42 → **44**) |
+| 🔴 **修正一处长期错误** | §4.0 总表与 §4.1 明细把 `D2.1` 的版本记为 **v5.3**(第十一轮口径),而 `D2.1` 早已到 **v6.26**;§1 权威链与 §2「开工只读 5 份」表也同步更正 |
+| 🔴 **修正一处门禁失败** | `tools/check_authoritative_docs.py`(`D3.4` `N-14` 登记的门禁)因 `docs\46`/`docs\47` **编号撞车实测 FAIL**。按「**后到者让位**」(组员 2026-09-16 建、我方 2026-09-20 建)把我方两份改名为 `docs\48-可改文件白名单.md` / `docs\49-底座会签申请单-2026-09-19.md`,并同步 **8 处引用** |
+| §8 遗留项闭合 | `D-5`(前端品牌面)、`D-6`(系统名统一)、`D-7`(语料入库门禁)、以及「`_chunks.jsonl` 未重灌库 / 仓库副本未同步」**四行**逐项标注为**已闭环**,并如实登记 `D-5` 的 **2 处真实残留**(`W12` 合并引入,本轮修正) |
+| §10.2 表述更正 | 「本区不在任何 git 仓库内」→ **已于 2026-09-20 入库** |
+| 外部文档同步 | `客服agent\`:`D2.1` → **v6.26**(新增 v6.26 段);`D2.2`/`D2.3`/`D2.4` 三份 HTML 加**投顾口径状态更新**并修正过期徽标;`D2.5` 修正 `advisor_t` 口径 + 切入一键脚本;`D2.6` 更新门禁数字并闭环两项「未做项」 |
+| ⚠️ **未做(诚实声明)** | ① 未追改 §11.2 的历史计数(第八轮史实,不追溯);② `docs\` 仍是另一套编号空间,**不并入本节 58 份**;③ 未改 `D7.1`/`D7.2` 的品牌(§4.7 既定裁定);④ 投顾 `config_release` 工具白名单(`advisor:*`)**仍未发布** —— 与客服线无关,见 `D4.7` §5 |
+
+---
+
> **维护责任**:本文件为活文档。**新增 / 改名 / 归档 / 改版本号后,须同步更新本文件 §3 与 §4.0 总表对应行**。
>
> 编制:项目文档组 | 审核:合规稽核部 | 日期:2026-09-17
diff --git a/开发文档/D1.6-对话上下文提取与开工前补充决策-2026-09-17.md b/开发文档/D1.6-对话上下文提取与开工前补充决策-2026-09-17.md
index 2f3aba8..b5ef1ed 100644
--- a/开发文档/D1.6-对话上下文提取与开工前补充决策-2026-09-17.md
+++ b/开发文档/D1.6-对话上下文提取与开工前补充决策-2026-09-17.md
@@ -2391,7 +2391,7 @@ pytest **2 failed / 1577 passed / 2 skipped**(= `T0` 基线同两项)、ruff
| 6 | **`F-07` 目录锚点** | 8 份交付 HTML | ✅ **实测失效锚点 = 0**(`D7.1` 63 个 `href` / 24 个目录锚点全部命中)⇒ **零工作量,非「未做」** |
| 7 | **`E-08` 三条红线对照** | `tests\unit\service\test_customer_service_red_lines.py` | ✅ **11 passed**,逐条映射:红线 1(风险等级唯一来源)5 例 / 红线 2(先揭示后确认)2 例 / 红线 3(不生成交易指令)4 例。**未发现缺口 ⇒ 无新增拦截代码**(对照验证 + 留痕结项) |
| 8 | **`H-05` 档位分区隔离收口**(由「未通过」改判达标) | `tools\setup_milvus_knowledge_collections.py`、`tools\load_knowledge_milvus.py`、`app\service\knowledge_search_service.py` | ✅ ① 四集合 `visibility` 均 `is_partition_key=true` / `max_length=16` / `num_partitions=16`;② **fail-closed 实测**:写入缺 `visibility` 的行被拒(`Insert missed an field 'visibility' …`);③ **双向实测**:同一 `registered` 档内容访客看不到、客户 top1 = 0.8717;④ `over-fetch` 全仓零命中;⑤ **双 schema 收敛**:`build_schema` 全仓**仅 1 处**定义,灌库脚本**反向 import 复用** |
-| 9 | **`A-09` / `A-10` 落档** | 新增 `group_fqcd_jr\docs\46-可改文件白名单.md`、`docs\47-底座会签申请单-2026-09-19.md` | ✅ 四类白名单 + **零 DDL 声明**(89 张业务表 / 无 `alembic` 改动 / 新增字段全部复用既有列)+ 相对 `HEAD` 的**实际改动对照表**;会签单按 `D2.1` 附录B 模板逐项写 |
+| 9 | **`A-09` / `A-10` 落档** | 新增 `group_fqcd_jr\docs\48-可改文件白名单.md`、`docs\49-底座会签申请单-2026-09-19.md` | ✅ 四类白名单 + **零 DDL 声明**(89 张业务表 / 无 `alembic` 改动 / 新增字段全部复用既有列)+ 相对 `HEAD` 的**实际改动对照表**;会签单按 `D2.1` 附录B 模板逐项写 |
| 10 | **全量回归**(停常驻 Worker 后跑,跑完重新拉起) | 见下表 | ✅ 全部通过 |
**二、全量回归实测(`W10`)**
@@ -2482,7 +2482,7 @@ pytest **2 failed / 1577 passed / 2 skipped**(= `T0` 基线同两项)、ruff
| 4 | **四处一次性收紧 + 8 条路径参数补约束** | 同上两文件 + `app\api\controllers\public_platform.py`、`agent_runs.py`、`conversations.py` | ✅ 只**收紧**(不可能让既有合法调用变红):`message ≤ 8000`、`session_id 1—64`、`idempotency_key 16—64`、`feedback_type ≤ 32`;路径参数 `{session_id}`/`{run_id}`/`{handover_id}` 补 `min_length=1, max_length=64, pattern=r"^[A-Za-z0-9_-]+$"`(沿用 `admin.py`/`risk.py` 既有写法) |
| 5 | **新增前端边界守卫测试** | 新增 `tests\unit\api\test_frontend_boundaries.py`(**33 例**) | ✅ 口径一致(前端 `maxlength` == 后端 `max_length`)、入参上限 ≤ 落库列宽、超限必须 `422` 信封、路径参数 OpenAPI 契约、缺权限 `403` / 未登录 `401`、**端点表 ↔ OpenAPI 全量对照**、`HEALTH` 探针路径必须真实存在 |
| 6 | **12 条真机边界复验** | `_fe_boundary_http.py`(脚本一次性) | ✅ **12/12 符合预期**,见下表「三」 |
-| 7 | **纪律凭据同步** | `group_fqcd_jr\docs\46-可改文件白名单.md`、`docs\47-底座会签申请单-2026-09-19.md` | ✅ `knowledge_tier.py` 登记进 `A-09` 类 1 与 `A-10` §3(第 12 项);**新增 `A-10` §4「前端入参边界对齐」组(5 文件,须补签)**,`A-09` 同步登记 |
+| 7 | **纪律凭据同步** | `group_fqcd_jr\docs\48-可改文件白名单.md`、`docs\49-底座会签申请单-2026-09-19.md` | ✅ `knowledge_tier.py` 登记进 `A-09` 类 1 与 `A-10` §3(第 12 项);**新增 `A-10` §4「前端入参边界对齐」组(5 文件,须补签)**,`A-09` 同步登记 |
| 8 | **答辩报告成文** | 新增 `客服agent\D2.6-客服Agent答辩报告-2026-09-19.md` | ✅ 12 节:问题定义 → 根因 → 五出口 → 安全不变量 → **金标前后对比** → 零容忍词挂载点口径 → 演示口径 → 工程纪律 → **坑与教训(含我 3 处判断更正)** → 诚实未做项 → 现场速答 → 一页速览 |
| 9 | **全量回归**(停常驻 Worker 后跑,跑完重新拉起) | 见下表「二」 | ✅ 全部通过;`pytest` 由 1810 → **1856 passed** |
| 10 | **临时脚本清零** | `D:\桌面\金融\_*.py` | ✅ 本轮新建的扫描 / 修补 / 校验脚本全部删除(保留件清单见「五」) |
@@ -2684,6 +2684,51 @@ pytest **2 failed / 1577 passed / 2 skipped**(= `T0` 基线同两项)、ruff
---
+### 4.39 2026-09-20 第三十五轮会话记录(`W13`:密钥轮换工具 + 两份文档目录审计 —— 修掉 12 处事实漂移与 1 处门禁失败)
+
+> **本轮指令(原文)**:「现在就带你走一遍,然后你再检查一遍我这两个文件夹里的文档 看看还有什么需要完善和补充的 我需要你仔细的去推理以及补充」
+
+**一、密钥轮换:把「必须人工、易错」的操作收敛成一个脚本**
+
+| 项 | 内容 |
+|---|---|
+| 新增工具 | `group_fqcd_jr\tools\rotate_api_keys.py`(6899 → 6877 字节):`--check` 体检 + 交互式轮换 |
+| 设计要点 | ① `getpass` **不回显**;② 自动备份 `.env.bak-<时间戳>`(被 `.gitignore` 命中);③ **三个 Qwen 变量写同一值**、**两个 DeepSeek 变量写同一值**(这是手改最容易漏的一步);④ 校验不通过则**整体不写入**;⑤ 只替换目标行,其余行原样保留(**保编码、保换行**);⑥ 不落日志、不落文档 |
+| `--check` 实测 | Qwen 三变量 **✅ 同值且非空**(115 位);DeepSeek 两变量 **✅ 同值且非空**(35 位) |
+| 🔴 **边写边修(如实登记,两处硬伤)** | ① 第 75 行提示语把 ASCII 双引号当成了中文引号(`"入库/检索"`),直接 **`SyntaxError`**,`ruff` 也拦下 —— 这是我在写之前**自己预判过、又差点放过**的坑,实测第一时间暴露;② 文档字符串里 22 处「反斜杠 + 反引号」触发 `SyntaxWarning: invalid escape sequence`。均已修正,`ruff check` + `ruff format` 通过 |
+| 口径确认 | `model_endpoint_config.secret_ref` 存的是**变量名**(`env:QWEN_API_KEY` / `env:DEEPSEEK_API_KEY`)⇒ **轮换只改 `.env`,不动 DB**;但**必须重启 API + Worker** |
+| 新增手册 | `开发文档\D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md`(5 步 / 3 个坑 / 复核清单 / 回退 / 能力边界) |
+
+**二、文档审计:逐份推理「还缺什么」,修掉 12 处漂移 + 1 处门禁失败**
+
+| # | 发现(按严重度) | 处置 |
+|---|---|---|
+| 1 | 🔴 **门禁实测 FAIL**:`tools/check_authoritative_docs.py`(`D3.4` `N-14` 登记的验收命令集之一)报 `docs 编号撞车:{'46': [...], '47': [...]}` —— 我方 `docs\46`/`docs\47`(2026-09-20 建,`5d0becb`)与投顾组 `docs\46-投顾Agent需求文档.md` / `docs\47-投顾Agent功能架构文档.md`(2026-09-16 建,`5607751`)**同号** | 按「**后到者让位**」(我方后到)`git mv` 我方两份 → `docs\48-可改文件白名单.md` / `docs\49-底座会签申请单-2026-09-19.md`;同步 **8 处引用**(`D1.1` 2 + `D1.6` 4 + `D2.1` 2 处所在的 4 个文件,含仓库内自引用 1 处) |
+| 2 | 🔴 **前端品牌残留 2 处**:`app\static\portal\employee-advisor\dashboard\index.html`、`app\static\portal\customer\advisor-plans\index.html` 的 `` 仍是 **`南方财富`** | 按 `DEC-27`(已批「改,并升 P1」)改为 **`南方基金`**;全仓 `app\` 复查 `南方财富` = **0**。根因:`W12` 合并取远端时把投顾组分支的旧品牌一起带了回来(**D-5 的「已清零」被合并静默回退**) |
+| 3 | 🔴 **`D1.1` 版本号严重过期**:§4.0 总表与 §4.1 明细把 `D2.1` 记为 **v5.3**(第十一轮口径),实际已 **v6.25**;§1 权威链、§2「开工只读 5 份」表同样是 v5.3 | 全部更正为 **v6.26**(含本轮 `D2.1` 升版) |
+| 4 | 🔴 **三份 HTML 交付文档口径与事实相反**:`D2.2`/`D2.3`/`D2.4` 仍写「**投顾已清除**」,而 `W12` 已恢复 | 三份均加「**2026-09-20 状态更新**」;**关键区分**:投顾模块恢复 **≠** 客服可承接投顾能力 ⇒ `D2.2` §1.7 范围与 `RK-10` 裁定**原样不变** |
+| 5 | 🔴 **`D2.2` 自相矛盾**:顶栏徽标写 `v2.4`、文档元数据写 `v2.5`;`D2.3` 徽标写 `v1.0 · 7 批次 51 项`(实际 v1.1 / 8 批次 / 57 项) | 徽标更正为 `v2.5 · 双主体 · 五出口 · 投顾已恢复` / `v1.1 · 8 批次 57 项 · 12 步关键路径` |
+| 6 | 🟡 **`D2.5` §2.1 内部矛盾**:同一段先写「**不要念** `advisor_t`,该账号在库里**不存在**」,紧接着写「该账号已于 2026-09-20 重建 ⇒ 重新有效」 | 改写为**账号表里的一行**(`advisor_t` / `abc12345`,可用)+ 一段口径更正;并登记「投顾 `advisor:*` 工具白名单**未发布**」这一事实 |
+| 7 | 🟡 **`D2.6` 门禁数字落后一轮**:仍写 1856 passed / 2 skipped、`ruff` 19 | 更新为 **1909 / 3 skipped**、`ruff` **20**(远端分支本身 22 / 客服线基线 19 ⇒ 未引入新债),并补 `portal_api_check` 40 项一行 |
+| 8 | 🟡 **`D2.6` §10 把两个「已闭环」的项目仍列在「未做项」** | ① 密钥轮换 → 改为「**已就绪:跑一个脚本**」(指向 `D3.8`);② `A-10` 组 3/4 签字 → 改为「**2026-09-20 已补签受理**,本项已闭环」 |
+| 9 | 🟡 **`D1.1` §8「遗留与待决」四行过期**:`D-5`(前端品牌面已执行,但本轮发现 2 处合并回退)、`D-6`(系统名已统一)、`D-7`(语料门禁已实现)、「`_chunks.jsonl` 未重灌 / 仓库副本未同步」(均已闭环) | 逐行标注**已闭环**并保留证据;`D-5` 如实登记**2 处真实残留** |
+| 10 | 🟡 **`D1.1` §10.2 表述过期** | 「本区不在任何 git 仓库内」→ **已于 2026-09-20 入库**(`W12`),并保留「移动/改名仍须先整包备份」的理由 |
+| 11 | 🟢 **缺一份「投顾现状」单据**:`D4.4`/`D4.5` 标题都叫「清除」,检索「投顾 恢复」查不到 | 新增 `开发文档\D4.7-投顾模块恢复记录-2026-09-20.md`(时间线 / 恢复动作 8 项 / 客服线不变的结论 / **一处必须更正的理由表述** / 遗留 / 我的失误) |
+| 12 | 🟢 **`_consistency.py` §三 口径会误报**:原文假设「投顾命中必须出现在『已清除』语境」,恢复后合法叙述会被标「疑似仍在依赖」 | 改为「**投顾状态口径检查**」,合法语境扩为 **清除史 / 恢复史 / 不属本 Agent 范围**,并在表头写明判读规则 |
+| 13 | 📌 **一处未做(如实登记)** | 投顾 `config_release` 工具白名单(`advisor:*`)**当前未发布**(连库实测 `active_agent_tools` = `customer_service:*` 4 项 + `risk:*` 4 项,共 8 项,**无 advisor**)⇒ 投顾 Agent 工具调用 fail closed。**与客服线无关**;要演投顾线先跑 `tools/publish_advisor_demo_config.py --apply`(组员提交 `9c6f839` 提供的脚本) |
+
+**三、计数同步(`D1.1` 的强制义务)**
+
+`开发文档\` 50 → **52 个文件**;总份数 56 → **58**(57 编号 + 1 存根);§4.0 总表 / §4.2 / §4.4 / §3.1 / §3.2 / §0 全部同步;「注入校验」52 → **54 份**。**新增两个编号**:`D3.8`(域 3 续号)、`D4.7`(域 4 续号)。
+
+**四、仍待你决定的(1 项)**
+
+| # | 事项 | 我的最优建议 |
+|---|---|---|
+| 1 | **两把 key 轮换的时点**(控制台建新 key 这一步我无法代做) | **演示后当轮立刻做**:按 `D3.8` 第 1→5 步走;演示前做要额外付一个「重启 + 复核 11/11」的窗口(约 5 分钟),若你希望演示前就换掉,也完全可以 —— 脚本会先体检、再写入、再备份,**失败整体不落盘** |
+
+---
+
## 5. 建议的开工顺序(在 `DEC-11` 拍板后)
```
diff --git a/开发文档/D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md b/开发文档/D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md
new file mode 100644
index 0000000..b37fc09
--- /dev/null
+++ b/开发文档/D3.8-模型密钥轮换与凭据安全操作手册-2026-09-20.md
@@ -0,0 +1,170 @@
+# D3.8 · 模型密钥轮换与凭据安全操作手册
+
+> **体系编号**:`D3.8` · 域:三、现行权威·完整版与专项 · 编号体系见 `D1.1` §4.0
+
+> **编号**:CS-OPS-2026-023 | **版本**:v1.0 | **日期**:2026-09-20 | **状态**:**现行(操作手册,答辩后当轮执行)**
+> **性质**:**操作手册(SOP)** —— 回答「两把模型密钥已经在会话/文档里出现过明文,怎么安全地换掉、怎么证明换对了」。
+> **配套**:工具 `group_fqcd_jr\tools\rotate_api_keys.py`(**本手册的唯一执行入口**);演示脚本 `D2.5`;答辩报告 `D2.6` §10 第 4 项;会话留痕 `D1.6` §4.35 第五节第 2 项与 §4.39。
+> **🔴 铁律**:**任何文档、任何提交、任何截图都不落 key 值**(含掩码全量、含片段)。本手册只写**变量名**与**校验方法**。
+
+---
+
+## 0. 一句话结论
+
+**控制台建新 key(人工,不可自动化)→ 跑一个脚本改 `.env` → 重启 API + Worker → 复核 → 再吊销旧 key。**
+核心风险不是「会不会改错一个变量」,而是**同一个 key 在 `.env` 里有多个变量名**:漏改一个,就会出现「入库成功但检索失败」这类**没有任何报错**的症状。
+
+---
+
+## 1. 为什么要轮换(触发条件)
+
+| # | 事实 |
+|---|---|
+| 1 | 本项目的两把模型密钥(DashScope/Qwen 一把、DeepSeek 一把)**在对话过程中出现过明文**(用户于 2026-09-18 直接粘贴在会话里) |
+| 2 | 会话记录(`D1.6` 等)与全部文档**从未写入 key 值**(`W12` 入库前已做过全仓密钥扫描:真实密钥只出现在被 `.gitignore` 命中的 `.env`) |
+| 3 | 但「明文已在会话里出现过」本身就是凭据泄露事件 ⇒ **按泄露处置:轮换 + 吊销旧 key** |
+
+> **轮换不等于改一行**:改完之后系统必须**仍然能工作**,这要用第 4 步的复核来证明,而不是靠「密码改成功了」的直觉。
+
+---
+
+## 2. 轮换前的现状(2026-09-20 实测,只写变量名与长度)
+
+### 2.1 `.env` 里的 5 个变量(`group_fqcd_jr\.env`,已被 `.gitignore` 命中,**不入库**)
+
+| 变量名 | 实测长度 | 谁在读它(代码取证) |
+|---|---|---|
+| `QWEN_API_KEY` | 115 | 🔴 **`model_endpoint_config.id=1` 的 `secret_ref` = `env:QWEN_API_KEY`**(检索侧向量化);`tools\load_knowledge_milvus.py:50`(灌库侧) |
+| `QWEN_EMBEDDING_API_KEY` | 115 | `tools\configure_embedding_endpoint.py:92`(**仅在端点不存在时**用于创建端点) |
+| `DASHSCOPE_API_KEY` | 115 | `app\service\promotion_image_service.py:28`(推广素材配图,缺则**降级**不报错) |
+| `DEEPSEEK_API_KEY` | 35 | 🔴 **`model_endpoint_config.id=2` 的 `secret_ref` = `env:DEEPSEEK_API_KEY`**(生成/判定);`app\service\advisor_reason_service.py:145` |
+| `OFFSITE_DEEPSEEK_API_KEY` | 35 | `app\service\offsite_document_recognition_adapter.py:610`(场外文档识别) |
+
+> 📌 脚本侧另有一个变量名 `DEEPSEEK_API_KEY_NL2SQL`(`nl2sql_yc.py:156` 优先取它、缺省回退 `DEEPSEEK_API_KEY`)。当前 `.env` **未定义**该变量 ⇒ 走回退,**无需处理**。
+
+### 2.2 数据库侧:`secret_ref` 存的是**变量名**,不是值
+
+| id | endpoint_code | provider | model_name | secret_ref | status |
+|---|---|---|---|---|---|
+| 1 | `knowledge-embedding-qwen-v3` | qwen | `text-embedding-v3` | `env:QWEN_API_KEY` | active |
+| 2 | `deepseek-flash` | deepseek | `deepseek-chat` | `env:DEEPSEEK_API_KEY` | active |
+
+⇒ **轮换只改 `.env`,不需要动 DB**。(`EnvironmentSecretResolver` 在**运行时**按名字去环境变量取值。)
+
+### 2.3 键值分组(**这就是脚本存在的理由**)
+
+| 组 | 变量 | 必须满足 |
+|---|---|---|
+| **Qwen(DashScope)** | `QWEN_API_KEY` / `QWEN_EMBEDDING_API_KEY` / `DASHSCOPE_API_KEY` | **三个 = 同一个值**(同源同一把千问 key) |
+| **DeepSeek** | `DEEPSEEK_API_KEY` / `OFFSITE_DEEPSEEK_API_KEY` | **两个 = 同一个值**(场外识别复用同一把) |
+
+---
+
+## 3. 五步流程
+
+### 第 1 步 · 控制台建新 key(人工,不可自动化)
+
+| 服务 | 入口 | 建什么 |
+|---|---|---|
+| 阿里云 DashScope(百炼) | 控制台 → API-KEY 管理 | **新建**一把 Qwen key(形如 `sk-…`,实测长度 115) |
+| DeepSeek 开放平台 | 控制台 → API keys | **新建**一把 DeepSeek key(形如 `sk-…`,实测长度 35) |
+
+⚠️ **先不要吊销旧 key** —— 旧的留作回退,直到第 4 步复核通过。
+
+### 第 2 步 · 体检(不改任何文件,先看现状)
+
+```powershell
+cd D:\桌面\金融\group_fqcd_jr
+$env:PYTHONPATH='D:\桌面\金融\group_fqcd_jr'
+& '.\.venv\Scripts\python.exe' tools\rotate_api_keys.py --check
+```
+
+**期望输出**(2026-09-20 实测即为此):
+
+```
+· Qwen(DashScope):
+ QWEN_API_KEY sk-ws-…(115 位)
+ QWEN_EMBEDDING_API_KEY sk-ws-…(115 位)
+ DASHSCOPE_API_KEY sk-ws-…(115 位)
+ ✅ 同值且非空
+· DeepSeek:
+ DEEPSEEK_API_KEY sk-e35…(35 位)
+ OFFSITE_DEEPSEEK_API_KEY sk-e35…(35 位)
+ ✅ 同值且非空
+```
+
+出现 `❌ 有变量为空` 或 `❌ 取值不一致` 时**先别轮换**,先查清为什么(不一致本身就是缺陷)。
+
+### 第 3 步 · 轮换(交互式,输入不回显)
+
+```powershell
+& '.\.venv\Scripts\python.exe' tools\rotate_api_keys.py
+```
+
+脚本会:① 提示输入新的 Qwen key(`getpass`,**不回显**);② 提示输入新的 DeepSeek key;③ 校验格式(`sk-` 前缀 + 长度下限),**不通过则整体不写入**;④ 备份 `.env.bak-<时间戳>`(已被 `.gitignore` 命中);⑤ 把**三个 Qwen 变量写成同一个值、两个 DeepSeek 变量写成同一个值**;⑥ 只替换目标行,其余行(含注释、缩进、顺序)**原样保留**。
+
+### 第 4 步 · 重启 + 复核(**不做这步等于没换**)
+
+```powershell
+# 1) 先停 API 与 Worker(进程里还是旧 key)
+Get-CimInstance Win32_Process -Filter "Name like '%python%'" | Where-Object { $_.CommandLine -match 'uvicorn app.main:app|app.worker' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
+# 2) 再起(日志见 _http_api.log / _http_worker.log)
+Start-Process -FilePath 'D:\桌面\金融\group_fqcd_jr\.venv\Scripts\python.exe' -ArgumentList '-m','uvicorn','app.main:app','--host','127.0.0.1','--port','8000','--log-level','warning' -WorkingDirectory 'D:\桌面\金融\group_fqcd_jr' -WindowStyle Hidden
+Start-Process -FilePath 'D:\桌面\金融\group_fqcd_jr\.venv\Scripts\python.exe' -ArgumentList '-m','app.worker' -WorkingDirectory 'D:\桌面\金融\group_fqcd_jr' -WindowStyle Hidden
+```
+
+| # | 复核项 | 命令 / 判据 |
+|---|---|---|
+| 1 | 服务就绪 | `GET /internal/health/ready` → `{"status":"ready", ...}` |
+| 2 | 全链路探针 | `_eval_harness\http_probe.py` → **11/11 succeeded**(含访客线 + 客户线 + 反诈/账户/代办/画像/费率/多轮) |
+| 3 | 一键自检 | `demo.ps1 -SkipStart -NoBrowser` → **五项自检全过**(其中第 2 项「向量库三集合可查」即检索侧向量化的**真实证明**) |
+| 4 | 行情链路 | `tools\sync_market_prices.py` → 跑通(另证明外部 HTTP 出口正常) |
+| 5 | 检索侧单独验(可选) | 发一句知识型问句(如「七日年化是什么意思」)必须走 `E3` 正常作答;**若变成「答不上来」或转人工,就是 key 没配对** |
+
+### 第 5 步 · 吊销旧 key(**只在第 4 步全过之后**)
+
+回到两个控制台,把**旧 key 删除/禁用**。删除后建议再跑一次第 4 步的第 2 项(证明系统确实已不再依赖旧 key)。
+
+---
+
+## 4. 三个必须知道的坑
+
+| # | 坑 | 症状 | 为什么 |
+|---|---|---|---|
+| 1 | **只改了 `QWEN_API_KEY`,漏改另两个** | 「入库成功 / 检索失败」,或旧 key 吊销后才炸 | 三个变量来自**同一把 key 的三个变量名**,被三处不同代码读取(§2.1) |
+| 2 | **只改了 `DEEPSEEK_API_KEY`,漏改 `OFFSITE_DEEPSEEK_API_KEY`** | 主链路正常,**场外文档识别**静默降级 | 场外适配器读的是另一个变量名(§2.1) |
+| 3 | **手改 `.env` 时带了 BOM / 改了编码 / 改了换行** | **第一个变量读不出来**(后面的都正常)⇒ 症状诡异、难查 | `.env` 是纯文本按行解析;脚本改写时**保留原编码与原换行**,就是为了防这一条 |
+
+> 📌 补充坑:**改完不重启**。`UVicorn` / `Worker` 进程内的环境变量是**启动时**读入的,`.env` 改了但进程没重启 ⇒ 仍然用旧 key。
+
+---
+
+## 5. 回退方式
+
+| 场景 | 怎么做 |
+|---|---|
+| 第 3 步写入后想撤回 | 用同目录的 `.env.bak-<时间戳>` **原样覆盖回去**,然后重启 API + Worker |
+| 新 key 在控制台建错了 / 想作废 | 在控制台禁用新 key,再用备份回退 |
+| 旧 key 已吊销、新 key 又不能用 | 只能回控制台再建一把 —— 所以**第 5 步必须排在第 4 步之后** |
+
+---
+
+## 6. 与其它文档的关系(避免两处口径漂移)
+
+| 文档 | 关系 |
+|---|---|
+| `D2.6` §10 第 4 项「两把 API key 轮换」 | 本手册是它的**执行细则**;该项状态已从「手工 4 步」改为「跑一个脚本(`D3.8`)」 |
+| `D2.5` §1 五项自检 | 第 4 步复核复用其中的「向量库三集合可查」 |
+| `D1.6` §4.39 | 本轮(`W13`)新增工具与本手册的会话留痕 |
+| `group_fqcd_jr\docs\26-JWT密钥管理与轮换.md` | 讲的是 **JWT 签名密钥**,与本手册的**模型 API key** 是两回事(前者是自签自验,后者是外部服务凭据) |
+
+---
+
+## 7. 如实声明(本手册的能力边界)
+
+| 项 | 说明 |
+|---|---|
+| **不能自动化第 1 步 / 第 5 步** | 控制台建 key 与吊销 key **必须由你本人在浏览器操作**(无 API 授权、也不应为此开授权) |
+| **本手册不记录任何 key 值** | 连掩码全量都不落 —— 掩码+长度对穷举无用,但**片段会缩小搜索空间**,故一并省略 |
+| **`--check` 只能证明「一致且非空」** | 它**不联网验证 key 是否有效**;key 是否可用由第 4 步的**真实链路**证明 |
+| **未覆盖** | 阿里云/DeepSeek 控制台的**子账号与权限模型**(本手册只处理主账号 key 轮换);密钥托管系统(KMS/Vault)接入 —— 当前项目用 `.env`,未上密钥托管 |
diff --git a/开发文档/D4.5-投顾模块清除执行报告-2026-09-17.md b/开发文档/D4.5-投顾模块清除执行报告-2026-09-17.md
index 335b14f..c898342 100644
--- a/开发文档/D4.5-投顾模块清除执行报告-2026-09-17.md
+++ b/开发文档/D4.5-投顾模块清除执行报告-2026-09-17.md
@@ -24,6 +24,9 @@
> + `tools/create_test_user.py --id 9020 --username advisor_t`(重建演示账号)。
> **`D4.4` 的范围与影响面清单仍是有效的历史留痕**(尤其 §0-②③ 对"清投顾会拆掉 MVP 硬阻断"的预警,
> 正是本次裁定的依据)。
+>
+> 📌 **想看「投顾现在的状态」请读 `D4.7-投顾模块恢复记录-2026-09-20.md`** —— 本件(`D4.5`)描述的是
+> 2026-09-17 当时的清除动作,**不再是仓库现状**;`D4.7` 是「现状」单据(时间线 / 恢复动作 / 客服线不变的结论 / 遗留)。
---
diff --git a/开发文档/D4.7-投顾模块恢复记录-2026-09-20.md b/开发文档/D4.7-投顾模块恢复记录-2026-09-20.md
new file mode 100644
index 0000000..055b23d
--- /dev/null
+++ b/开发文档/D4.7-投顾模块恢复记录-2026-09-20.md
@@ -0,0 +1,96 @@
+# D4.7 · 投顾模块恢复记录
+
+> **体系编号**:`D4.7` · 域:四、清除与重建留痕 · 编号体系见 `D1.1` §4.0
+
+> **编号**:CS-PURGE-2026-014 | **版本**:v1.0 | **日期**:2026-09-20 | **状态**:**现行(本件描述仓库现状;`D4.4`/`D4.5` 降级为历史留痕)**
+> **性质**:**状态单据(现状)**。回答「投顾模块到底删了没有、现在还在不在、怎么恢复的」—— 这是答辩现场**必被追问**的一点(因为 `D4.4`/`D4.5` 两份文档的标题与结论都写着「清除」)。
+> **时间线证据**:会话留痕 `D1.6` §4.37;合并提交 `e5b4d02`;远端 3 个投顾提交 `5607751` / `2fe7d0c` / `74b7d00`。
+> **配套**:范围与影响面 `D4.4`(仍是有效的历史留痕);清除执行报告 `D4.5`(顶部已加状态更新);纪律凭据 `docs\48` / `docs\49`。
+
+---
+
+## 0. 一句话结论(现状)
+
+**投顾模块在仓库中「有效存在」** —— 2026-09-17 曾按 `D4.4`/`D4.5` 整体清除(94 个文件),2026-09-20 合并远端组员 3 个投顾提交时,因其代码**反向依赖被删除的模块**,裁定「**组员新功能 > 本地清除**」⇒ **恢复**。
+
+| 问题 | 答案 |
+|---|---|
+| 投顾代码还在吗? | **在**(`app\service\*.py` 投顾服务、`app\api\controllers\recommendations.py`、`employee-advisor/` 前端等,取远端版本) |
+| `D4.4` / `D4.5` 还有效吗? | **作为历史留痕有效**;作为「仓库现状」**已失效**(`D4.5` 顶部已加状态更新指向本件) |
+| 客服 Agent 受影响吗? | **不受影响**。客服的范围裁定(`D2.2` §1.7 两条业务线 / `RK-10` 不越界实现投顾)**原样成立** |
+| 恢复有遗留吗? | **有 1 项**:投顾的 `config_release` 工具白名单(`advisor:*`)**尚未发布** ⇒ 投顾 Agent 工具调用 fail closed(见 §5) |
+
+---
+
+## 1. 时间线
+
+| 时间 | 事件 | 依据 |
+|---|---|---|
+| 2026-09-16 | 组员在 `qyqy_develop` 落 **3 个投顾提交**(需求与架构文档 / 客户主动申报 + 受理出草稿 / 方案交付落点与 LLM 增强) | `5607751` `2fe7d0c` `74b7d00` |
+| 2026-09-17 | 本线按 `D4.4`/`D4.5` **整体清除投顾**(94 文件删除) | `D4.5` |
+| 2026-09-20 | 推送被拒(**non-fast-forward**):`fetch` 后发现远端领先 3 个提交,且新代码 `import` 了已删模块 | `D1.6` §4.37 一 |
+| 2026-09-20 | **裁定恢复投顾**:合并提交 `e5b4d02`(parents = `5d0becb` + `74b7d00`) | `D1.6` §4.37 二 / 九 |
+| 2026-09-20 | 补数据库夹具 + 修 1 条「远端本身就是红的」断言 ⇒ 全量回归 **1909 passed / 3 skipped / 0 failed** | `D1.6` §4.37 六/七/八 |
+
+**为什么不能两全**:`D4.4` 在清除**之前**就预警过两条风险 —— ① 按名字清投顾会**同时删掉产品数据底座与 MVP 的硬阻断实现**;② 会**失去「改 6 个底座文件时的对照组」**。组员在**同一个模块**上落了新功能 ⇒ 清除与新功能**不可能同时成立**。裁定取「组员新功能」,依据正是 `D4.4` 自己写下的预警。
+
+---
+
+## 2. 恢复动作清单(做了什么)
+
+| # | 动作 | 说明 |
+|---|---|---|
+| 1 | **取远端版本** | 8 处 `modify/delete` 冲突全部**取远端**:`recommendations.py`、`product_recommendation_service.py`、`employee-advisor/dashboard/` 4 文件、`tools/check_portal_modules.py`、`tools/grant_advisor_role.py` |
+| 2 | **取远端版本(内容冲突 3 处)** | `app/main.py`(投顾 import + `include_router`)、`common/api-client.js`(投顾端点表)、`tests/unit/api/test_portal_frontend.py`(4 条投顾前端契约) |
+| 3 | **定点保留我方改动 1 处** | `app/main.py` 解除冲突的同时,**保留**本轮「移除 `/customer-service-test` 挂载」(联调页与用例已随重构作废) |
+| 4 | **语义回滚(4 处)** | 因「取消清除」而必须回滚:`app/service/agent/bootstrap.py`(`AdvisorAgent` + 5 个投顾工具注册)、`app/core/config.py`(`advisor_rollout_*`)、`app/static/portal/common/layout/app-shell.js`(投顾工作台导航 + `advisor` 角色名)、`tools/seed_test_rbac.py`(admin 全量元组授权模型) |
+| 5 | **叠加我方修复** | `app/static/portal/common/api-client.js`:以远端为基准,**重新叠加**本轮的「访客令牌 `Authorization` 优先」修复(否则该修复被合并静默吃掉) |
+| 6 | **数据库夹具同步** | `tools/grant_advisor_role.py` → 新建 `advisor` 角色(实测 **34 项**权限);`tools/create_test_user.py --id 9020 --username advisor_t --role advisor --password abc12345` → 重建演示账号。补夹具前 3 条投顾集成用例全红,补后 **2 passed / 1 skipped** |
+| 7 | **修一条「远端本身就是红的」断言** | `tests/unit/test_advisor_migration_contract.py` 把 alembic 末端钉死在 `20260914_baseline_auto_increment`,而远端新增 `20260916_advisor_service_request` ⇒ 该断言在远端 `qyqy_develop` 上**本身就失败**(不是合并引入的)。已更新到新末端并补注释 |
+| 8 | **顺带修掉一类假红** | `tools/portal_api_check.py` 新增 `empty_collection_note()`:被渲染的集合为空时判 **`SKIP`(附原因)** 而非 `FAIL` ——「没有行」与「字段没带」是两回事。改后 40 项:**通过 35 / 失败 0 / 跳过 5** |
+
+> 🔑 **未用 `--force`**:强推会毁掉组员 3 个提交。
+
+---
+
+## 3. 恢复后,「客服线」的哪些结论**不变**
+
+| 结论 | 状态 |
+|---|---|
+| 客服 Agent 范围 = **两条业务线**(游客线 + 客服线),不承接投顾能力 | **不变**(`D2.2` §1.7 / `RK-10`) |
+| 长期记忆召回 = **关**、画像 = 客户侧字段级只读 | **不变**(`DEC-19`;理由见 §4) |
+| 客服知识库三集合 / 三档可见性 / 分区隔离 | **不变**(`D2.4`;投顾知识**不进**客服知识库) |
+| 五出口决策链 + 安全不变量 `INV-1`~`INV-5` | **不变**(`D3.6`) |
+| 46 条金标与全部指标(转人工率 10.9% / 出口 100% / 事实 100%) | **不变**(`D3.7` / `D2.6`) |
+| 全量门禁 | **更强了**:对照组回归 ⇒ 1909 passed / 3 skipped / 0 failed |
+
+---
+
+## 4. 一处必须更正的**理由表述**(不是结论)
+
+`DEC-19`(长期记忆召回 = 关)的**结论不变**,但**理由**里有一条曾经写着「收益方(投顾)已整体清除」—— 该理由**随恢复失效**。
+
+**正确理由(继续成立、且更硬)**:
+
+1. **客服 Agent 不产生长期记忆**:`app/worker/runtime.py` 的 `NO_LONG_TERM_MEMORY_AGENT_TYPES` 显式含 `customer_service`(`W7` 发现并修回的真实合规回归 `D-10`);
+2. **注入生成上下文与证据约束生成直接冲突**:`E4` 的输入必须是**证据包**(`INV-2`),把长期记忆注入进去会让答案出现证据包外的内容;
+3. **`PROFILE_CANDIDATE_AGENT_TYPES` 为空集是裁定落地**,不是「重构期临时状态」—— 要重开必须**先改口径**,而不是往集合里加 `agent_type`。
+
+---
+
+## 5. 遗留(**1 项,与客服线无关**)
+
+| # | 遗留 | 说明 | 怎么解 |
+|---|---|---|---|
+| 1 | 投顾 `config_release` 工具白名单(`advisor:*`)**未发布** | 2026-09-20 连库实测 `active_agent_tools` 只有 `customer_service:*` 与 `risk:*` 共 8 项 ⇒ 投顾 Agent 的工具调用**正确 fail closed**(代码在、白名单不在) | 要演投顾线时跑 `tools/publish_advisor_demo_config.py --apply`(该脚本由组员提交 `9c6f839` 提供)。**客服线完全不受影响** |
+| 2 | 投顾演示数据未灌 | `AD011` / `A047` 需要带 `source_url` + `document_sha256` 的适当性证据行,披露文件不在仓库;`tools/seed_advisor_demo.py` 明令**不编证据**(fail closed) | 空集 `SKIP`,不是缺陷(`D1.6` §4.37 十-2) |
+
+---
+
+## 6. 如实登记(含我的失误)
+
+| # | 事项 | 说明 |
+|---|---|---|
+| 1 | 🔴 **清理临时产物时误删 `_advisor_db_backup.sql`** | 属我的操作失误。缓解:真正的代码级备份 `_advisor_purge_backup/`(**51 文件**)与 `_cs_purge_backup/`(34 文件)**完好**;且该库投顾表本为空 |
+| 2 | **本件是「补记」,不是当时的记录** | 恢复发生在 2026-09-20(`W12`),当时的留痕在 `D1.6` §4.37 与 `D4.5` 顶部状态更新。本件是 `W13` 文档审计时**补的上游单据** —— 补记的理由是:`D4.4`/`D4.5` 两份文档标题都叫「清除」,未来检索「投顾 恢复」会**查不到** |
+| 3 | 「恢复」的**边界**需明确 | 恢复的是**模块代码 + 数据库夹具**;投顾的**演示数据/工具白名单**仍是空的(§5)—— 「恢复了」≠「投顾线演示已就绪」 |