diff --git a/AGENTS.md b/AGENTS.md index bf62d4b..fb1a253 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,13 +18,15 @@ ## 📖 接手先读(按此顺序,只读这些就够) > **⭐ 第 0 步先读这个**:`docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md` -> —— 2026-09-11 收尾会话的交接文档:环境口径、本次交付内容与**可复现验证证据**、 -> 6 个"单测绿但真机挂"的静默故障、**8 条已知问题清单**、Git 未提交状态。 +> —— 客服 Agent + RAG 这条线的交接文档(**含合并完成后的第二次更新**):环境口径、交付内容与 +> **可复现验证证据**、合并后修掉的 3 个真机故障、**已知问题清单(逐条标注当前状态)**、Git/PR 状态。 +> 当前工作分支是 **`NL_develop`**(个人分支 → PR 合回 `qyqy_develop`),**不要再用 `6516ccb`**。 > 它是对"当前状态"最准确的一份,读完它再读下面这些。 > > 2026-09-11 做过一次文档清理:**已删除 5 份编号文档**(`04`/`06`/`10`/`13`/`99`)与 10 份过期过程产物。 > 删除理由与内容去向见 `docs/superpowers/ARCHIVE-2026-09-11-文档清理归档.md`。 -> **下面这 17 份是清理后剩下的,均已核对过内容正确性。** +> ⚠️ 注意:架构师的分支上**仍保留这 5 份**(只是没人引用),合并时保留了他的版本以不干扰其工作线; +> 若要彻底删掉,请在合回 `qyqy_develop` 的 PR 里单独说明。 ### A. 核心 7 份(无论接手哪条线都必读) @@ -69,7 +71,10 @@ - 解释器固定 **`.\.venv\Scripts\python.exe`**。**不是** `conda activate jr_py313`、**不是** `D:\conda\envs\jr_py313`(旧文档里有这些残留写法,已修正主要几处)。 - 数据库现为 **52 张表**(含 `alembic_version`)= **51 张业务表**。核验命令:`.\.venv\Scripts\python.exe tools\audit_schema.py`。 -- 已注册业务 Agent:`FundQueryDemoAgent`、`CustomerServiceAgent`(见 `app/service/agent/bootstrap.py`)。 -- 已注册公共只读工具:`check_suitability`、`query_fund_quote`、`query_knowledge`、`query_customer_profile`;**工具可用范围 = 代码上限 ∩ 当前 active `config_release` 的发布白名单**,缺发布配置则失败关闭。 -- 测试基线:`1 failed, 804 passed, 2 skipped`(2026-09-11 实测);唯一失败是 `tests/unit/repository/test_fund_readonly_contract.py`(**底座既有缺陷,不要修也不要报**)。 -- mypy 基线 **151 个错**(`mypy app`)——接手时不要让它变多。 +- 已注册业务 Agent:`FundQueryDemoAgent`、`CustomerServiceAgent`、`RiskAgent`、`PlatformProbeAgent`(见 `app/service/agent/bootstrap.py`)。 +- 已注册公共只读工具:`search_knowledge`(客服知识检索)、`check_suitability`、`query_customer_profile`(画像)、`query_fund_quote`; + **工具可用范围 = 代码上限 ∩ 当前 active `config_release` 的发布白名单**,缺发布配置则失败关闭。 + 白名单现由 `tools/publish_customer_service_config.py` 发布(当前生效版本 `id=216`); + 发布时**同 key 的继承项必须被本次定义覆盖**,否则旧值会被子集校验 422 拦下(脚本已处理)。 +- 测试基线:`1 failed, 1013 passed, 2 skipped`(2026-09-11 合并后实测);唯一失败是 `tests/unit/repository/test_fund_readonly_contract.py`(**底座既有缺陷,不要修也不要报**)。 +- mypy 基线 **181 个错**(`mypy app`)——其中 135 个集中在 `app/model/fund.py`+`app/model/risk.py`(架构师侧模型文件),接手时不要让它再变多。 diff --git a/docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md b/docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md index 7db7a7a..04c9c49 100644 --- a/docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md +++ b/docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md @@ -7,11 +7,21 @@ ## 0. 30 秒摘要 -- 分支 `qyqy_develop`,代码停在 `6516ccb`(**本次交付尚未提交**,见 §6)。 -- 本次交付的线:**客服 Agent(`CustomerServiceAgent`)+ RAG 知识检索 + 画像工具**。 -- 交付状态:**代码与真机链路均已验证通过**;测试基线 `1 failed, 804 passed, 2 skipped`(唯一失败是既有缺陷,不属本次,见 §5)。 -- 未提交:**87 项变更**(含新建 22 个模块 + 16 个测试文件)。用户会自己 `git add -A`,**你不要动 git**。 -- 最大的两个遗留:① `memory_sync_outbox` 没有消费者(画像不真同步);② Redis 密码没配(限流降级)。 +> ⏱ **2026-09-11 第二次更新(合并完成后)**:本节已按最终状态重写,§6 的 Git 状态也已更新。 +> 你的工作**已推送**到远端个人分支 `NL_develop`(`fb7d2f7`),并已包含架构师当时最新的 +> `qyqy_develop`(38 个新提交)。**接手请从这条分支开始,不要再用 `6516ccb`。** + +- 分支:**`NL_develop`**(个人分支,从架构师的 `qyqy_develop` 拉出)→ PR 合回 `qyqy_develop`。 +- 本次交付的线:**客服 Agent(`CustomerServiceAgent`)+ RAG 知识检索 + 画像工具 + 知识库管理三端点**。 +- 交付状态:**代码与真机链路均已验证通过**;测试基线 `1 failed, 1013 passed, 2 skipped` + (唯一失败 `test_fund_readonly_contract` 是既有空集缺陷,与本线无关,见 §5)。 +- 合并形态:`NL_develop` **以架构师那套为骨架**(三档置信判定、适当性裁决、短期会话记忆、 + 话题矩阵、风控工具全部保留),把本线独有的**画像问答出口**、**知识库管理三端点**、 + **合规上下文豁免**嫁接了进去。 +- 合并后修掉 3 个"单测全绿但真机必挂"的问题:知识检索字段名与现库集合 schema 不符 + (静默零召回)、发布白名单与代码上限不匹配(`AGENT_PERMISSION_DENIED`)、免责声明被追加两次。 +- 最大的两个遗留仍是:① `memory_sync_outbox` 没有消费者(画像不真同步); + ② Redis 密码没配(限流降级)。 --- @@ -141,54 +151,68 @@ --- -## 5. 已知问题清单(按优先级,**都还没修**) +## 5. 已知问题清单(按优先级) -1. **`memory_sync_outbox` 无消费者**(最重要)。画像快照会写入 2 条 `待处理` 事件,但没有任何 Worker - 消费它们 → 画像**并没有真的同步到 Milvus / Neo4j**。现库 2 条待处理。 +> ⏱ 2026-09-11 第二次更新:下面每条都标注了**当前状态**(哪些合并时顺带修掉了)。 + +1. **`memory_sync_outbox` 无消费者**(**仍未修,最重要**)。画像快照会写入 `待处理` 事件, + 但没有任何 Worker 消费它们 → 画像**并没有真的同步到 Milvus / Neo4j**。 修法:仿 `app/worker/knowledge_vector_worker.py` 写 handler,并在 `app/worker/runtime.py` - 的 handler 字典里注册(**该文件第 191-203 行就是上一次"handler 写了但没注册"的教训**)。 -2. **Redis 密码未配**:容器 `redis` 以 `--requirepass 123456` 启动,`.env` 的 - `REDIS_URL=redis://127.0.0.1:6379/0` 无密码 → 每次请求打一条 `AuthenticationError`, - 限流器**降级放行**(不阻断业务,但限流形同虚设)。修法:`REDIS_URL=redis://:123456@127.0.0.1:6379/0`。 + 的 handler 字典里注册(**该文件里 `knowledge.vector_sync_requested` 的注册处就是 + 上一次"handler 写了但没注册"的教训**,照着它来)。 + ⚠️ 注意:架构师那轮提交里有"记忆→画像→图全自动触发"的工作,**动手前先确认这条是否已被他覆盖**。 +2. **Redis 密码未配**(**仍未修**):容器 `redis` 以 `--requirepass 123456` 启动,`.env` 的 + `REDIS_URL=redis://127.0.0.1:6379/0` 无密码 → 每次请求打一条 `AuthenticationError` 堆栈, + 限流器**降级放行**(不阻断业务,但限流形同虚设,且日志噪声极大)。 + 修法:`REDIS_URL=redis://:123456@127.0.0.1:6379/0`。 ⚠️ `.env` 属本地环境配置,**改前先问用户**。 -3. **`tools/seed_test_rbac.py` 跑不起来**:13 个 FK 指向 `sys_user`,而子表非空 - (`agent_faq_synonym` 488 行等)→ 脚本里的父表 DELETE 必然失败。 - 修法:删掉父表 DELETE,改 upsert。**注意**:此脚本会创建 4 个权限(其中包含知识库的 - `knowledge:query`/`knowledge:manage`),改完才能一键重建 RBAC 演示数据。 -4. **`agent.run_requested` 积压**:pending 266 / failed 40,另有 `agent.run_completed` pending 34、 - `memory.extraction_requested` pending 34 —— 都是**历史 run 留下的**,不是当前故障; - 但说明常驻 Worker 没在跑。交验收前要么启动 Worker,要么在报告里说清口径。 -5. **`TODO.md` 系统性过期**(5 处"49 张表"、T8.1 未勾选但已交付)。**已决定不修**, - 只在 `AGENTS.md` 里标注"不要用它判断进度"。你若修了,请同步删掉 `AGENTS.md` 里那条警告。 -6. **Milvus 容器脆弱**:本次遇到过 `Exited (134)` + `panic: etcdserver: leader changed`, +3. **`tools/seed_test_rbac.py` 跑不起来**(**仍未修**):13 个 FK 指向 `sys_user`,而子表非空 + (`agent_faq_synonym` 488 行等)→ 脚本里的父表 DELETE 必然失败。修法:删掉父表 DELETE,改 upsert。 +4. **`agent.run_requested` 积压**(**仍未修,但已确认无害**):历史 run 留下的 pending/failed, + 常驻 Worker 没在跑;探针手工 `dispatch_one + execute` 即可跑通。交验收前要么启动 Worker, + 要么在报告里把口径说清楚。 +5. **`TODO.md` 系统性过期**(**已决定不修**,只在 `AGENTS.md` 里标注"不要用它判断进度")。 +6. **Milvus 容器脆弱**(**已复核**):遇到过 `Exited (134)` + `panic: etcdserver: leader changed`, `docker start milvus-standalone` 可恢复(恢复后 `Up (healthy)`)。它不是"没装",只是会掉。 -7. **`profile_uuid` 有 UNIQUE 约束**,所以每个版本用新 uuid。若将来需要"跨版本同一实体标识", +7. **`profile_uuid` 有 UNIQUE 约束**(**仍适用**):每个版本用新 uuid。若将来需要"跨版本同一实体标识", **加新字段**(如 `entity_uuid`),**不要**改约束(违反 `AGENTS.md` 规则 4)。 -8. **未验证的残留**:M002 正向路径未复跑(`docs/20` §5 记录了底座 4 条未修偏差,接手前值得看一眼)。 +8. ~~JWT 密钥路径~~ **✅ 已修**:架构师把路径改成 `config/jwt/dev/`,本机密钥已在 + `tools/generate_jwt_keys.py --out-dir config/jwt/dev` 生成,并已同步到 `.env`。 + 换机器/清目录后若出现 `JWT public key cannot be read`,照这条重建(见 `docs/26`)。 +9. ~~免责声明重复~~ **✅ 已修**:Agent 曾自己拼一句 + 治理层再追加 → 客户看到两条。 + 现统一由治理层注入(`review_output` 的 `agent_type` 判定是否面向客户)。 +10. ~~检索服务字段名不符~~ **✅ 已修**:见下方 §6 的 PR 说明第 3 条。 +11. **M002 正向路径未复跑**(**仍未做**):`docs/20` §5 记录了底座几条未修偏差,接手前值得看一眼。 --- ## 6. Git 状态(**你绝对不要执行任何 git 写操作**) -- 分支 `qyqy_develop`,HEAD = `6516ccb`。 -- 变更总量(**按 `git diff HEAD` + 未跟踪**,权威口径):**已跟踪改动 33 个 + 未跟踪新文件 51 个 = 84 个文件**。 - - 未跟踪的 51 个里有:`app/` 新模块 19、`tests/` 新测试 17、`tools/` 新脚本 5、文档与产物 10。 - - `git status --short` 会显示 86 行(3 行 `A ` 与 5 行 `AD` 是同一批文件的暂存态重复显示)。 - - **没有新表、没有新迁移**:`fin_knowledge_meta` 等本就在 `docs/00` 基线内,本次只补 ORM 映射。 -- 索引里还有 **5 项 `AD`**(曾 `git add` 过又被删除的文件:`docs/superpowers/handoff/` 下 3 份 + - `docs/superpowers/plans/` 下 1 份)与 **6 项 `D`**。**用户的暂存区有他自己的东西**, - 所以必须由用户自己跑 `git add -A` 来收敛,AI 一律不碰。 -- 建议提交信息(按主题拆,也可合并成一条): +> ⏱ 2026-09-11 第二次更新:本节原来描述的是"未提交"状态,已经**不再适用**。 + +- 你的工作**已推送**:远端个人分支 **`origin/NL_develop`** = `fb7d2f7`,本地与之完全一致(领先/落后均为 0)。 +- 该分支的提交序列(从新到旧): ``` -chore(docs): 清理 5 份过期编号文档与 10 份过程产物,补 ARCHIVE 归档说明与验收证据入 docs/ -feat(knowledge): 打通知识库三端点(上传/列表/删除)与 Milvus 向量同步,修 6 处真机静默故障 -feat(agent): CustomerServiceAgent 接入 RAG 与画像工具,两段式工具白名单失败关闭 -feat(profile): 新增画像生成服务与 memory-profile 白名单投影,修 memory() 恒返回 {} -fix(compliance): 零容忍词按句界豁免否定与元语言上下文,恢复政策问答 -test: 新增 6 个服务/核心模块单测(画像/知识/合规上下文),基线 804 passed +fb7d2f7 merge: 跟进架构师最新 qyqy_develop(38 提交) ← docs/25 撞号 → 本人让号到 docs/26 +cbd6de2 Merge remote-tracking branch 'origin/qyqy_develop' ← 冲突仅 model_gateway.py(取并集) +395bad2 fix(knowledge): 检索适配现库 schema、发布对齐的白名单、免责声明只由治理层注入 +57c4add merge: 客服Agent+RAG+画像 与 架构师当时最新版合并(conflict 全解) +e4c4099 wip: 客服Agent + RAG + 画像收尾(基于 6516ccb) ← 用户原始 84 文件工作 ``` +- **架构师最新的 `qyqy_develop` 已是本分支的祖先**(`git rev-list --count HEAD..origin/qyqy_develop` = 0)。 +- 工作区干净(`git status --porcelain` 为空);临时探针脚本已全部清理。 +- **下一步合回主干**:对 `qyqy_develop` 发 PR(Gitea:`.../pulls/new/NL_develop`)。 + 需要注意 PR 里会带上 3 类"跨分支决策",请在 PR 描述里点明,别让评审者自己去猜: + 1. **删除了 5 份编号文档**(`docs/04`/`06`/`10`/`13`/`99`)——它们在架构师分支上仍存在, + 本次删除是**有意的**(与 `AGENTS.md` 的收尾文档清理一致),理由见 + `docs/superpowers/ARCHIVE-2026-09-11-文档清理归档.md`; + 2. **`docs/26-JWT密钥管理与轮换.md` 是我方新增**(原 `docs/21`→`docs/25`→`docs/26` 两次让号); + 3. **检索服务字段映射**(`knowledge_search_service.py` 的 `_FIELD_ALIASES`)是**按现库集合 schema** + 做的适配,不是按 `tools/load_knowledge_milvus.py` 那套;若将来按那套重建集合并回填, + 改回映射即可(代码里有注明)。 + --- ## 7. 文档地图(哪些能读、哪些别读) @@ -205,6 +229,8 @@ test: 新增 6 个服务/核心模块单测(画像/知识/合规上下文) | 6 | `docs/08-数据库结构审计基线.md` | 审计工具职责 | | 7 | `docs/07-测试问题修复记录.md` | P0/P1 修复记录(**无替代**) | | + | `docs/14` → `docs/18` → `docs/19` → `docs/09` | 你这条线(客服+RAG)的接入细节 | +| + | `docs/21` / `docs/24` / `docs/25` | 架构师侧的风控迁移清单、客服阶段性总结、风控代码评审 | +| + | `docs/26-JWT密钥管理与轮换.md` | JWT 密钥路径与轮换(本地 `config/jwt/dev` 需自行生成,见 §1) | | + | `docs/验收与审计/phase1-acceptance-report.md` | **"现在做到哪了"的唯一答案**(Phase 1 七条标准逐条证据) | **别读 / 别信**: