From 58849addcc9fd6111b12135f398f743a3eab86a8 Mon Sep 17 00:00:00 2001 From: qyqy Date: Fri, 11 Sep 2026 20:06:23 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BA=A4=E4=BB=98=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E8=A1=A5=E7=AC=AC=E4=BA=8C=E8=BD=AE=E6=89=B9=E5=A4=8D=EF=BC=88?= =?UTF-8?q?=E5=90=AB=20mypy=20=E5=BD=92=E5=9B=A0=E7=BA=A0=E6=AD=A3?= =?UTF-8?q?=EF=BC=89=EF=BC=9B=E4=BF=AE=E6=AD=A3=E6=AE=8B=E7=95=99=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E6=95=B0=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上一轮我只更新了接手文档,**漏了交付说明**——它的末次更新(19:15)早于架构师 19:43 的 第二轮答复,导致它还写着已被推翻的结论。本次补齐: - 新增 §0-B:架构师第二轮的 9 条批复逐条落地对照(含"mypy 归因纠正""docs/00 不改另立登记" "两件事归他""那 2 个失败按新引入对待") - §5.2 整体重写:**认错并给出四组对照实验**(SQLAlchemy 2.0.34+1.14→173、2.0.52+1.14→6、 2.0.52+1.20→3),说明真因是 SQLAlchemy **补丁版**而非"缺类型存根";环境已升级到 2.0.52+1.20.2,mypy 184→3;并列出剩余 3 个错全在同事那条线的文件里 - §5.1 接受架构师口径:那 2 个失败**不是"双方共有的既有失败"**,应作为合并后**新引入的失败**跟踪 - §2 净差异分两段重算:本线增量 16 模块/17 测试/5 工具 vs 同事那条线 334 文件/11 迁移 - §6/§7 更新为第二轮后的状态(哪些已批准、哪些归他、哪些已落地) - 修正残留过期数字:结构审计 51→68 张表、去掉"缺 SQLAlchemy 2.0 类型信息"的错误论断 - 章节号整理:两个同名 "## 0" → "## 0-A / ## 0-B" 文档守卫 35 份无重号;mypy 3 错;测试 1218 passed。 --- docs/交付说明-NL_develop-给架构师.md | 185 ++++++++++++++++++--------- 1 file changed, 124 insertions(+), 61 deletions(-) diff --git a/docs/交付说明-NL_develop-给架构师.md b/docs/交付说明-NL_develop-给架构师.md index db7f27b..bb23437 100644 --- a/docs/交付说明-NL_develop-给架构师.md +++ b/docs/交付说明-NL_develop-给架构师.md @@ -3,16 +3,19 @@ > **收件人**:架构师(`qyqy_develop` 维护者) > **来源分支**:`NL_develop` **合并目标**:`qyqy_develop` > **基线**:本分支已包含 `qyqy_develop` 的 `3f7c5ca`(含你与同事各自的最新推送,落后 0) +> **版本**:**第三版**(§0-A 第一轮评审的落实 → §0-B 你第二轮答复的落实) > **一句话**:以**你已有的客服实现为骨架**,把本线独有的**画像问答出口**、**知识库文档管理三端点**、 > **合规语境豁免**嫁接进去;按你的评审意见把检索字段名改为**运行时探测**; > 并修掉合并过程中暴露的多个"单测全绿但真机必挂"的问题。 > -> 📌 **本文档是给评审者看的**,与给接手开发的 `docs/superpowers/handoff/2026-09-11-交接文档-客服Agent与RAG收尾.md` -> 定位不同:那份讲"怎么继续开发",这份讲"**动了你什么、为什么、要不要你点头**"。 +> 📌 **本文档是给评审者看的**,与另外两份的分工: +> `docs/接手文档-NL_develop-给架构师.md`(接手维护用)、 +> `docs/评审意见回复-NL_develop.md`(对照你的评审意见)、 +> `docs/superpowers/handoff/…`(给下一位开发者:怎么继续写代码)。 --- -## 0. 第二次修订:评审意见的落实情况(2026-09-11 晚) +## 0-A. 第一轮修订:你首轮评审意见的落实情况(2026-09-11 晚) 你那份《评审意见》里的每一条我都核对过实测证据,**除 §3.3 我照你的要求撤回之外,其余全部采纳**。 @@ -21,7 +24,7 @@ | **§1.1 我说的 active 216 在你那边不存在** | ✅ **你是对的**。我这边 `config_release` **总共只有 4 条**(最高 id=216),你那台有 201/198/197… 与 9 条 agent_tools 白名单 —— **两台机器连的不是同一套 MySQL/Milvus**。已把"216 已在共享库生效"整体改写为"**我方环境**已发布,你那台需在合并后补发" | §4.9 | | **§1.2 合并后画像出口会 `AGENT_PERMISSION_DENIED`** | ✅ 采纳。`customer_service:faq` 必须补 `query_customer_profile`。你已提出"我这边可以出脚本"——**接受,由你来发**(`config_release` 是环境数据,不随代码合并) | §4.9 | | **§1.3 字段映射不是 A/B/C,应改运行时探测** | ✅ **已按你的方案实现**:新增 `app/core/knowledge_schema.py`,`describe_collection` 拿真实字段名建映射、按集合缓存;`visibility` 有才过滤;缺必需字段的集合明确判为不可用。**两套 schema 各有单测**(任何回退到硬编码都会让其中一侧红) | §4.2 | -| **§1.4 解释器不统一、mypy 数字不可比** | ✅ **你是对的**,而且我查到了根因:本机 `mypy app` 报 181/184 个错的**主因是缺 SQLAlchemy 2.0 类型信息**(装上 `sqlalchemy2-stubs` 后 181→43,卸载回 184)。**这个数字双方不可比,我不再拿它当结论**;我文件里的 8 个真实错误已单独修掉 | §5 | +| **§1.4 解释器不统一、mypy 数字不可比** | ✅ 你的方向对;**但我的归因在第二轮被你纠正了**:我说"缺 SQLAlchemy 2.0 类型信息"是错的 —— 真因是**我的 SQLAlchemy 补丁版太旧**(2.0.34→2.0.52 使报错 173→6)。环境已升级,**184 → 3 个错**。详见 §5.2 | §5.2 | | **§2 `docs/26` 会和 `docs/21` 重复** | ⚠️ 核对后是**同名重命名**而非并存:你那台的 `docs/21-JWT密钥管理与轮换.md` 与我这台的 `docs/26-…` 是同一份内容,我这边 `21` 已被你的《风控业务第二版迁移清单》占用,所以只能让号。**合并后是一次 rename(删 21、加 26),不会出现两份同主题文档** | §2 末 | | **§3.1 `agent_type` 同意,但要写进审计** | ✅ 已加:`interaction_audit.detail` 增 `agent_type` + `governance_rewrite`(**不改表结构**,`detail` 是 JSON 列);真机已验证最新审计行含这两个键 | §4.1 | | **§3.3 驳回删除 5 份文档** | ✅ **撤回,5 份已全部恢复**(`git show` 从你分支取回,逐字节相同)。`AGENTS.md` 改为"保留但仅作历史参考"并入 D 类 | §1 第 3 项 | @@ -34,6 +37,29 @@ --- +## 0-B. 第二轮修订:你答复里的批复已全部落地(2026-09-11 晚) + +你在《架构师答复 · 第二轮》里的每一条都已按此执行,**本文件是最终版**: + +| 你的批复 | 落地位置 / 状态 | +|---|---| +| §1 **mypy 根因是我的环境版本,不是缺存根** | ✅ **我认错并复现**:SQLAlchemy 2.0.34→2.0.52 使报错 173→6,mypy 1.14→1.20 再降到 3。环境已升级,**mypy 184 → 3 个错**。详见 §5.2 | +| §1 不要把 `sqlalchemy2-stubs` 写进依赖 | ✅ 已卸载、未写入任何依赖文件 | +| §0 `docs/26` 让号批准(且修好了你的既有故障) | ✅ 保留 | +| §0 末 `docs/27` 让号批准 | ✅ 保留 | +| §2.1 画像白名单补发**归你** | ✅ 我这边不再重发;已把我的发布脚本坑(同 key 覆盖)说明给你 | +| §2.2 `memory_sync_outbox` 消费端**归你** | ✅ 我方保持不动;要接的三处已在 §7 列出 | +| §3 `docs/00` **不改**,另立登记 + 更新审计口径 | ✅ 新增 `docs/28-场外与推广域数据表登记.md`;`docs/08` 口径改为「场内 51 + 场外/推广 17 = 68」 | +| §4 那 2 个失败**不是"双方共有的既有失败"** | ✅ **接受你的口径**:它们随本分支合并才出现,请当**新引入的失败**跟踪。详见 §5.1 | +| §6 文档体系两套口径**不需要改写索引** | ✅ 维持现状 | +| §7 环境重建 → 推送 `NL_develop` | ✅ 已完成(环境升级 + 本文件与其余三份文档已推送) | + +> **还剩你那四件事**(你答复 §5 自列的清单),我这边已全部就绪、不需要你再等我: +> ① `alembic upgrade heads` → ② 补发配置 → ③ 接 outbox 消费端 → ④ 补表登记。 +> 其中 **④ 我已替两边做好**(`docs/28` + `docs/08` 随代码合并给你),你只剩前三件。 + +--- + ## 1. 请你重点看的四件事(都在 §4 有逐条说明) | # | 事项 | 状态 | @@ -45,26 +71,38 @@ --- -## 2. 净差异总量(相对 `qyqy_develop` 的 `d2cdbba`) +## 2. 净差异总量 -``` -93 项:新增 51 / 修改 35 / 删除 6 / 重命名 1 -``` +> ⚠️ **本节已按最新状态重算**(原文写的是相对 `d2cdbba` 的 93 项,那已过时)。 +> 那次统计之后发生了两件事:**同事那条线(袁聪,11 提交 / 334 文件)被并进来**, +> 以及**按你的两轮评审意见做的整改**。所以"净差异"要分两段看: -> 新增的 51 项里**包含本文档自身**(`docs/交付说明-NL_develop-给架构师.md`); -> 本说明写作时的数字是 92 项/新增 50,加入本文后为 93/51。 +### 2.1 我这条线独有的增量(相对你的客服/知识线) | 类别 | 数量 | 说明 | |---|---|---| | 新增 `app/` 模块 | **16** | 画像生成与投影、知识入库/检索/管理、Milvus 读写适配、文档解析与落盘、合规语境 | | 新增 `tests/` | **17** | 与服务一一对应;另有 1 个 MySQL 集成测试 | | 新增 `tools/` | **5** | 知识集合建表、种子导入、画像演示数据、合规种子、QA 素材解析 | -| 新增文档 | **14** | 交接文档、工作报告、本交付说明、验收证据(从被 gitignore 的 `.superpowers/` 复制)、ARCHIVE 归档、设计 spec | -| 修改 | 35 | 其中 **7 个是你的核心文件**(见 §4) | -| 删除 | 6 | 5 份编号文档 + 1 份过程产物(见 §1.3) | +| 新增文档 | **5** | 交接文档、本交付说明、评审意见回复、接手文档、`docs/28` 表登记 | +| 修改你的核心文件 | **7** | 逐文件说明见 §4 | -**未新增任何数据库表、未新增迁移**:`fin_knowledge_meta` 等本就在 `docs/00` 基线内,本次只补 ORM 映射。 -`.venv\Scripts\python.exe tools\audit_schema.py` → `51 business tables, no missing or unexpected tables`。 +### 2.2 同事那条线带入的量(**不是我写的,但随本分支一并过来**) + +| 类别 | 数量 | +|---|---| +| 提交 | 11(含 6 个 merge/辅助) | +| 文件 | **334** | +| **alembic 迁移** | **11**(新建 17 张 `offsite_*` / `promotion_*` 表) | +| 影响 | 表数 **51 → 68**(见 `docs/28-场外与推广域数据表登记.md`) | + +> ⚠️ **表数跳变不是"有人偷偷建表"**:`tools/audit_schema.py` 的期望集合是**动态推导**的 +> (读 `baseline_generated.sql` + 扫描 `alembic/versions/*.py` 的 `CREATE TABLE`), +> **随迁移自动增长**。你合并后会看到 `68 business tables`,那是这 11 个迁移的预期结果。 +> `.\.venv\Scripts\python.exe tools\audit_schema.py` → `68 business tables, no missing or unexpected tables` + +**我这条线本身未新增任何数据库表、未新增迁移**:`fin_knowledge_meta` 等本就在 `docs/00` 基线内, +本次只补 ORM 映射。**17 张新表全部来自同事那条线。** --- @@ -329,55 +367,77 @@ raw = client.search(..., output_fields=list(schema.output_fields)) # 只请求 # 1 个是既有缺陷(test_fund_readonly_contract 的空集问题,与本线无关) # 2 个是环境相关(§5.1 已说明:断言方式依赖 JSON 序列化配置,非代码缺陷) -# 结构审计(证明未动 docs/00 基线) +# 结构审计(**注意:表数已从 51 变为 68**,原因见 §2.2) .\.venv\Scripts\python.exe tools\audit_schema.py -# → schema audit passed: 51 business tables, no missing or unexpected tables +# → schema audit passed: 68 business tables, no missing or unexpected tables # 文档守卫(编号无冲突) .\.venv\Scripts\python.exe tools\check_authoritative_docs.py -# → checked 32 documents, no number collision +# → checked 35 documents, no number collision # 顺带修了一处**同事那条线带入的重号**:`docs/15-金融NL2SQL工具接入说明.md` 与既有 # `docs/15-Agent组员详细开发与使用手册.md` 撞号 → 新的那份让号到 `docs/27`(详见 §6) ``` -### 5.1 两个环境相关失败(不是代码缺陷) +### 5.1 两个环境相关失败(**你提醒得对:它们不是"双方共有的既有失败"**) `tests/unit/service/test_offsite_document_recognition_adapter.py` 的 2 个用例断言 **请求体里是中文原文**(`"产品代码".encode() in requests[1].content`), 而本机 httpx 把中文序列化成 `\uXXXX`,字节序列自然不匹配。 -判定它既不是代码缺陷、也不是我引入的,有两条硬证据: -① 该测试文件与我合并的分支 `origin/qyqy_develop` **逐字节相同**(`git diff` 无输出); +**你指出的关键事实我接受**:这 2 个用例**在你那条分支上根本不存在**(同事那条线没进来), +所以它们**不是"双方共有的既有失败",而是随本分支合并才会出现的**。 +⇒ 合并后请当**新引入的失败**跟踪,不要按"历史遗留"放过。我这边已按此口径记录。 + +判定它**不是代码缺陷**的两条证据(供你复核): +① 该测试文件与 `origin/qyqy_develop` **逐字节相同**(`git diff` 无输出)—— 非我方改动; ② 本机 `.pytest_cache` 的 `lastfailed` 里**早已记录这两个用例**(合并前的运行结果)。 -功能无影响(OCR/LLM 请求本身正常)。建议改为断言 `json.loads(body)` 后的字段值—— -比字节级断言稳,也不受序列化配置影响。 +功能无影响(OCR/LLM 请求本身正常)。建议改为断言 `json.loads(body)` 后的字段值 —— +字节级断言本来就不该用来测 JSON(你在答复里也是这个意见)。 -### 5.2 mypy:**这个数字不可比,我不拿它当结论**(采纳你 §1.4) +### 5.2 mypy:**你在第二轮的纠正成立,我原归因错了** ✅ 已收敛 -你那边 `mypy app` 是 138 文件 0 错;我这边同一份代码报 **184** 个错。 -根因**不是代码质量差异,而是本机缺 SQLAlchemy 2.0 的类型信息**: +**先认错**:我原先写"根因是本机缺 SQLAlchemy 2.0 的类型信息",**方向对了一半、结论反了**。 +你的纠正成立 —— SQLAlchemy 2.0 **自带 `py.typed`**,`sqlalchemy2-stubs` 是给 **1.4** 用的 +(装上后"181→43 看着变好",实际是换了一批按 1.4 API 核对的错)。 -``` -本机(无存根) mypy app → 184 errors -装 sqlalchemy2-stubs mypy app → 43 errors ← 该类存根是 2.0 之前的旧包, - 还会换一批新错(mapped_column/DeclarativeBase 不存在) -卸载后 mypy app → 184 errors -``` +**我做了决定性实验(四组对照)**: -**结论:本机 mypy 基线不可作为质量结论,两边也不可比。** -但那 184 里有 **8 个是我文件里的真实错误**,已单独修掉: +| 组合 | `mypy app` | +|---|---| +| SQLAlchemy **2.0.34** + mypy 1.14.1 ← 我原来的环境 | **173** | +| SQLAlchemy 2.0.34 + mypy 1.20.2 | 173 | +| SQLAlchemy **2.0.52** + mypy 1.14.1 | **6** | +| SQLAlchemy 2.0.52 + mypy **1.20.2** | **3** | + +⇒ **主因是 SQLAlchemy 的补丁版本**(173 → 6):旧补丁版的类型标注不完整, +`BIGINT`/`DATETIME` 被判成未类型化函数,于是 `app/model/*.py` 每处列定义都报一条。 +mypy 版本是次因(6 → 3)。 + +**已处理**: +1. 环境升到 **SQLAlchemy 2.0.52 + mypy 1.20.2**(均在 `pyproject.toml` 约束内)→ **184 → 3 个错**; +2. **没有**把 `sqlalchemy2-stubs` 写进依赖(按你的明确要求); +3. 我文件里那 8 个真实错误已修(你已看过,认为改法正确): | 文件 | 错数 | 处理 | |---|---|---| -`app/service/knowledge_retrieval_service.py` | 4 | ✅ 已修 | -`app/api/controllers/knowledge_management.py` | 3 | ✅ 已修 | -`app/service/model_gateway.py` | 2 | ⏸ 未动:`ModelEndpointConfig` 实际具备协议要求的全部字段,属 `Mapped[T]` 在缺存根时的消解问题,**不用 `cast` 掩盖** | -`app/worker/runtime.py` | 1 | ⏸ 未动:同类问题 | -其余 ~174 | — | 全在 `app/model/*.py` 与既有文件,属本机缺存根所致 | +`app/service/knowledge_retrieval_service.py` | 4 | ✅ 已修(`Mapping`→`dict` 等) | +`app/api/controllers/knowledge_management.py` | 3 | ✅ 已修(工厂返回类型) | -> 若希望两边数字可比,需要固定 mypy 依赖版本或把"缺存根"写进已知限制 —— 属公共约定, -> 我**没有擅自改** `pyproject.toml` 的 mypy 配置。 +**剩余 3 个错**(都在**同事那条线的文件**里,非本线代码,你合并前那边没有这些文件): + +``` +app/service/offsite_document_recognition_adapter.py:788 redundant-cast +app/service/offsite_fund_service.py:1203 return-value(dict[str, bool|None]) +app/service/offsite_fund_service.py:1240 attr-defined(Message.get_content) +``` + +> 按你"先放着"的意见,`model_gateway.py` 与 `runtime.py` 那两处我**没动**(也没用 `cast` 掩盖)—— +> 环境升上来之后它们**确实自己消失了**,与你的预判一致。 + +**一个建议(供你裁决,我没擅自改)**:`pyproject.toml` 的 `sqlalchemy>=2.0,<3` 允许范围内 +补丁版差异会带来 173 vs 3 的量级差异。若希望门禁数字稳定,建议把 SQLAlchemy 钉到具体补丁版 +(例如 `>=2.0.52,<2.1`),否则同样的门禁命令在两个人的机器上可能给出完全不同的结论。 **真机链路**(真实 MySQL / Redis / Milvus / DashScope / HTTP,非单测替身): @@ -393,29 +453,33 @@ raw = client.search(..., output_fields=list(schema.output_fields)) # 只请求 ## 6. 需要你裁决 / 知晓的事项汇总 -1. **`AgentGovernance.review()` 新增 `agent_type` 参数** —— 你已同意;**审计留痕已按你要求补上** - (§4.1)。若你更希望走别的判定途径(例如让 Agent 自己声明 `customer_facing` 属性),告诉我,我改。 +1. **`AgentGovernance.review()` 新增 `agent_type` 参数** —— ✅ **你已同意**;审计留痕已按你要求补上 + (§4.1,真机验证通过)。若你更希望走别的判定途径(例如让 Agent 自己声明 `customer_facing`),告诉我,我改。 2. **检索字段名** —— ✅ 已按你 §1.3 改为**运行时探测**,不再是"三选一"(§4.2)。 -3. ~~删除 5 份编号文档~~ —— ✅ **已撤回**,5 份全部恢复(你 §3.3 驳回)。 -4. **`docs/26-JWT密钥管理与轮换.md`** —— 是**重命名**(原 `docs/21`,因 `21` 已被你的《风控业务 - 第二版迁移清单》占用),**不是新增、也不会与 `docs/21` 并存**。 -5. **`config_release` 是环境数据** —— 我方已发 216 且**仅对我方环境有效**;**你那台需在合并后 - 补发**(把 `query_customer_profile` 加进 `customer_service:faq`)。这一步你说你来出脚本,我接受。 +3. ~~删除 5 份编号文档~~ —— ✅ **你驳回,已撤回**,5 份全部恢复。 +4. **`docs/26-JWT密钥管理与轮换.md`** —— 是**重命名**(原 `docs/21`)。✅ **你在第二轮批准**, + 并指出 `docs/21` 在我让号**之前**就已经是两份了(你的守卫脚本当时是失败的)—— + 即我的让号顺手修好了你那边一个既有故障。 +5. **`config_release` 是环境数据** —— ✅ **归你**(第二轮确认):你那台合并后补发一版, + 把 `query_customer_profile` 加进 `customer_service:faq`,其余 8 条原样继承。 + 你已记下"**同 key 的继承项必须被本次新定义覆盖**"这个坑。 6. **`fund_query_demo:fund_quote` 白名单** —— 在我方环境缺失(你那边 201 里有)。属环境差异, 我方需补发;你那台不受影响。 -7. **同事那条线带入的文档重号** —— `docs/15-金融NL2SQL工具接入说明.md` 与既有 - `docs/15-Agent组员详细开发与使用手册.md` 撞号,我把**新的那份**让号到 `docs/27` - (依据:`15-…手册` 被 `docs/16`/`17` 与 `AGENTS.md` 三处引用,改名代价更大)。 - 若你认为该由旧的那份让号,我改回来。 -8. **同事那条线带入 11 个 alembic 迁移**,我方已执行 `alembic upgrade heads` 建出 - `offsite_*` / `promotion_*` 等表(本库此前**一张都没有**,而 `alembic_version` 却已指向 - 同事的 revision —— 属"版本号跑了但表没建"的状态)。**你那台若也这样,合并后需补跑迁移。** +7. **同事那条线带入的文档重号** —— ✅ **你在第二轮批准**我让 `docs/15` → `docs/27` + (依据:手册被 `docs/16`/`17`/`AGENTS.md` 三处引用,改名代价更大)。 +8. **同事那条线带入 11 个 alembic 迁移** —— ✅ **两边的坏状态都靠 `alembic upgrade heads` 收敛**: + 我方是"版本号跑了、表没建",你方是"表没建、版本号也没跑"。**你合并后需补跑**(已在你的清单里)。 +9. **`docs/00` 要不要补那 17 张表** —— ✅ **你在第二轮裁决:不动 `docs/00`,另立登记**。 + 我方已按此落地:新增 **`docs/28-场外与推广域数据表登记.md`**(17 张表逐表登记 + 规则 8 两向边界核对), + 并把 `docs/08` 的审计口径改为「场内 51 + 场外/推广 17 = 68」。**`docs/00` 一个字段都没动。** --- ## 7. 已知限制(未做,不是遗漏) -1. **画像链路"生产端已接、消费端未接"** —— 与你 §4 的发现**同源但不同表现**,请一起裁决归属: +1. **画像链路"生产端已接、消费端未接"** —— ✅ **归属已定(第二轮):消费端归你**。 + 判定依据是你给的(生产者在我这边、你那边什么都没有 ⇒ 缺的是装配层的消费端,而 `app/worker/` + 正是你在维护)。**我方保持不动**,等你合并后接。 | | 你那台(你 grep 的结论) | 我这台(实测) | |---|---|---| @@ -424,11 +488,10 @@ raw = client.search(..., output_fields=list(schema.output_fields)) # 只请求 | 消费端 | 无 | 有服务定义(`ProjectionReconciliationService`)**但全仓无实例化点** | | `GraphProjectionWorker` | **无实例化点**(你发现) | **同样无实例化点**(我复核一致) | - **⇒ 同一类问题:组件写好了、线没接。** 我这台更进一步:事件**已经写进表里**、没人消费。 - 建议**先定归属再动手**(涉及 `app/worker/` 与 `app/service/profile_*`,跨你我两条线), - 否则两边各接一根线会更乱。 -2. **mypy** —— 见 §5.2:本机数字不可比(缺 SQLAlchemy 2.0 类型信息);我文件里的 8 个真实错误已修, - 其余未动。**没有擅自改 mypy 配置。** + 具体要接的三处(供你参考):`GraphProjectionWorker` 的实例化、与 `runtime.py` 的装配、 + `ProjectionReconciliationService` 的接线。 +2. **mypy** —— ✅ **已收敛**:见 §5.2。环境升到位后从 184 → **3 个错**,且剩余 3 个都在 + **同事那条线的文件**里(非本线代码,你合并前那边没有这些文件)。**没有擅自改 mypy 配置。** 3. **Redis 限流降级**:容器以 `--requirepass 123456` 启动而 `.env` 无密码 ⇒ 每次请求一条 `AuthenticationError` 堆栈、限流形同虚设(不阻断业务)。属本地环境配置,未擅自修改。 4. **Docker Desktop 不常驻**:它没运行时 Milvus 不可用(`docker` CLI 报连不上守护进程)。