Просмотр исходного кода

docs(tdd): R104 测试负责人执行汇报 — 后端定向契约132/107/25(+4绿)、251派发恢复43/32/11、浏览器28/28;新增B-97(并发构建+磁盘满致全量两次失效)/B-91解除

E2E Test Bot 3 дней назад
Родитель
Сommit
9f2dad792e

+ 196 - 0
docs/tdd/orchestration/report-test-2026-11-09-R104.md

@@ -0,0 +1,196 @@
+# 测试负责人工作汇报(R104)
+
+> 汇报人:测试负责人(软件测试专家团 · 陆谨)|汇报周期:2026-11-09(第 104 轮)
+> 负责模块/单元:浠艾福 XAF(d:/cfc)· 全栈测试闭环(浏览器自动化 + 251 langgraph 派发 + 回归)
+> 执行档:review(内网站点 + 251 派发已授权;未联网装依赖、未改生产代码、静默无人值守)
+> 基线:`cfclub @ 4cc66482b`(= `origin/cfclub`)
+
+---
+
+## 一、本轮工作数据汇总
+
+### 1.1 测试用例建设
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 本轮新增测试用例数 | **0 个** | 窗口 `7a677c4c7..HEAD` 对 `docs/superpowers/specs` / `tests/test-cases` 命中 **0 提交**(仅 1 个 `[skip ci]` bump + R103 报告)→ 无 SRS/场景变更,无新建用例义务 |
+| 本轮验证执行测试数 | **768 个** | 后端定向契约 132 + 前端 426 + 管理端 116 + 根级 23 + 浏览器 E2E 28 + langgraph@251 43 |
+| 用例通过率 | **88.7%** | 681 / 768;红 84(契约 25 + 前端 32 + 根级 16 + langgraph 11)、skip 3 |
+
+### 1.2 会话与任务分发
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 分派任务数 | **3 个** | ① 251 langgraph pytest(shell 通道,**成功**)② 本机 admin/frontend/shop E2E ③ 本机 health 鉴权契约 |
+| 恢复智能体会话数 | **1 个** | 251 首派 shell 轮询 408s 未退出 → 改用独立 shell 直读 `/tmp/r104_pytest.log`(8s 取回),非重建会话 |
+| 当前在用会话数 | 1 个 | 251 opencode(`sh_*` shell 会话,均 exited) |
+
+### 1.2b 各会话当前工作状态列表
+
+| 会话标签 | 会话 ID | 当前状态 | 当前任务 | 静默/空闲时长 | 工作目录 | 备注 |
+|----------|---------|----------|----------|---------------|----------|------|
+| 251-langgraph | `sh_1bf27c640001cHu8eYd2Vsf7Jh` 等 | done | pytest 43 例 | — | `/sc-data/cfc/cfc-langgraph` | 后台写文件 + 独立 shell 读文件(B-96 法) |
+| 本机-admin | — | done | admin-live 5 | — | 干净 | `tests/` 内执行(B-52) |
+| 本机-frontend | — | done | frontend-live 6 | — | 干净 | 189/204 失联,本机单节点串行 |
+| 本机-shop | — | done | shop-sort 4 | — | 干净 | 首跑 1 超时 → 复跑 4/4 |
+| 本机-health | — | done | health-contract 13 | — | 干净 | 全 401(B-61 维持) |
+| 本机-backend | — | failed | 全量 mvn test | — | 不干净(target 被外部改写) | 两次均环境失效(B-97) |
+
+### 1.3 问题处置
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 新测试发现问题数 | **2 个** | **B-97(P1 环境)**:跑测窗口内工作区被并发构建/写入 + 磁盘 100% → 后端全量两次失效(433 NoClassDefFound / 卡死 11 分钟);**B-91 解除**(251 派发确定性通道) |
+| 已解决测试相关问题数 | **1 个** | B-91(251 派发「取不回结果」)→ 「kill 残留 + 后台写文件 + 独立 shell 读文件」闭环 |
+| 待解决测试相关问题数 | **10 个** | P0:B-65(第 11 轮)、B-90(第 4 次);P1:B-69(第 11 轮)、B-89(第 6 轮)、B-95(第 2 轮)、B-92、B-82、B-84、B-87、B-97 |
+
+### 1.4 本轮 git 提交与推送证据
+
+| 提交 sha | 关联任务/能力键 | 阶段 | 触及文件类型 | 目标分支 | 已推送远端 | 备注 |
+|----------|-----------------|------|--------------|----------|------------|------|
+| (见文末回填) | R104 汇报 + 执行记录 + 通知 + blockers | 报告 | 文档 | cfclub | 是 | 提交后回填实际 sha |
+
+### 1.5 状态机阶段分布(全局进度)
+
+| 阶段 | 键数 | 备注 |
+|------|------|------|
+| UNTRACKED | — | CFC 发现/跟踪模式 |
+| RED | 4 族 | Guhe T3/T4 18 例 / guhe.kb.queryLowSidePatch 4 例 / diet healthAdjust 9 例 / dx-bridge(沿用) |
+| YELLOW | 2 键 | `guhe.p3.lowSideAggregate` / `diet.recommendation.participantSelect`(沿用) |
+| GREEN | 11 类 | 本轮定向契约 **11 类 86 例全绿**(NoPathMap/V2Route/VersionSplit/ShellGuard/PageTailClean/KbFieldExpose/KbVersionSense/GateLowSideRedline/GateStrainBlock/LowSideAggregate/ReportPersonalAssert) |
+| DONE | +2 | `dae41ff59`(S-cfc-121)已复验;`S-cfc-118/123` 实现已入 origin,待下轮基线复验 |
+
+### 1.6 数据源健康度
+
+| 数据源 | 读取键数 | 是否正常 | 备注 |
+|--------|----------|----------|------|
+| 需求侧(SRS) | 203 份 specs | 正常 | 窗口内零新增、零变更 |
+| 测试用例(test-cases) | 13 文件 / 824 条 TC | 正常 | 锚点可执行引用 73 条(8.9%) |
+| E2E 用例 | 28 例 | 正常 | 100% 通过 |
+| langgraph pytest@251 | 43 例 | 正常 | 32/11,零漂移 |
+| 后端 surefire XML | 定向 16/16 | 部分 | 全量两次失效(B-97);XML 未沉默 |
+
+---
+
+## 二、向研发提出的改进建议
+
+| 序号 | 建议标题 | 问题描述 | 根因分析 | 建议方案 | 优先级 | 状态 |
+|------|----------|----------|----------|----------|--------|------|
+| 1 | langgraph analyze checkpointer(第 11 轮) | `test_analyze.py` 2 例 500 | `analysis_graph.py:96 MemorySaver()` + `analyze.py:35 ainvoke` 无 `thread_id` | 去 MemorySaver 或显式传 `thread_id` | P0 | 待评估 |
+| 2 | 251 LLM 链路超时/熔断(第 4 次) | live `chat` 挂起 75s 零字节(analyze 已恢复 200/21.5s) | 无 timeout/熔断,凭据不稳(B-84 同源) | 全部 LLM/检索调用加 timeout + 熔断 + 凭据巡检 | P0 | 待评估 |
+| 3 | `/api/mind/**` 4 端点在公开白名单(第 11 轮) | 匿名 POST 未 401,直接进控制器返回「参数缺失」 | `JwtInterceptor.java:79-82` PUBLIC_PATHS | 4 条移入 `LOGIN_REQUIRED_PATHS` | P1 | 待评估 |
+| 4 | 前端 diet 32 例红 | `diet/recommendation.uiRework` 等契约红 | S-cfc-127 实现已入 origin,本轮基线未含 | 下轮基线更新后定向复跑 | P1 | 待评估 |
+| 5 | Guhe T3/T4 与 kb.queryLowSidePatch 25 例红 | 契约声明的方法/常量未实现 | T3 判据、T4 红线、L2-2 可查询子键在途 | S-cfc-118/123 已入库 → 下轮基线复验;剩余 T3 续派 | P1 | 待评估 |
+| 6 | 构建/磁盘环境治理 | 全量跑测两次失效、编译瞬时失败、`safe-delete` 超时 | 工作区被并发构建 + D 盘 100%(470MB) | 跑测窗口内禁止并发 clean/IDE 重建;清理历史 worktree 释放 ≥10GB | P1 | 待评估 |
+
+---
+
+## 三、本轮阻塞与风险
+
+| 阻塞项 | 影响范围 | 阻塞类型 | 处置进展 | 需要协调 |
+|--------|----------|----------|----------|----------|
+| **B-97(本轮新增)** | 后端全量回归 | 环境 | 跑次 1:433 NoClassDefFound(产物被清空);跑次 2:50/336 卡死 11 分钟后进程消失 → 降级为定向契约 + 编译复验 | 运维/研发:跑测窗口内勿并发构建;清盘 |
+| B-65(第 11 轮) | AI 报告解析 | 研发 | 251 pytest 2 例 500 复现 | 研发实现 |
+| B-90(第 4 次) | AI 管家对话 | 研发/运维 | chat 75s 零字节;analyze 已恢复 | 注入有效凭据 + 超时熔断 |
+| B-69(第 11 轮) | 鉴权边界 | 研发 | 线上匿名 POST /api/mind/** 4 端点仍非 401 | 研发实现 |
+| B-89(第 6 轮) | admin 浏览器节点 | 运维 | 189:22/4090 仍 CLOSED → 本机降级 5/5 绿 | 放通 189 |
+| B-95(第 2 轮) | frontend 浏览器节点 | 运维 | 204:4090 仍 CLOSED → 本机降级 6/6 绿 | 放通 204 |
+| B-92 | D 盘 100%(470MB) | 环境 | `[safe-delete]` 超时;`--output` 规避 | 清理历史 worktree |
+
+---
+
+## 四、下轮工作计划
+
+| 计划项 | 预计完成时间 | 前置依赖 | 备注 |
+|--------|--------------|----------|------|
+| 基线更新至 `957cac4e7` 并复跑 | 下轮 | 工作区无并发构建 | 含 S-cfc-118/123/126/127 四个实现 |
+| 后端全量(B-97 解除后) | 下轮 | 磁盘 ≥2GB + 无并发构建 | 恢复 G5 全量证据 |
+| diet 32 红 + Guhe 25 红收敛 | 下轮 | 基线更新 | 预期大幅转绿 |
+| 251 派发纳入常规 | 下轮 | 无 | 用「后台写文件 + 独立 shell 读」法 |
+
+---
+
+## 五、本轮实测明细
+
+### 5.1 浏览器自动化(用户指令:`/admin` + `/frontend`)
+
+| 目标 | 节点 | 用例 | 结果 | 说明 |
+|------|------|------|------|------|
+| `http://cfc.iwintrue.com/admin` | 189 失联(第 6 轮)→ 本机降级 | admin-live 5 | ✅ 5/5 | TC-A-U01~U05 |
+| `http://cfc.iwintrue.com/frontend` | 204 失联 → 本机串行 | frontend-live 6 | ✅ 6/6 | TC-F-U01~U06 |
+| 商城排序契约 | 本机 | shop 4 | ✅ 4/4 | 首跑 TC-S-U01 30s 超时 → curl 3×200 + 复跑 4/4 判假红 |
+| 健康鉴权契约 | 本机 | health 13 | ✅ 13/13 | 华为/小米 10 + 健康方案 3 全 401 |
+
+> 每节点仅一个浏览器任务;本机单节点串行(`workers=1`),28 例零 skip。
+
+### 5.2 langgraph(251 派发成功)
+
+| 指标 | 值 |
+|---|---|
+| collected / passed / failed | **43 / 32 / 11** |
+| 耗时 | 63.03s |
+| 节点 HEAD | `64aeee729`(cfclub) |
+| 11 红归因 | analyze 2(B-65)、auto_tag 5(B-74/B-82)、intent 4(B-82 LLM key 401) |
+
+### 5.3 回归套件
+
+| 套件 | 执行 | 通过 | 红 | skip | 通过率 | 与 R103 对比 |
+|------|------|------|----|------|--------|-------------|
+| cfc-backend 定向契约 | 132 | 107 | 25 | 0 | 81.06% | R102 103/29 → **+4 绿** |
+| cfc-frontend | 426 | 391 | 32 | 3 | 91.8% | 零漂移 |
+| cfc-web | 116 | 116 | 0 | 0 | 100% | 零漂移 |
+| 根级 tests | 23 | 7 | 16 | 0 | 30.4% | 零漂移(B-36) |
+| 浏览器 E2E | 28 | 28 | 0 | 0 | 100% | 零漂移 |
+| cfc-langgraph | 43 | 32 | 11 | 0 | 74.4% | 零漂移 |
+| **合计** | **768** | **681** | **84** | **3** | **88.7%** | — |
+
+### 5.4 SRS / 用例台账变更
+
+| 项 | 变更 | 处置 |
+|---|---|---|
+| 窗口内新增/变更 SRS | **0** | 无新建用例义务 |
+| 远端前进入库实现 | 4 个(S-cfc-118/123/126/127) | 不在本轮基线,列入下轮首件事 |
+| 用例台账 | 824 条 TC / 216 个 SC / 锚点 73 条(8.9%) | 无更新义务,G9 仍未达标 |
+
+---
+
+## 六、门禁结论
+
+**结论:⚠️ 不通过(有条件)**
+
+| 门禁 | 判据 | 实测 | 是否达标 |
+|---|---|---|---|
+| G1 用例通过率 | ≥95% | **88.7%**(768 例) | ❌ |
+| G2 红例数 | ≤20 | **84**(契约 25 + 前端 32 + 根级 16 + lg 11) | ❌ |
+| G3 前端套件 | 全绿 | 391/426(32 红) | ❌ |
+| G4 管理端 | 全绿 | 116/116 | ✅ |
+| G5 后端完整性 | 无沉默、可编译 | 编译 ✅(2319 class);定向 16/16 XML 无沉默;**全量两次失效** | ⚠️ 部分 |
+| G6 浏览器 E2E | 全通过 | **28/28** | ✅ |
+| G7 langgraph | 0 红 | 11 红 | ❌ |
+| G8 鉴权契约 | 全 401 | health 13/13 ✅;`/api/mind/**` 4 端点仍匿名可达(第 11 轮) | ⚠️ 部分 |
+| G9 SRS 可追溯 | 锚点 ≥80% | 8.9%(73/824) | ❌ |
+| G10 节点分派 | 按指令分派 | **251 派发成功 ✅**;189/204 失联 → 本机降级 | ⚠️ 部分 |
+| G11 CI 门禁 | blocking | 仍软门禁(B-40) | ❌ |
+| G12 资产入库 | 新资产已入库 | 无新增用例义务;派发脚本 `.tdd` 按规不入库 | ✅ |
+
+**未实测项(不计入通过)**:后端全量(B-97 环境失效,改按定向契约取证);覆盖率/变异(无 JaCoCo/PIT);性能压测;DAST/SCA(未授权联网);无障碍/多浏览器矩阵;UAT/BDD/探索性;`tests/test_chat.py`(B-84 无超时,主动排除);`tests/qna`(死资产);189/204 节点派发。
+
+**复评条件(全部满足方转「通过」)**:
+1. B-97 解决(跑测窗口无并发构建 + 磁盘 ≥2GB)→ 后端全量可复现,G5 恢复。
+2. 基线更新至 `957cac4e7+` → diet 32 红与 Guhe kb/noSupplement 8 例定向转绿。
+3. B-65/B-90 修复 → langgraph 11 红收敛 + live chat <30s 200。
+4. B-69 修复 → 4 条 `/api/mind/**` 移入 `LOGIN_REQUIRED_PATHS`,线上匿名 401。
+5. G9/G11:补 TC 锚点至 ≥80%;CI 增设 blocking job。
+
+---
+
+## 变更触发(用户规则:结果有变提交远程 + 通知研发)
+
+本轮 vs R103 存在**变化**,触发推送与通知:
+
+- **后端定向契约 132/107/25**(R102 为 103/29):Guhe 11 类全绿,红例 −4 → 结果改善,通知研发确认。
+- **langgraph 251 派发恢复**:B-91 解除,取回权威 **43/32/11**(R103 未实测、沿用 R102)→ 通道恢复,通知运维。
+- **新增 B-97**:工作区并发构建 + 磁盘 100% 导致后端全量两次失效 → 需研发/运维协调(跑测窗口勿并发 clean、清盘)。
+- 浏览器 28/28、管理端 116/116、前端 391/32 零漂移 → 不重复通知。
+
+→ 本报告 + 执行记录 + blockers + 研发交接通知 commit 并 push `origin/cfclub`;Agent Mail 仍 `not_bound`,以仓库通知 + 推送为通知载体。

+ 143 - 0
docs/tdd/test/automation-run-2026-11-09-R104.md

@@ -0,0 +1,143 @@
+# R104 自动化测试执行记录(2026-11-09 15:03~16:40)
+
+> 执行人:测试负责人(软件测试专家团 · 陆谨)
+> 基线:`cfclub @ 4cc66482b`(= `origin/cfclub`,跑前跑后本地未变)
+> 执行档:review(内网站点 + 251 派发已授权;未联网装依赖、未改生产代码)
+> 环境:Windows / JDK1.8.0_25 + IDEA 内置 Maven 3.9.9(`-o` 离线)
+
+---
+
+## 一、结论摘要
+
+| 套件 | 执行 | 通过 | 红 | skip | 通过率 | 与上轮对比 |
+|------|------|------|----|------|--------|-----------|
+| cfc-backend 定向契约(16 类) | 132 | 107 | 25 | 0 | 81.06% | R102: 132/103/29 → **+4 绿** |
+| cfc-frontend (Jest) | 426 | 391 | 32 | 3 | 91.8% | 零漂移(R103 同值) |
+| cfc-web (Jest) | 116 | 116 | 0 | 0 | 100% | 零漂移 |
+| 根级 tests (Jest) | 23 | 7 | 16 | 0 | 30.4% | 零漂移(B-36 未解) |
+| 浏览器 E2E(live) | 28 | 28 | 0 | 0 | 100% | 零漂移 |
+| cfc-langgraph @251 | 43 | 32 | 11 | 0 | 74.4% | 零漂移(R102 同值) |
+| **合计** | **768** | **681** | **84** | **3** | **88.7%** | — |
+
+**后端全量本轮两次均因环境失效**(详见第三节),故后端证据降级为「16 类定向契约 + 编译成功」,不冒充全量。
+
+---
+
+## 二、执行动作与原始数据
+
+### 2.1 后端全量(两次尝试,均判失效)
+
+**跑次 1 —— `mvn -o -B -DskipTests=false clean test`,15:05:24~15:29:31,24:07 min,BUILD FAILURE**
+
+- 表面结果:336 类 / 2711 例 / 2206 过 / 70F / **433E** / 2S = **81.37%**(剔环境 85.32%),94 红类 / 503 红例。
+- 完整性核对发现异常:`find target/classes -name "*.class" | wc -l` → **1173**,而主源码 **2115** 个;`target/classes/com/etotem/cfc/util/UserUtil.class` 不存在,对应红例报 `NoClassDefFoundError: com/etotem/cfc/util/UserUtil`。
+- 编译日志(第 20 行)明确:`Compiling 2115 source files` 且无写盘错误 → **编译期产物完整,跑测期间被外部清空/替换**(同一时刻另有 java 进程以 2GB 堆持续活动)。
+- 判定:**433 E 为环境损坏产物,不是产品缺陷**,本轮**不采信**该跑次的任何比率。
+
+**跑次 2 —— `mvn -o -B -DskipTests=false test`(不 clean),15:50~16:25**
+
+- 先归档失效报告目录:`target/surefire-reports` → `target/surefire-reports-r104invalid`。
+- 进度:15:54 起出 XML,16:11 达 50 类(合计 time=1031s),此后 **XML 数冻结在 50**。
+- 卡死点:`com.etotem.cfc.controller.GuideTeamControllerTest` 于 16:13:52 启动,日志末行为 16:14:54(`cfc-scheduler-3` DEBUG),至 16:25 **11 分钟零输出**;随后 `tasklist java.exe` 计数归 0 → 进程整体消失,无 BUILD 结论。
+- 完整性核对:卡死期间 `target/classes` 仍为 **2319** class(正常),说明第二次不是产物缺失,而是**进程被外部活动拖死/终止**。
+
+**编译复验(16:38 一次失败 → 15:49 成功)**
+
+- 15:38 `mvn -o -B -DskipTests compile` 失败:`HealthKnowledgeBaseController.java:[310,63] 找不到符号 getLowSideJudgmentPatch()`。
+- 但 `UnifiedKnowledgeBaseService.java:525` **存在**该方法,且该文件 mtime = 15:39(`git status` 却显示未修改,内容与 HEAD 一致)→ 判定为**外部进程在写入半成品/回滚瞬间被读到**的竞态。
+- 15:44~15:49 复跑同一命令:**BUILD SUCCESS,4:36 min,2319 class** → 基线 `4cc66482b` 源码可编译,前次失败非代码缺陷。
+
+### 2.2 后端定向契约(有效证据)
+
+命令:`mvn -o -B test -Dtest=<16 类逗号分隔> -DfailIfNoTests=false -Dsurefire.timeout=300`
+结果:**132 例 / 107 过 / 23F + 2E = 25 红 / 0 skip**(81.06%);16/16 类均产出 XML。
+
+| 类 | 例 | F | E | 判定 |
+|---|---|---|---|---|
+| GuheGateLowSideRedlineContractTest | 12 | 0 | 0 | GREEN |
+| GuheKbVersionSenseContractTest | 11 | 0 | 0 | GREEN |
+| GuheNoPathMapContractTest | 10 | 0 | 0 | GREEN |
+| GuheReportPersonalAssertContractTest | 9 | 0 | 0 | GREEN |
+| GuheV2RouteContractTest | 8 | 0 | 0 | GREEN |
+| GuheShellGuardContractTest | 7 | 0 | 0 | GREEN |
+| GuheGateStrainBlockContractTest | 6 | 0 | 0 | GREEN |
+| GuheKbFieldExposeContractTest | 6 | 0 | 0 | GREEN |
+| GuheLowSideAggregateContractTest | 6 | 0 | 0 | GREEN |
+| GuhePageTailCleanContractTest | 6 | 0 | 0 | GREEN |
+| GuheVersionSplitContractTest | 5 | 0 | 0 | GREEN |
+| GuheEvidenceIsolateContractTest | 12 | 0 | **2** | 10/12(2 NPE,B-88 续) |
+| GuheLowSideNoSupplementContractTest | 6 | **3** | 0 | RED(T4 未实现) |
+| GuheKbQueryLowSidePatchContractTest | 8 | **4** | 0 | RED(T1/L2-2 未实现) |
+| GuheLowSideRuleLoadContractTest | 10 | **7** | 0 | RED(T3 判据未实现) |
+| DietFoodHealthAdjustContractTest | 10 | **9** | 0 | RED(§3 A1~A5 未实现) |
+
+25 红全部为「契约声明的未实现能力键」→ **预期 RED,非回归**。其中 `guhe.kb.queryLowSidePatch`(S-cfc-123)与 `guhe.lowSide.noSupplement`(S-cfc-118)已在本轮窗口内被研发合入 `origin/cfclub`(见 2.5),**不在本轮基线**,下轮基线更新后应转绿。
+
+### 2.3 前端 / 管理端 / 根级
+
+- **cfc-frontend**:`npx jest` → 426 例 / **391 过 / 32 红 / 3 skip**,2 个 suite 失败,红例集中在 `__tests__/pages/diet/recommendation.uiRework.test.js`(如 `:428`)等 diet 重构契约 → 与 R103 **逐值零漂移**(S-cfc-127 实现已入 origin,不在本轮基线)。
+- **cfc-web**:17 suites / **116 例全绿**(332s,受并发负载影响耗时偏高)。
+- **根级 tests**:3 suites / 23 例 / 7 过 / 16 红 → 与 R101~R103 零漂移(B-36:23 例改环境门控后实质 0 执行)。
+
+### 2.4 浏览器自动化(用户指令:`/admin` + `/frontend`)
+
+命令(**必须在 `tests/` 目录内执行**,B-52):`npx playwright test -c playwright.config.live.js --output=.live-out-r104`;`workers=1` 串行。
+
+| 目标 | 用例 | 结果 | 说明 |
+|---|---|---|---|
+| `http://cfc.iwintrue.com/admin` | admin-live 5 | ✅ 5/5 | TC-A-U01~U05(登录页/滑块/未登录拦截/真实登录/核心菜单) |
+| `http://cfc.iwintrue.com/frontend` | frontend-live 6 | ✅ 6/6 | TC-F-U01~U06 游客只读链路 |
+| 商城价格排序契约 | shop 4 | ✅ 4/4(复跑) | 首跑 TC-S-U01 `POST /api/product/list` 30s 超时 → 见下 |
+| 健康鉴权契约 | health 13 | ✅ 13/13 | 华为/小米 10 + 健康方案 3 全 401(B-61 维持) |
+
+- **首跑**:14 passed / 1 failed(shop TC-S-U01,`Timeout 30000ms`)。
+- **假红三证**(B-67 纪律):① curl 直探 3 次全 200(0.32s/0.17s/0.14s);② 单 project 复跑 `4/4 passed (13.3s)`;③ 失败发生在 maven 全量 + jest 并发窗口。→ 判定**瞬时超时假红**,非回归。
+- **首跑遇 `[safe-delete] ETIMEDOUT`**:Playwright 启动时清理旧 `outputDir` 触发回收站二进制超时(D 盘仅 470MB);用 `--output=<新目录>` 规避。
+
+### 2.5 langgraph(按指令派发 192.168.16.251)
+
+- 节点探活:`251:4096` OPEN、`251:9000` OPEN;`189:22/4090` CLOSED(第 6 轮,B-89);`204:4090` CLOSED(B-95)。
+- 派发通道(B-96 方法):`POST /api/shell` 下发
+  `pkill -f 'venv/bin/python.*-m pytest'` → `nohup timeout 900 .venv/bin/python -m pytest tests -q --tb=line --ignore=tests/qna --ignore=tests/test_chat.py > /tmp/r104_pytest.log 2>&1 &`,随后由**独立 shell 读 `/tmp/r104_pytest.log`** 取回结果。
+- **结果:43 collected / 32 passed / 11 failed / 63.03s**,与 R102/R103 权威值**逐例零漂移**;251 仓库 HEAD = `64aeee729`(cfclub)。
+- 11 红分布:`test_analyze.py` 2(B-65 checkpointer 第 11 轮)、`test_auto_tag.py` 5(B-74/B-82)、`test_intent.py` 4(B-82 LLM key 401)。
+- **B-91 本轮解除**:首派主 shell 轮询 408s 仍未退出(`pgrep` 等待循环未收敛),改为独立 shell 直读日志文件后 8s 取回完整结果 → 「后台写文件 + 独立 shell 读文件」是确定性解法,不要依赖 `pgrep` 等待循环。
+
+### 2.6 线上鉴权复证(B-69 第 11 轮)
+
+- 匿名 POST:`/api/mind/alert/active` → **500「参数缺失:memberId」**、`/api/mind/alert/checkin-alerts`、`/api/mind/traditional/mirror`、`/api/mind/traditional/compatibility` → 均**非 401**(放行到控制器)。
+- 对照(证明拦截器在听):`/api/huawei-health/status` → **401**、`/api/health/plan/list` → **401**、`/api/xiaomi-health/status` → **401**。
+- **口径修正(本轮新增方法论)**:对照组必须用 **POST** 探测——统一 `@PostMapping` 平台对 GET 返回 HTTP 200 包裹 `{"code":405}`,本轮首测用 GET 得到「huawei-health=200」的假信号,几乎误判拦截器整体失效。
+
+### 2.7 251 live 探测(B-90 第 4 次)
+
+- `/api/v1/chat` → **0 字节挂起 75s(http=000)**(第 4 次复现);
+- `/api/v1/analyze` → **200 / 21.5s / 658B**(**首次恢复有响应**,此前多轮 90~100s 零字节);
+- `/health` → 200 / 4ms。
+- 定性:LLM 链路**部分恢复**(analyze 通、chat 仍挂),仍缺超时/熔断(B-84 同源)。
+
+---
+
+## 三、本轮环境失效根因(新增 B-97)
+
+| 证据 | 观测 |
+|---|---|
+| 编译产物被清空 | 跑次 1 期间 2115 源 → 2319 class 正常编译,跑后仅剩 1173 class |
+| 源文件被瞬时改写 | `UnifiedKnowledgeBaseService.java` mtime 15:39 但内容 == HEAD;同时刻 `HealthKnowledgeBaseController:310` 报找不到该方法 |
+| 外部 java 进程反复重生 | 15:33 / 16:17 / 16:24 / 16:25 多次出现新 java 进程(2GB 级堆),16:26 后归 0 |
+| 磁盘耗尽 | `D:` 294G 已用 293G,可用 **470~755MB(100%)**;`[safe-delete]` 回收站二进制超时 |
+| 进程整体消失 | 跑次 2 在 50/336 类处日志冻结 11 分钟后 java 计数归 0 |
+
+→ 结论:**本机工作区在跑测窗口内存在并发构建/写入活动,且磁盘已满**,后端全量在当前条件下不可稳定复现。测试侧处置:改跑定向契约 + 编译复验;并登记 B-97 交运维/研发协调。
+
+---
+
+## 四、变更触发(用户规则)
+
+| 项 | 变化 | 处置 |
+|---|---|---|
+| SRS / 用例台账 | 窗口 `7a677c4c7..HEAD` **零变更**;203 份 specs 未动 | 无新增用例义务 |
+| 远端前进 8 提交 | 含 `957cac4e7` S-cfc-118、`1bad02ec1` S-cfc-127、`0c8f1b8ea` S-cfc-123、`7366733e0` S-cfc-126(4 个实现) | 本轮基线不含;已列入下轮首件事 |
+| 后端红例 29→25 | 定向契约 +4 绿(Guhe 11 类全绿) | 结果有变化 → 提交 + 通知 |
+| langgraph 派发恢复 | B-91 解除,取回权威 43/32/11 | 结果有变化 → 通知 |
+| 浏览器 / 管理端 / 前端 | 零漂移 | 不重复通知 |

+ 12 - 0
docs/tdd/test/blockers.md

@@ -184,3 +184,15 @@
 | B-91-Update(第 103 轮 · 复发) | langgraph pytest 251 派发(shell 通道)| 环境/测试 | **复发(第 103 轮实测)**。`251:4096` opencode Basic Auth 返回 200(v2.0.29,pid 113249),建会话成功;经 `/api/session/{id}/shell` 派发 `pytest tests --ignore=tests/qna --ignore=tests/test_chat.py -q`,**两次均中途 `fetch failed`**(会话 `ses_e40f8bddeffehEMhzQ4moiy7sH` / `ses_e40f1c967ffeapp7DBNRhq8tFe`),未取得 stdout。与 B-90 同源(251 LLM 挂起拖垮 opencode 会话)。**降级**:本地 venv 跑非 LLM 子集 → 31 passed / 1 环境失败(chromadb,B-54)in 100.89s;11 个 LLM 依赖测试本地挂起无法测 → **本轮 langgraph 未实测,沿用 R102 权威 43/32/11**。闭环判据:运维注入 251 有效 LLM 凭据 + 251 加 pytest 进程超时巡检,复派应可取回结果 | 测试负责人(第 103 轮实测登记) | 2026-11-09 | 待处理(P1,251 派发复发) |
 | B-65-Update(第 103 轮 · 连续第 10 轮) | langgraph `/api/v1/analyze` checkpointer 缺 thread_id | 研发 | **连续第 10 轮未修(第 103 轮)**。本轮 251 派发未取回结果,沿用 R102 证据:`test_analyze.py` 2 例 500(`ValueError: Checkpointer requires ... thread_id`)。源码未变(`analysis_graph.py:96 MemorySaver()`、`analyze.py:35 ainvoke` 无 config)。闭环判据不变 | 测试负责人(第 103 轮确认登记) | 2026-11-09 | 待处理(P0,连续第 10 轮) |
 | B-69-Update(第 103 轮 · 连续第 10 轮) | 4 个 `/api/mind/**` 位于公开白名单 | 研发 | **连续第 10 轮未修(第 103 轮)**。本轮未定向复跑;R102 线上匿名 POST 实测 4 端点全 200 证据仍有效。闭环判据不变:4 条移入 `LOGIN_REQUIRED_PATHS` → 线上全 401 | 测试负责人(第 103 轮确认登记) | 2026-11-09 | 待处理(P1,连续第 10 轮) |
+
+<!-- ===== 第 104 轮(2026-11-09 15:03~16:40)追加 ===== -->
+
+| B-97(第 104 轮新增 · 环境) | 跑测窗口内工作区被并发构建/写入 + D 盘 100% → 后端全量回归两次失效 | 运维/研发 | **P1 环境(第 104 轮实测,两次独立报废)**。① **跑次 1**(15:05~15:29,`mvn -o -B clean test`):表面 336 类/2711 例/2206 过/**433E**=81.37%,但跑后 `find target/classes -name "*.class"` 仅 **1173**(主源码 2115),`UserUtil.class` 缺失,红例报 `NoClassDefFoundError` → 编译期日志明确 `Compiling 2115 source files` 无写盘错误,故为**跑测期间产物被外部清空/替换**,该跑次数据整体作废。② **跑次 2**(15:50~16:25,不 clean):50/336 类后 `GuideTeamControllerTest` 于 16:13:52 启动、16:14:54 后**日志冻结 11 分钟**,随后 `tasklist java.exe` 计数归 0(进程整体消失),无 BUILD 结论;期间 `target/classes` 保持 2319 完整。③ **编译竞态**:15:38 `mvn compile` 报 `HealthKnowledgeBaseController:310 找不到符号 getLowSideJudgmentPatch()`,而 `UnifiedKnowledgeBaseService.java:525` 存在该方法且 mtime=15:39、`git status` 显示内容==HEAD → 外部写入半成品/回滚瞬间被读到;15:44~15:49 复跑 **BUILD SUCCESS(2319 class)**。④ 磁盘:`D:` 294G/已用 293G/**可用 470~755MB(100%)**,Playwright 启动清理触发 `[safe-delete] ETIMEDOUT`。**降级处置**:后端证据改为「16 类定向契约 132 例」+ 编译复验。**闭环判据**:跑测窗口内无并发 `mvn clean`/IDE Rebuild,且磁盘可用 ≥2GB 时,全量 `mvn -o -B clean test` 一次跑完且 `target/classes` 前后均为 2319 class | 测试负责人(第 104 轮实测登记) | 2026-11-09 16:25 | 待处理(P1,环境) |
+| B-91-Close(第 104 轮 · 解除) | langgraph pytest 251 派发「取不回结果」 | 测试(自处置) | **解除(第 104 轮实测)**。沿用 B-96 法并做两点强化,**43/32/11 于 63.03s 确定性取回**(与 R102 逐例零漂移):① 先 `pkill -f 'venv/bin/python.*-m pytest'` 清残留;② `nohup timeout 900 ... > /tmp/r104_pytest.log 2>&1 &` 后台写文件;③ **不再用 `while pgrep ... ; do sleep 5; done` 等待循环**(本轮该循环 408s 未退出,主 shell 停在 running),改为**另起一个 shell 直接 `tail /tmp/r104_pytest.log`**,8s 取回完整尾部。教训:远程 shell 的「等待完成」是不可靠抽象,**只信文件** | 测试负责人(第 104 轮自处置登记) | 2026-11-09 16:08 | 已处置(通道固化) |
+| B-65-Update(第 104 轮 · 连续第 11 轮) | langgraph `/api/v1/analyze` checkpointer 缺 thread_id | 研发 | **连续第 11 轮未修**。251 实派 pytest:`test_analyze.py::test_analyze_endpoint` 与 `::test_analyze_missing_report` 均 `assert 500 == 200`。源码未变(`analysis_graph.py:96 MemorySaver()`、`analyze.py:35 ainvoke` 无 config)。闭环判据不变 | 测试负责人(第 104 轮复现登记) | 2026-11-09 16:08 | 待处理(P0,第 11 轮) |
+| B-69-Update(第 104 轮 · 连续第 11 轮) | 4 个 `/api/mind/**` 位于公开白名单 | 研发 | **连续第 11 轮未修**。匿名 POST:`/api/mind/alert/active` → **500「参数缺失:memberId」**(已进控制器);`alert/checkin-alerts`、`traditional/mirror`、`traditional/compatibility` 均非 401。对照组(证明拦截器在听):`/api/huawei-health/status`、`/api/health/plan/list`、`/api/xiaomi-health/status` **全 401**。**口径修正**:对照组必须用 **POST**——平台统一 `@PostMapping`,GET 会得到 HTTP 200 包裹 `{"code":405}`,本轮首测用 GET 得出「huawei-health=200」的假信号,差点误判拦截器整体失效 | 测试负责人(第 104 轮线上复证) | 2026-11-09 16:20 | 待处理(P1,第 11 轮) |
+| B-90-Update(第 104 轮 · 第 4 次复证 · 部分恢复) | 251 `chat` 挂起 / `analyze` 恢复 | 研发/运维 | **部分恢复(第 4 次复证)**。`POST /api/v1/chat` → **http=000,75.02s,size=0**(仍挂起);`POST /api/v1/analyze` → **200 / 21.50s / 658B**(此前连续多轮 90~100s 零字节,**首次恢复**);`/health` → 200/4ms。定性:LLM 链路一半恢复,仍缺 timeout/熔断(B-84 同源)。闭环:注入有效凭据 + 全部 LLM/检索调用加 timeout+熔断 → live chat/analyze 各连跑 3 次 <30s 且 200 | 测试负责人(第 104 轮实测) | 2026-11-09 16:25 | 待处理(P0,第 4 次) |
+| B-89-Update(第 104 轮 · 第 6 轮失联) | `192.168.16.189` 节点失联 | 运维 | **第 6 轮失联**。`189:22`、`189:4090` TCP 均 CLOSED → admin 仍降级本机(5/5 绿)。闭环判据不变 | 测试负责人(第 104 轮探活) | 2026-11-09 15:04 | 待处理(P1,运维) |
+| B-95-Update(第 104 轮 · 第 2 轮失联) | `192.168.16.204` 节点失联 | 运维 | **第 2 轮失联**。`204:4090` TCP CLOSED → frontend 仍降级本机(6/6 绿)。闭环判据不变 | 测试负责人(第 104 轮探活) | 2026-11-09 15:04 | 待处理(P1,运维) |
+| B-92-Update(第 104 轮 · 恶化) | D 盘满导致工具链异常 | 环境 | **恶化(第 104 轮)**。可用空间 470~755MB(100%);不再只是 `git worktree` 失败,本轮 **Playwright 启动即 `[safe-delete] 操作失败: spawnSync genie-trash ETIMEDOUT`**(清理旧 outputDir 时回收站二进制超时)。规避:`--output=<全新目录>`。闭环:释放 ≥10GB | 测试负责人(第 104 轮实测) | 2026-11-09 16:00 | 待处理(P1,运维) |
+| B-88-Update(第 104 轮 · 第 3 次) | `GuheEvidenceIsolateContractTest` 2 例 NPE | 研发/测试 | **仍有 2 NPE(第 3 次)**。定向复跑 **12 例 10 绿 / 2 E**:`tagEvidence_unknownOrBlank_markedUnverified:159->call:267`、`canEnterRecommendationBasis_unverified_false:175->callBoolean:284->call:267`(反射入口 `:267`)。与 R102 同点位、同例数 → 反射目标 bean 注册/方法签名仍需核 | 测试负责人(第 104 轮复验) | 2026-11-09 16:32 | 更新(10/12 绿,剩 2 NPE) |

+ 42 - 0
docs/tdd/研发交接通知-2026-11-09-第104轮.md

@@ -0,0 +1,42 @@
+# 研发交接通知 · 第 104 轮(2026-11-09 15:03~16:40)
+
+> 来源:测试负责人(软件测试专家团 · 陆谨)|基线 `cfclub @ 4cc66482b`
+> 详情:`docs/tdd/orchestration/report-test-2026-11-09-R104.md`|执行记录:`docs/tdd/test/automation-run-2026-11-09-R104.md`
+
+## 一、需要研发处理的 P0(连续多轮未修)
+
+| 编号 | 轮次 | 现象 | 证据 | 建议修法 |
+|---|---|---|---|---|
+| **B-65** | 第 **11** 轮 | langgraph `/api/v1/analyze` 500(checkpointer 缺 thread_id) | 251 实派 pytest:`test_analyze.py` 2 例 `assert 500 == 200` | `analysis_graph.py:96 MemorySaver()` → 去掉,或 `analyze.py:35 ainvoke(..., config={"configurable":{"thread_id":...}})` |
+| **B-90** | 第 **4** 次 | 251 live `chat` 挂起 75s 零字节(`analyze` 本轮已恢复 200/21.5s) | `POST /api/v1/chat` http=000 size=0;`/health` 200/4ms | 全 LLM/检索调用加 `timeout` + 熔断;核对 etotem/deepseek 凭据 |
+
+## 二、P1
+
+| 编号 | 轮次 | 现象 | 证据 | 建议修法 |
+|---|---|---|---|---|
+| **B-69** | 第 **11** 轮 | 4 个 `/api/mind/**` 匿名可达 | 匿名 POST:`alert/active` → 500「参数缺失:memberId」;其余 3 个非 401。对照 `huawei-health/status`、`health/plan/list`、`xiaomi-health/status` 均 **401** | 把 `JwtInterceptor.java:79-82` 的 4 条移入 `LOGIN_REQUIRED_PATHS` |
+| **B-97(新)** | 第 1 轮 | 跑测窗口内工作区被并发构建/写入 + D 盘 100%,后端**全量回归两次失效** | ①跑次1:`target/classes` 2319→1173,433 `NoClassDefFound`;②跑次2:`GuideTeamControllerTest` 卡死 11 分钟后进程消失;③编译瞬时失败(`UnifiedKnowledgeBaseService.java` mtime 15:39 内容==HEAD) | 测试窗口内不要 `mvn clean` / IDE Rebuild;清理历史 worktree 释放 ≥10GB |
+| **B-89 / B-95** | 第 6 / 2 轮 | 189、204 节点 opencode 端口拒连 | `189:22/4090`、`204:4090` 均 CLOSED | 运维放通 |
+
+## 三、本轮结果变化(好消息)
+
+1. **Guhe 定向契约 11 类 86 例全绿**(NoPathMap / V2Route / VersionSplit / ShellGuard / PageTailClean / KbFieldExpose / KbVersionSense / GateLowSideRedline / GateStrainBlock / LowSideAggregate / ReportPersonalAssert)→ 定向契约 132 例 **107 过 / 25 红**(上轮 103/29,+4 绿)。
+2. **251 langgraph 派发通道恢复**(B-91 解除)→ 取回权威 **43/32/11(63.03s)**,与 R102 逐例零漂移。
+3. **浏览器 E2E 28/28、管理端 116/116 零漂移**;前端 391/32 零漂移。
+
+## 四、请研发确认的「已实现待复验」
+
+本轮基线 `4cc66482b` **未包含**窗口内合入 `origin/cfclub` 的 4 个实现:
+
+| 提交 | 能力键 | 声称 |
+|---|---|---|
+| `957cac4e7` | `guhe.lowSide.noSupplement` T4 | 契约 3 RED → 6/6 GREEN |
+| `0c8f1b8ea` | `guhe.kb.queryLowSidePatch` | 契约 8/8 绿 |
+| `1bad02ec1` | `diet.recommendation.uiRework` | 前端 diet 重构 |
+| `7366733e0` | `diet.food.healthAdjustUi` | 健康问卷提示条 |
+
+→ 下轮测试将更新基线到 `957cac4e7+` 后定向复跑:Guhe 25 红中的 **7 例**(noSupplement 3 + queryLowSidePatch 4)与前端 **32 红**预期转绿。**请研发勿在测试窗口内 `mvn clean`**(本轮已因此报废两次全量)。
+
+---
+
+*本通知随 R104 报告一并推送 `origin/cfclub`(Agent Mail 通道 not_bound,以仓库通知 + 推送为交付)。*