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

test(tdd): 测试负责人 第65轮 全量clean实测 231类1847例=1769绿/95.78%(+2.28pp) 红例116→74 · B-29三行Mockito修正实证(预测95.78%=实测95.78%) · 前端313/313 管理端90/90 pytest49/2/12(96.08%) · 新发现B-34(P0 问卷GenerateRequest缺prompt_template→AI问卷100%降级)/B-35(DAN解析A1A2B4仍失效)/B-36(根级23例门控0执行) · 门禁不通过(有条件)

cfc-tester 6 дней назад
Родитель
Сommit
eb2b2ea64a
2 измененных файлов с 330 добавлено и 1 удалено
  1. 326 0
      docs/tdd/test/automation-run-2026-11-07-0215.md
  2. 4 1
      docs/tdd/test/blockers.md

+ 326 - 0
docs/tdd/test/automation-run-2026-11-07-0215.md

@@ -0,0 +1,326 @@
+# 测试负责人工作汇报 · 2026-11-07 02:15(定时自动化 · 第 65 轮 · WIP 价值实测转正 + 后端 95.78%)
+
+| 项目 | 内容 |
+|------|------|
+| 汇报人 | 测试负责人(cfc-tester) |
+| 汇报周期 | 2026-11-07 00:32 ~ 2026-11-07 02:15(第 65 轮 · 全量 clean 实测 + WIP 闭环验证) |
+| 负责模块/单元 | cfc-backend(359 控制器)/ cfc-frontend / cfc-web / cfc-langgraph / tests |
+| 执行档 | **review 档(离线)** — 不联网、不装依赖、不启停服务、不改被审源码(仅测试资产自处置) |
+| 权威基线 | 隔离工作树 `D:\_wt_r0032` @ `origin/cfclub` **`78976243e`**(含第 64 轮报告),跑前跑后 SHA 未变 |
+| 主工作区状态 | `D:\cfc` HEAD `525a40b70`(落后远端 3 提交)+ **42 项未提交**;本轮**零侵入**(仅只读复制测试资产到隔离树) |
+| 环境 | JDK 1.8.0_25 + Maven 3.6.1(`-o` 离线);MySQL 127.0.0.1:3306 部分可用(B-13);Python 3.12.7 `.venv` |
+| 结论 | **不通过(有条件)** — 但本轮把上轮「预测值」转成了「实测值」,后端通过率 **93.50% → 95.78%** |
+
+> **本轮定位(一句话)**:上轮(第 62 轮)B-29 判定「WIP 只差 3 行 Mockito 修正即可让 42 例转绿、后端达 95.78%」;本轮把它**实测出来了**——3 行修正后全量 clean 跑出 **1847 例 / 1769 绿 / 95.78%**,与预测值**完全一致**;并新发现一条**生产缺陷(P0)**:LangGraph 问卷生成 100% 失败降级。
+
+---
+
+## 一、本轮工作数据汇总
+
+### 1.1 测试用例建设
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| **本轮新增测试用例数*** | **0** | 未新建用例(无 SRS/场景变更触发:`git log` 窗口内 `docs/superpowers`/`tests/user-scenarios`/`tests/test-cases` 零提交);本轮价值在「存量用例校准 + 实测转正」 |
+| **本轮验证执行测试数*** | **2301** | 后端 1847 + 小程序 313 + 管理端 90 + pytest 执行 51(根级黑盒 23 例环境门控未执行,见 1.6) |
+| **用例通过率** | **96.52%** | 2221 / 2301(后端 95.78%、小程序 100%、管理端 100%、pytest 执行口径 96.08%);若把 12 个 pytest skip 计入分母则为 **96.03%**(2221/2313) |
+
+**分模块实测结果(全部本轮本机/隔离树实跑)**:
+
+| 套件 | 用例 | 绿 | 红 | 跳过 | 通过率 | 耗时 | 对比上轮(承袭基线) |
+|------|------|----|----|------|--------|------|----------------------|
+| cfc-backend(surefire 231 类) | 1847 | **1769** | 45F/29E | 4 | **95.78%**(剔环境红 96.21%) | 43:5x(XML 单类耗时和 2628.4s) | 93.50% → **+2.28pp**,红例 116 → **74(−42)** |
+| cfc-frontend(jest 16 套件) | 313 | 313 | 0 | 0 | **100%** | 63.6s | 296 → **+17**(WIP 2 个新 spec 实测通过) |
+| cfc-web(jest 12 套件) | 90 | 90 | 0 | 0 | **100%**(连续第 9 轮) | 112.5s | 持平 |
+| tests/ 根级(jest 2 套件) | 23 | 0 | 0 | **23** | **未执行(环境门控)** | 13.2s | 上轮 11 绿/12 红 → 现默认 skip(B-36) |
+| cfc-langgraph(pytest) | 51 执行(共 63) | **49** | 2 | 12 | **96.08%** | 392.2s | 55.81% → **+40.27pp** |
+
+**★ 本轮核心突破:B-29 从预测转实测**
+
+| 项 | 第 62 轮(预测) | 本轮(实测) | 差异 |
+|----|------------------|--------------|------|
+| 后端通过率 | 95.78% | **95.78%** | **0** |
+| 后端红例 | 116 − 42 = 74 | **74** | **0** |
+| 合计通过率 | 96.37% | **96.52%**(执行口径) | +0.15pp(pytest 分母口径差异) |
+| 前端 | 313 | **313** | 0 |
+| pytest | 49 绿 | **49 绿** | 0 |
+
+→ **B-29 的「只差 3 行」判断经全量实测确认无误**,唯一修正:
+```java
+// 错(WIP 原文,编译期 "找不到符号")
+when(articleService).recordRead(eq(1L), isNull(), isNull(), eq(30)).thenReturn(new HashMap<>());
+// 对(当轮隔离树实证:改后 testCompile 232 源 0 错)
+when(articleService.recordRead(eq(1L), isNull(), isNull(), eq(30))).thenReturn(new HashMap<>());
+```
+涉及 `ArticleControllerTest.java:201 / 215 / 226` 三行(`when(mock)` 返回 `OngoingStubbing`,其上无 `recordRead`)。
+
+**静态度量(隔离树 @ `78976243e` + 测试资产)**:控制器 **359**(`*Controller.java`)/ `@RestController` **360** / `@PostMapping` **1935** / **`@GetMapping` 8 处 3 文件(仍违 AGENTS.md 统一 POST 约定)** / 测试文件 **232** / `@Test` **1838**。
+**恒等式(B-27 口径)**:`@Test 1838 − 类级@Disabled 20 + surefire 占位 3 + Σ(参数化展开−1)=26 = 1847`,**误差 0**(`test_report_metrics.py` 复算一致)。
+**完整性**:源测试类 231 = 报告类 231,**沉默 0**;`.dump` 0;XML 与 Maven 末行一致(F45/E29/S4)。
+
+### 1.2 会话与任务分发
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| **分派任务数*** | **0** | 测试角色不派发(纪律);本轮全量测试由 `run_in_background` 本机执行 |
+| **恢复智能体会话数*** | **0** | 无中断会话 |
+| **当前在用会话数** | **0** | 期末无测试侧活跃会话 |
+
+### 1.2b 各会话当前工作状态列表
+
+| 会话标签 | 会话 ID | 当前状态 | 当前任务 | 静默/空闲时长 | 工作目录 | 备注 |
+|----------|---------|----------|----------|---------------|----------|------|
+| —(测试侧本轮无会话) | — | `—` | 全量跑测由负责人本机完成 | — | 隔离树 `D:\_wt_r0032` **干净**(仅测试资产改动,未提交) | 主工作区 `D:\cfc` **不干净**(42 项 WIP,见 G11) |
+| 远端研发负责人巡检会话 | 见研发历轮报告 | `done` | 错峰闭环巡检(第 43 轮 O-7 裁决) | — | 干净 | 与测试无在途冲突 |
+
+### 1.3 问题处置
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| **新测试发现问题数*** | **3** | **B-34(P0 生产缺陷)**:LangGraph 问卷 `GenerateRequest` 缺 `prompt_template` 字段 → AI 问卷生成 100% 失败降级;**B-35(P1)**:DAN 报告解析 A1/A2/B4 仍失效(修复提交 `c611ec55d` 未覆盖);**B-36(P1 覆盖)**:根级黑盒 API 23 例改为环境门控默认 skip,执行数归零 |
+| **已解决测试相关问题数*** | **2** | **B-29 收口**(3 行 Mockito 修正实证,42 例转绿);**B-26 复现路径闭合**(同一批 WIP,testCompile 0 错) |
+| **待解决测试相关问题数** | **13** | P0:B-31(明文凭据)、B-34;P1:B-13(环境 8 例)、B-18(A 类 57)、B-35、B-36、B-30(场景锚点)、B-33(`.gitignore *.py`);P2:B-24/B-25/B-27/B-32/B-28 |
+
+### 1.4 本轮 git 提交与推送证据(真理证据)
+
+| 提交 sha | 关联任务/能力键 | 阶段 | 触及文件类型 | 目标分支 | 已推送远端 | 备注 |
+|----------|-----------------|------|--------------|----------|------------|------|
+| 本轮报告 `docs/tdd/test/automation-run-2026-11-07-0215.md` + `blockers.md` | 第 65 轮汇报 | — | 文档 | cfclub | 见推送回执 | 仅台账/报告,零研发资产 |
+| (隔离树内验证,未提交)测试资产 + 3 行修正 | B-29 | — | 测试 | — | 否 | 按纪律不代提交研发 WIP(O-5 待裁决);3 行修正已写入本报告与 B-29,可一处复用 |
+
+> 本轮无 RED/YELLOW/GREEN 阶段推进(无新能力键、无状态机变更)。
+
+### 1.5 状态机阶段分布(全局进度)
+
+| 阶段 | 键数 | 备注 |
+|------|------|------|
+| UNTRACKED | 0 | 目标池无未实现键 |
+| RED | 0 | 历史 3 个伪 RED 早已转 GREEN |
+| YELLOW | 0 | — |
+| GREEN | **5** | health.report.createReport / dan.assessment.getActiveMaterial / guide.trainingPlan.getPlanDetail / admin.auth.login / health.report.upload;`state.json` `updated_at` **2026-11-06 16:58**(连续第 8 轮未变) |
+| DONE | 0 | 部署验证未回写(`deploy_verify` 无部署会话,单机降级) |
+
+### 1.6 数据源健康度
+
+| 数据源 | 读取键数 | 是否正常 | 备注 |
+|--------|----------|----------|------|
+| 需求侧(⏳ wish) | 0 | 正常 | 无未实现键 |
+| 契约常量(contract) | **10 类 / 114 例** | 正常 | 本轮全量内实跑:**110 绿 / 4 红**(`DimensionRegistryMapContractTest` 3 + `SleepConfigTagsMechanismContractTest` 1) |
+| 测试用例引用(test_case_map) | 784 | 正常 | 12 个 TC 文档解析成功 |
+| 执行结果回填(case_results) | 231 类 / 1847 例 | 正常 | 全量 XML 回收,`silent_missing = 0` |
+
+---
+
+## 二、三层归因(74 例 / 28 类,逐例按堆栈首帧判定)
+
+| 层 | 例数 | 类数 | 含义 | 处置 |
+|----|------|------|------|------|
+| **A 测试类缺陷** | **57** | 21 | 堆栈首帧落在测试代码:桩缺、Mockito 误用、断言基线过期、夹具未跟进新增参数 | 测试侧可自处置(本轮未改,因与研发 WIP 同文件,需 O-5 裁决后批量收口) |
+| **B 生产缺陷** | **4** | 1 | 首帧落在生产类,且实现行为与规格不符 | 研发修(B-35) |
+| **C 环境/数据/前置** | **9** | 4 | `Failed to load ApplicationContext` 8 例(硬编码 127.0.0.1:3306,B-13)+ 真库列溢出 1 例 | 环境/DB 侧 |
+| **契约待裁决** | **4** | 2 | 期望 500/400 实得 200(`DimensionRegistryMapContractTest` 3、`SleepConfigTagsMechanismContractTest` 1) | 主理人裁决口径(P-2 延续) |
+
+**A 类 57 例分布(21 类)**:`CfCommissionServiceSettleTest` 8(档位查询未 stub → `awardSalesBonus` 提前 return)、`EnergySystemFlowTest` 6、`ProductOrderServiceFulfillmentMultiModeTest` 6(`setUp` `InvalidUseOfMatchers` + 桩 helper NPE)、`PlannerBindInviteFlowTest` 5(403 前置)、`FamilyJoinRequestServiceReferrerBindTest` 4(夹具 NPE)、`ArticleWorkflowTest` 3(文案「仅已驳回」→「仅已驳回或已撤回」)、`ProductOrderServiceUpdateExpressFieldTest` 3(`uploadShippingInfo` 实参 5→7,测试未跟进)、`GuideFamilyTaskControllerTest` 3、`GrowthRecordSyncFlowTest` 3、`GuideRolePermissionTest` 2、`WishControllerTest` 2、`FortuneServiceTest` 2、`ServiceRoleApproveTest` 2,其余 8 类各 1。
+
+**量化(若 A 类全修)**:`(1769+57)/1847 = 98.86%`;叠加 B 类 4 例 → **99.08%**;再修 C 类 9 例 → **99.57%**;仅剩契约 4 例待裁决。
+
+---
+
+## 三、本轮最重要新发现
+
+### 3.1 B-34(P0 生产缺陷)· AI 问卷生成 100% 失败降级
+
+| 项 | 内容 |
+|----|------|
+| 现象 | `cfc-langgraph` pytest `tests/test_graph.py::TestGraph::test_graph_valid_output` 与 `test_graph_invalid_llm_response_rejected` 均 `AttributeError: 'GenerateRequest' object has no attribute 'prompt_template'`(任务 `build_prompt`) |
+| 根因 | 提交 `c3925c97e feat(langgraph): 全部提示词迁移到Java后端可配置` 只给 `src/schemas/tongue.py:14` 的 `TongueRequest` 加了 `prompt_template`,**未给 `src/schemas/questionnaire.py:39 GenerateRequest` 加**;而 `src/graphs/questionnaire.py:39 build_prompt` 直接读 `req.prompt_template` → 每次调用必抛 `AttributeError` |
+| 影响链 | Java `AiGateway:321` 恒发送 `prompt_template` → Python 端 pydantic 静默丢弃该额外字段 → 图节点必抛 → 接口 500 → `AiGateway` `catch` 后返回 `null`(`recordFailure`)→ 调用方降级模板。**即 `/api/family/questionnaire` 的 AI 生成能力 100% 不可用,且对外表现为「静默降级」** |
+| 性质 | 生产缺陷(B 类),非测试问题;`c3925c97e` **已在 `origin/cfclub` 祖先链上**(现网同样受影响) |
+| 修复(五要素见 P-1) | `questionnaire.py` 的 `GenerateRequest` 增 `prompt_template: Optional[str] = None`(与 `TongueRequest:14` 对齐) |
+
+### 3.2 B-35(P1)· DAN 报告解析 A1/A2/B4 仍失效
+
+`DanReportParseServiceTest` 4 例红(`testParseA2_standardCoreLiteracyFormat` 姓名 `expected 俊辰 but null`、`testParseB4_regression` 仍走降级、`testParseA1_shouldFallbackToGenericPattern`、`testParseA1_shouldExtractCognitiveDimensionFromDetailPage`)。而修复提交 `c611ec55d fix(dan): 修复 A1/B4 认知维度解析失效` 声称已修 → **修复未覆盖这两种版式**。健康报告解析是核心链路(`docs/AGENTS.md` 的「健康报告 PDF 上传与解析」),建议研发按真实样本回归。
+
+### 3.3 B-36(P1 覆盖)· 根级黑盒 API 套件由「12 恒红」转为「默认 skip」
+
+WIP 把 `tests/integration/mini-games-api.spec.js` / `plan-chain.spec.js` 改为 `CFC_API_E2E=1 && CFC_API_TOKEN` 门控(原为写死 `Bearer test-token` 打真服务 → 恒 401/500),本轮实测 **23 例全部 skip、0 执行**。方向正确(消除 12 个伪红),但**覆盖归零**:必须补 `globalSetup` 自动登录 + `.env.test`,并在 CI 注入 token,否则「接口层验收」从「假红」变成「真空」。
+
+---
+
+## 四、SRS / 用户场景覆盖(含异常流)
+
+| 指标 | 数值 | 判定 |
+|------|------|------|
+| 用户场景总数 | **215**(11 个 `user-scenarios/*.md`) | — |
+| 场景被用例台账映射 | **155(72.1%)** | ⚠️ 设计层覆盖尚可 |
+| 场景被自动化资产**字面引用** | **6(2.8%)** | ❌ **自动化绑定缺失(G10)** |
+| 结构化 TC 总数 | **784** | — |
+| 其中异常流/负向 TC | **474(60.5%)** | ✅ 异常流「设计」充足 |
+| TC 编号在 349 个测试资产中出现次数 | **0 / 784** | ❌ 无法反查「哪条 TC 无自动化」(B-30) |
+
+**结论**:用户目标中的「覆盖所有 SRS 及用户场景(含异常流)」**当前不可量化达成**——异常流用例设计量充足(474/784),但资产侧无 TC 锚点、场景侧引用率 2.8%,只能给出「间接证据」:真正的异常流断言体现在后端 74 个红例与 110 个契约绿例中(如 401/403/400/5001 分支)。建议按 B-30 的三步法(约定 `@TC-*` 锚点 → 反向核对脚本 → 按角色分批补锚)推进。
+
+---
+
+## 五、20 类测试覆盖矩阵(三态)
+
+| # | 测试类型 | 状态 | 证据(本轮实测/资产) |
+|---|----------|------|------------------------|
+| 1 | 单元测试 | **已发现** | 231 测试类 / 1847 例(`src/test/java` 232 文件) |
+| 2 | 测试覆盖率 | **未发现** | pom 无 jacoco;`target/site/jacoco` 不存在 → 未实测 |
+| 3 | 变异测试 | **未发现** | pom 无 pitest → 未实测 |
+| 4 | 集成测试 | **已发现** | `com.etotem.cfc.integration.*` 多套件(`EnergySystemFlowTest`/`PlannerBindInviteFlowTest` 等) |
+| 5 | 契约测试 | **已发现** | 10 类 114 例(110 绿 / 4 红) |
+| 6 | 接口 API 测试 | **待核实** | 根级 jest 黑盒 23 例**本轮 0 执行**(门控,B-36);Playwright API 级未授权未跑 |
+| 7 | 系统/端到端 | **待核实** | Playwright 76 spec / 444 例存在,未授权联网未实测 |
+| 8 | 验收 UAT | **未发现** | 无 UAT 脚本/验收清单 |
+| 9 | BDD 规格 | **未发现** | 无 `.feature` |
+| 10 | 冒烟测试 | **已发现** | `docs/scripts/*smoke*`、`tests/*_smoke_*.cjs`(本地脚本形态) |
+| 11 | 回归测试 | **已发现** | 本轮全量 clean 即为回归基线;但无 CI 定时回归(G6) |
+| 12 | 探索性测试 | **未发现** | 无探索式测试章程/记录 |
+| 13 | 性能测试 | **未发现** | 无 k6/jmeter 脚本(仅 B-24 时延观测) |
+| 14 | 可靠性测试 | **未发现** | 无故障注入/混沌 |
+| 15 | 安全测试 | **待核实** | 静态:8 处 `@GetMapping` 违约定 + **7 处明文凭据(B-31)**;无 SAST/DAST |
+| 16 | 兼容性测试 | **待核实** | 小程序/管理端无多端矩阵证据 |
+| 17 | 可用性测试 | **未发现** | — |
+| 18 | 无障碍测试 | **未发现** | — |
+| 19 | QA 流程 | **已发现** | `.tdd/` 状态机 + `blockers.md` + 报告轮次(本轮第 65 轮) |
+| 20 | 质量指标 | **已发现** | 通过率/红例/恒等式/契约/场景四类度量(`test_report_metrics.py` 复算一致) |
+
+---
+
+## 六、测试方案与执行档(本轮)
+
+| 项 | 内容 |
+|----|------|
+| 目标 | ①全量用例实测取真值 ②上轮 B-29 预测值验证 ③新缺陷挖掘 |
+| 范围 | `cfc-backend` 全量 surefire;`cfc-frontend` / `cfc-web` / `tests` jest;`cfc-langgraph` pytest |
+| 排除 | Playwright(未授权联网 + `globalSetup` 会 reset 共享库)、覆盖率/变异/压测/SAST(无工具)、`dan/danshop`(方案外) |
+| 执行档 | **review(离线)**;`mvn test` 内含 testCompile 属运行前提 |
+| 隔离 | 独立 worktree `D:\_wt_r0032`(远端 SHA 固定),`node_modules` 用 junction 复用,临时 worktree 结束后清理 |
+| 测试资产自处置边界 | 仅修正**测试代码**的编译阻断(3 行 Mockito),不改 `src/main`、不代提交研发 WIP |
+
+---
+
+## 七、覆盖缺口清单
+
+| 编号 | 缺口类型 | 现状 | 风险 | 建议测试设计 | 优先级 | 闭环方式 |
+|------|----------|------|------|--------------|--------|----------|
+| G-1 | 用例通过率 | 95.78%(74 红) | 不可发布 | 按 A 57 → B 4 → C 9 顺序收口 | P0 | 修后全量 clean 复跑 ≥99% |
+| G-2 | 环境红 8 例 | 3 类硬编码 `127.0.0.1:3306` | 上下文类恒红,掩盖真实回归 | 测试 profile 用 H2/容器化 | P0 | 8 例转绿 |
+| G-3 | 契约红 4 例 | MapContract 3 + SleepConfigTags 1 | 契约口径未定 | 主理人裁决「unknown legacy 是否报 400」 | P1 | 裁决后统一断言 |
+| G-4 | CI 缺失 | 仅 `test-compile` + manual workflow | 无回归网,绿是瞬时绿 | 加 nightly 全量 + PR 门禁 | P0 | CI 出绿灯记录 |
+| G-5 | 场景绑定 | 2.8% 字面引用 / 0 个 TC 锚点 | SRS 覆盖不可量化 | 见 B-30 三步法 | P1 | 锚点覆盖率 ≥60% |
+| G-6 | 接口层验收 | 根级 23 例默认 skip | 覆盖归零 | `globalSetup` 自动登录取 token | P1 | 23 例可实跑且绿 |
+| G-7 | 非功能测试 | 覆盖率/变异/压测/SAST 全无 | 质量盲区 | 先接 jacoco(最低成本) | P2 | 出首份覆盖率报告 |
+| G-8 | 测试资产入库 | 21 个测试文件仍 WIP 未提交 | 一次 `git clean` 即丢(B-23 前科) | O-5 裁决后 `git add` + push | P0 | `--clean-check` 通过 |
+
+---
+
+## 八、域结论表
+
+| 审查维度 | 负责专家 | 结论 | 关键证据 |
+|----------|----------|------|----------|
+| 单元·组件级 | 苏雅 | **有条件通过** | 231 类 1847 例 95.78%;A 类 57 例仍为最大块 |
+| 集成·接口级 | 柯砚 | **不通过** | 契约 110/114;接口层 23 例 0 执行(B-36) |
+| 系统·验收级 | 白樾 | **未实测** | Playwright 76 spec 未授权未跑;无 UAT/BDD |
+| 测试保障级 | 闻朔 | **有条件通过** | 全量回归基线可用;无 CI 定时回归 |
+| 性能·可靠性 | 骆骋 | **未实测** | 无压测工具;仅 XML 耗时和 2628.4s(B-24 环境时延 +34% vs 上轮 1899.9s) |
+| 安全 | 关屿 | **不通过** | 7 处明文凭据(B-31)+ 8 处 `@GetMapping` 违 AGENTS.md;无 SAST |
+| 兼容·体验 | 阮清 | **未实测** | 无多端/无障碍证据 |
+| 流程·度量·代码 | 何序 | **不通过** | 42 项 WIP(G11)、`.gitignore *.py` 阻断工具入库(B-33)、恒等式口径已修正 |
+
+---
+
+## 九、五要素问题清单(P-1 ~ P-4)
+
+### P-1(P0)LangGraph 问卷生成 100% 失败(B-34)
+
+| 要素 | 内容 |
+|------|------|
+| ① 问题描述 | `pytest tests/test_graph.py` 2 例必红:`AttributeError: 'GenerateRequest' object has no attribute 'prompt_template'`(节点 `build_prompt`);生产链 `/api/family/questionnaire` → `AiGateway:321` → `/api/v1/questionnaire/generate` 必 500,网关捕获后返回 null → 全量降级模板 |
+| ② 测试 bug 点 | `cfc-langgraph/tests/test_graph.py:64` 与 `:82`(`GenerateRequest(member_name=..., respondent_name=..., relationship_type=...)` 构造合法,缺字段在**生产模型**);生产侧 `cfc-langgraph/src/graphs/questionnaire.py:39`;模型 `cfc-langgraph/src/schemas/questionnaire.py:39-46` |
+| ③ 最优修改方案 | 在 `GenerateRequest` 增加一行:`prompt_template: Optional[str] = Field(default=None, description="Java 后端配置的提示词模板")`(与 `src/schemas/tongue.py:14` 对齐);`build_prompt` 亦可防御性改 `getattr(req, "prompt_template", None)` |
+| ④ 修改目的 | 恢复 AI 问卷生成能力(当前 100% 降级),并让 2 例 pytest 转绿(pytest 执行口径 96.08% → 100%) |
+| ⑤ 闭环 | 复跑 `pytest tests/test_graph.py -q` → 2 例绿;`curl -X POST /api/v1/questionnaire/generate`(带 `prompt_template`)返回 200 且 `questionnaire_json` 非空;Java 侧 `AiGateway.generateQuestionnaire` 不再打 `调用失败` warn |
+
+### P-2(P0)测试资产 + 3 行 Mockito 修正未入库(B-29 收口动作)
+
+| 要素 | 内容 |
+|------|------|
+| ① 问题描述 | 21 个测试资产(11 后端 + 8 pytest + 2 前端 spec)+ 3 行 Mockito 修正仍为工作区 WIP,`git status` 显示 `M/??`;一旦 `git clean`/分支切换即丢失(B-23/B-28 前科) |
+| ② 测试 bug 点 | `cfc-backend/src/test/java/com/etotem/cfc/integration/controller/ArticleControllerTest.java:201 / :215 / :226` |
+| ③ 最优修改方案 | 三处 `when(articleService).recordRead(...)` → `when(articleService.recordRead(...))`;随后 `git add` 21 个测试文件 + 台账,commit + push `cfclub` |
+| ④ 修改目的 | 让 WIP 可编译入库,锁定 42 例转绿成果(93.50% → 95.78%) |
+| ⑤ 闭环 | `mvn -o -B test-compile` 232 源 0 错;全量 clean 复跑 1847 例 95.78%;`--clean-check` 退出码 0 |
+
+### P-3(P1)A 类 57 例批量收口
+
+| 要素 | 内容 |
+|------|------|
+| ① 问题描述 | 57 例红例堆栈首帧全在测试代码:桩缺(`CfCommissionServiceSettleTest` 8 例未 stub 档位查询 → `awardSalesBonus` 提前 return)、Mockito 误用(`ProductOrderServiceFulfillmentMultiModeTest.setUp` 3 例 `InvalidUseOfMatchers`、`DailyCheckinStreakFlowTest` 1 例 `doNothing` 用于非 void)、实参滞后(`ProductOrderServiceUpdateExpressFieldTest` 3 例 `uploadShippingInfo` 5→7 参数)、断言基线过期(`ArticleWorkflowTest` 3 例文案、`WishControllerTest` 2 例 `childId`→`memberId`/500→5001) |
+| ② 测试 bug 点 | `CfCommissionServiceSettleTest.java:239-287`;`ProductOrderServiceFulfillmentMultiModeTest.java:setUp`;`ProductOrderServiceUpdateExpressFieldTest.java:126`;`ArticleWorkflowTest.java:205/217/228`;`WishControllerTest.java:341/367` |
+| ③ 最优修改方案 | 按类逐个:补 `cfEarnRule`/档位查询 stub;matcher 与 stub 分离(`when(mock.method(any()))` 全量 matcher 化);`uploadShippingInfo` 断言补 2 参;文案断言改为「包含关键词」而非全等 |
+| ④ 修改目的 | A 类清零 → 后端 98.86%,叠加 B 类 → 99.08% |
+| ⑤ 闭环 | 逐类定向复跑(`-Dtest=XxxTest`)全绿后,跑一次全量 clean 确认零附带漂移 |
+
+### P-4(P1)根级接口层覆盖归零(B-36)
+
+| 要素 | 内容 |
+|------|------|
+| ① 问题描述 | `tests/integration/*.spec.js` 改为 `CFC_API_E2E=1 && CFC_API_TOKEN` 门控后,本轮 23 例全部 skip、0 执行;原先 12 例恒红(打真服务用假 token)已消除,但接口层验收从「假红」变成「真空」 |
+| ② 测试 bug 点 | `tests/integration/mini-games-api.spec.js:6-11`、`tests/integration/plan-chain.spec.js:21-22`(依赖 `ADMIN_PHONE`/`ADMIN_PASSWORD` 为空) |
+| ③ 最优修改方案 | 新增 `tests/.env.test`(seed 账号)+ `globalSetup` 自动登录取 token 并写入 `process.env.CFC_API_TOKEN`;CI 注入 `API_BASE_URL=http://127.0.0.1:9082` |
+| ④ 修改目的 | 让接口层 23 例可稳定实跑,恢复「SRS 接口验收」信号 |
+| ⑤ 闭环 | 本地 9082 在听时 `CFC_API_E2E=1 npm test` 23 例实跑,红例均有归因;CI 中出现绿灯记录 |
+
+---
+
+## 十、门禁结论
+
+| 门禁 | 阈值 | 实测 | 判定 |
+|------|------|------|------|
+| G1 后端用例通过率 | ≥95% | **95.78%**(剔环境 96.21%) | ✅ **首次达标**(上轮 93.50%) |
+| G2 后端红例数 | ≤20 | **74** | ❌ |
+| G3 前端用例 | 100% | **313/313** | ✅ |
+| G4 testCompile | 0 错 | **232 源 0 错** | ✅ |
+| G5 完整性 | 沉默 0 | **231/231,沉默 0,dump 0** | ✅ |
+| G6 CI 回归 | 有全量门禁 | 仅 `test-compile` + manual | ❌ |
+| G7 状态机 | 无伪 RED | 5 键全 GREEN(第 8 轮) | ✅ |
+| G8 契约红 | 0 | **4**(MapContract 3 + SleepConfigTags 1) | ❌(上轮 3 → 4,+1 为 SleepConfigTags 新暴露) |
+| G9 pytest 通过率 | ≥90% | **96.08%**(执行口径) | ✅ **首次达标**(上轮 55.81%) |
+| G10 场景绑定率 | ≥60% | **2.8%** 字面 / 72.1% 台账映射 | ❌ |
+| G11 工作目录 | 干净 | 主工作区 **42 项 WIP** | ❌ |
+| G12 测试资产入库 | 全部入库 | 21 个测试文件仍 `M/??` | ❌ |
+
+**结论:不通过(有条件通过路径已明确)**
+
+- **进步**:G1(93.50%→95.78%)与 G9(55.81%→96.08%)**双双首次达标**;红例 116→74(−42)
+- **放行条件(按成本排序)**:① 修 P-1(LangGraph 一行字段,pytest→100%);② 执行 P-2(3 行 + 入库,锁定 95.78%);③ 补 CI 全量(G6,杜绝瞬时绿);④ 批量收 P-3(A 57 例 → 98.86%);⑤ 环境红 8 例(G-2)
+- **不可放行原因**:G2(74 红)、G6(无 CI)、G11(42 项 WIP)、G12(资产未入库)四项均属「流程/环境」而非「代码」,可在 1~2 轮内闭环
+
+---
+
+## 附录 A:证据文件(本地,未提交)
+
+| 文件 | 内容 |
+|------|------|
+| `_r0032_backend.log` | 后端 `mvn -o -B clean test` 全量日志(BUILD SUCCESS,`Tests run: 1847, Failures: 45, Errors: 29, Skipped: 4`) |
+| `_r0032_compile.log` / `_r0032_compile2.log` | 修正前(3 处"找不到符号")/ 修正后(BUILD SUCCESS)testCompile 对照 |
+| `_r0032_agg.json` | 逐类聚合(231 类 / 1847 例 / 1769 绿 / 28 红类 / 74 红例 / env 8 / nonenv 66 / 耗时和 2628.4s) |
+| `_r0032_attr.json` | 逐例归因(类型 / 消息 / 首帧 / 生产帧计数) |
+| `_r0032_metrics.json` | `test_report_metrics.py` 输出(恒等式 + 场景覆盖) |
+| `_r0032_aggregate.py` / `_r0032_attr.py` | 本轮聚合/归因脚本(B-33:`.gitignore:70 *.py` 阻断入库) |
+| `D:\_wt_r0032` | 隔离工作树(测试结束后清理) |
+
+## 附录 B:与上轮(第 64 轮定向契约复验)的关系
+
+第 64 轮为**定向契约复验**(15 类 169 例 165 绿 / 4 红,97.63%),彼时未跑全量。本轮为**全量 clean 首跑(含 WIP 测试资产)**,因此「契约 4 红」与第 64 轮**完全一致**(`DimensionRegistryMapContractTest` 3 + `S-cfc-31` 1 → 本轮定位为 `SleepConfigTagsMechanismContractTest` 1 例),零新增契约红。
+
+## 附录 C:本轮方法论新增
+
+1. **「预测→实测」必须同口径复算**:B-29 预测 95.78% 与本轮实测 95.78% 完全一致,说明上轮「隔离副本代入 WIP + 只改 3 行」的推演方法本身是可复用的**低成本预演手段**——先在小副本验证「修完能到多少」,再决定是否花 40 分钟跑全量。
+2. **compile 失败也是证据**:`_r0032_compile.log` 与 `compile2.log` 的对照把「3 行」从口头判断变成可复核的因果链(改前 3 处"找不到符号" → 改后 0 错)。
+3. **归因要用「首帧 + 生产帧」双读**:单看 `message` 会把 `WantedButNotInvoked` 误判成生产缺陷;本轮 `CfCommissionServiceSettleTest` 8 例若只看消息会判 B 类(分润不发),实际首帧在 `awardSalesBonus:249` 的 `ratePercent<=0` 提前 return,根因是**测试未 stub 档位查询** → A 类。
+4. **机器负载会显著拉长跑测**:本轮同机有多个 WorkBuddy/opencode 进程,后端全量 78 分钟(上轮 42~50 分钟),且 `cfc-web` jest 112s(历史 28~45s)→ B-24 的「时延」结论须先排除本机负载再归因代码。

+ 4 - 1
docs/tdd/test/blockers.md

@@ -33,8 +33,11 @@
 | B-26 | cfc-backend 主工作区 testCompile 阻断(11 个 integration 测试文件 WIP) | 研发 | 主工作区 `mvn testCompile` 失败:`ArticleControllerTest.java:201/215/226` 三处编译错误(`recordRead` 找不到符号,位置 `OngoingStubbing<ArticleService>`)。**根因(20:20 轮细化)**:WIP 采用 `when(articleService).recordRead(eq(1L), isNull(), isNull(), eq(30)).thenReturn(new HashMap<>())`——`when(T mock)` 返回 `OngoingStubbing<T>`,其无 `recordRead` 方法,属 Mockito API 误用;主代码 `ArticleService.recordRead(Long,Long,Long,int)` 返回 `Map<String,Object>`(`ArticleService.java:409`),故正确写法为 **`when(articleService.recordRead(...)).thenReturn(...)`**(方法调用置于 `when(...)` 内)。**同时**已提交基线本身亦为 A 类装置缺陷:3 例用 `doNothing().when(...).recordRead(...)` 对非 void 方法 stubbing → `Only void methods can doNothing()`。测试侧已用独立 worktree 干净基线(`origin/cfclub` `e4ce9f80a`)旁路完成全量 231 类 1847 例 93.50%,证明**非主线回归**。**登记留痕丢失**:本条 19:10 首登后未入库,19:37 工作区文件被回滚覆盖(与 B-15/B-23 同类资产丢失),20:20 轮据实测重建。建议:① 按上述正确写法修 3 处并同批复核 `getPublicList`/`getFeatured` 8 处实参个数;② testCompile 复验 0 错后提交推送 | 测试(59/60 轮实测登记) | 2026-11-06 19:10(20:20 细化重建) | 待处理 |
 | B-27 | `@Test` 恒等式失效(引入 @ParameterizedTest 后口径未修订) | 测试 | 20:20 轮全量实测 `@Test 1838 − 20(3 类类级 @Disabled)+ 3(surefire 占位)= 1821`,但 surefire 实际执行 **1847** 例,差 **26**。根因:`cfc-backend/src/test/java/com/etotem/cfc/config/JwtInterceptorLoginRequiredPathTest.java:62` 引入 `@ParameterizedTest + @MethodSource`,该类单注解展开 **27** 例(surefire `tests=28` = 1 @Test + 27 展开)。修订后恒等式:`@Test − 类级@Disabled + 占位 + Σ(参数化展开数−1) = 执行数`(本轮 1838−20+3+26=1847,误差 0)。风险:口径不修正会把新增用例漏记/错记(B-15/B-26 同源度量漂移)。建议把计数脚本 `count_identity.py` 纳入 `docs/tdd/tools/` 并入库 | 测试(20:20 轮登记) | 2026-11-06 20:20 | 待处理 |
 | B-28 | 测试交付物跨分支丢失(第 59 轮报告 + B-26/O-5 在 cfclub 不可见) | 研发/流程 | 19:41 仓库分支由 `feature/report-upload-product-cards` 切至 `cfclub`(HEAD `df7f60af5`,merge `da2727f53`+`e205656ee`);`git merge-base --is-ancestor 963bedae7 HEAD` = **NO** → 19:12 提交的第 59 轮报告(`docs/tdd/test/automation-run-2026-11-06-1910.md`)与 B-26/O-5 台账条目**在 `cfclub` 分支不存在**(文件在磁盘上被 checkout 覆盖清除)。内容未真丢(仍在 `origin/feature/report-upload-product-cards` 祖先链上,`merge-base --is-ancestor 963bedae7 origin/feature/...` = YES),但主线不可见 → 台账审计断链。与 B-14(窗口内并发提交)/ B-15(脚本丢失)/ B-23(测试文件未入库)同族:**测试交付物没有随主线合并机制**。建议:① 主理人裁决 `git cherry-pick 963bedae7` 或合并 feature 分支;② 测试报告/台账提交统一落在 `cfclub`(主线)分支,避免分支切换即丢失;③ 跑测前记录 `git rev-parse --abbrev-ref HEAD` 与 HEAD sha,报告中固化 | 测试(20:20 轮实测登记) | 2026-11-06 20:20 | 待处理 |
-| B-29 | WIP 测试校准批次被 3 行 Mockito 误用阻断(P0) | 研发/测试 | 主工作区 39 项 WIP(11 后端测试 + 8 pytest + 2 前端 spec)**已具备大幅转绿能力**:隔离副本带入 WIP 并仅修 3 行后,11 个被改后端类 **170 例 48 红 → 6 红(−42)**,其中 Article/GuideOrder/ProductOrder/Product/GuideTeam/Payment/Family/Auth 8 类清零;pytest **24 绿 → 49 绿(执行口径 96.1%)**;前端 **296 → 313 全绿**。合计预测 **(2148+67)/2299 = 96.37%**,后端 **95.78%**(越 G1)。**唯一阻断**:`ArticleControllerTest.java:201/215/226` 三处 `when(articleService).recordRead(...)` 应为 `when(articleService.recordRead(...))`(`when(mock)` 返回 `OngoingStubbing`,无 `recordRead`;`ArticleService.recordRead` 返回 `Map`,见 `:409`)→ 修此 3 行即可编译入库。剩余 6 红:GuideFamilyTask 3(overview/reviewTask/batchReview)+ GuideRolePermission 2(reviewTask/batchReview NPE、计数 0)+ Stats 1(文案「请先创建或加入家庭」)。建议:修 3 行 → `mvn test-compile` 0 错 → `git add` 21 个测试文件 + 台账 → push → `--clean-check` 复核 | 测试(62 轮实测登记) | 2026-11-06 23:10 | 待处理 |
+| B-29 | WIP 测试校准批次被 3 行 Mockito 误用阻断(P0) | 研发/测试 | 主工作区 39 项 WIP(11 后端测试 + 8 pytest + 2 前端 spec)**已具备大幅转绿能力**:隔离副本带入 WIP 并仅修 3 行后,11 个被改后端类 **170 例 48 红 → 6 红(−42)**,其中 Article/GuideOrder/ProductOrder/Product/GuideTeam/Payment/Family/Auth 8 类清零;pytest **24 绿 → 49 绿(执行口径 96.1%)**;前端 **296 → 313 全绿**。合计预测 **(2148+67)/2299 = 96.37%**,后端 **95.78%**(越 G1)。**唯一阻断**:`ArticleControllerTest.java:201/215/226` 三处 `when(articleService).recordRead(...)` 应为 `when(articleService.recordRead(...))`(`when(mock)` 返回 `OngoingStubbing`,无 `recordRead`;`ArticleService.recordRead` 返回 `Map`,见 `:409`)→ 修此 3 行即可编译入库。剩余 6 红:GuideFamilyTask 3(overview/reviewTask/batchReview)+ GuideRolePermission 2(reviewTask/batchReview NPE、计数 0)+ Stats 1(文案「请先创建或加入家庭」)。建议:修 3 行 → `mvn test-compile` 0 错 → `git add` 21 个测试文件 + 台账 → push → `--clean-check` 复核 | 测试(62 轮实测登记) | 2026-11-06 23:10 | **已解除(65 轮实测转正,2026-11-07 02:15)**:在隔离树 `D:\_wt_r0032`@`78976243e` 代入 21 个 WIP 测试资产 + 上述 3 行修正后,`testCompile 232 源 0 错`,全量 `mvn -o -B clean test` 跑出 **1847 例 / 1769 绿 / 45F / 29E / 4S = 95.78%**(红例 116→74,−42),与 62 轮预测值**逐位一致**(95.78% / 74 红例 / 前端 313 / pytest 49 绿)。修正后写法:`when(articleService.recordRead(eq(1L), isNull(), isNull(), eq(30))).thenReturn(new HashMap<>())`(`:201/:215/:226`)。**遗留未闭环部分转入 B-36/G12**:21 个测试资产仍为工作区 WIP,未提交入库(测试角色不代提交研发 WIP,待 O-5 裁决) |
 | B-30 | 场景/用例台账与自动化资产零编号锚点(覆盖不可量化) | 测试/需求 | 实测 215 个用户场景(11 文件)、784 条 TC(异常流 474 = 60.5%),但 **TC 编号在 348 个测试资产中出现 0 次**(0/784);场景被 Playwright spec 字面引用仅 **6 个(2.8%)**,被用例台账映射 155 个(72.1%)。后果:无法回答「哪些 SRS 场景没有自动化」,历史各轮只能以「用例数/通过率」代替「需求覆盖率」。根因:`tests/test-cases/*.md` 的 `对应 e2e` 列与真实文件名脱节(如 `e2e/roles/parent/../tasks` 非合法路径),资产侧亦无 `@TC-*` 锚点约定。建议:① 约定每个自动化用例首行注明 TC 编号;② 写反向核对脚本生成「场景→TC→资产」三列缺口清单;③ 按角色分 4 批补锚点,优先 `-N` 负向 TC(异常流) | 测试(62 轮登记) | 2026-11-06 23:10 | 待处理 |
 | B-31 | `application.yml` 7 处明文凭据(安全) | 研发 | `cfc-backend/src/main/resources/application.yml` 存在 **7 处** `password/secret/api-key/appsecret` 明文赋值(本台账不复制取值),覆盖数据源口令、微信 appsecret 与第三方 key。任何具备仓库读权限者可直取测试/生产凭据;且历史提交已留在 git 历史中。建议:改 `${ENV}` 占位 + 本地 `.env`(gitignore)+ 配置中心/Secret 管理;**同时轮换已泄露凭据**;CI 加明文凭据扫描(gitleaks 规则集) | 测试(62 轮静态扫描登记) | 2026-11-06 23:10 | 待处理 |
 | B-32 | 场景/用例度量口径跨轮漂移(度量不可比) | 测试 | 本轮实测:场景 **215**、TC **784**(异常流 474);上一轮报告记「场景 244、TC 492(异常流 237)」。差异非增长(90 分钟内不可能新增 292 条 TC),而是**解析口径不同**(是否计入 `### 场景`(08/09 butler 17 条)、是否计入 `TC-*-N*` 负向编号、类型列是否含「权限」判异常)。与 B-15/B-27 同族:**度量脚本未入库、口径未固化** → 跨轮数字不可相减。建议:把 `_r2135_scene.py` 等脚本收进 `docs/tdd/tools/` 并入库,报告固定写「口径定义 + 脚本版本」,禁止手算 | 测试(62 轮登记) | 2026-11-06 23:10 | **部分解除(62 轮自处置)**:度量脚本已落地 `docs/tdd/tools/test_report_metrics.py`(聚合 + 逐例归因 + 场景覆盖 + 恒等式,纯只读、带 CLI 参数),本轮数字用该脚本复算完全一致(231 类/1847 例/1727 绿/93.50%/36 红类/116 红例;场景 215、TC 784、异常流 474、TC 锚点 0/784;恒等式 1838−20+3=1821,参数化净增 26 → 1847)。**但脚本无法入库**:被 `.gitignore:70 *.py` 全局忽略 → 见 B-33,需放行规则后才算真闭环 |
 | B-33 | `.gitignore:70 *.py` 全局忽略 Python 文件 —— 度量脚本「写了就丢」的真正根因 | 研发/流程 | 62 轮把度量工具落到 `docs/tdd/tools/test_report_metrics.py` 后 `git add` 被拒:`git check-ignore -v` → **`.gitignore:70:*.py`**。这解释了 B-15(`discover_tests.py`/`test_inventory.py` 全仓丢失、历史度量不可复现)与 B-32(口径跨轮漂移)为何反复发生:**任何 Python 度量/校验脚本在本仓库都不可能入库**,只存在于某个工作区,分支切换或清理即消失。影响面:度量脚本、数据 seed 脚本、报告解析脚本(`docs/scripts/fingerprint_engine.py` 等)同受此规则约束(后者是否被例外放行需核实)。建议:把规则细化为 `/*.py`(仅忽略仓库根临时脚本)或追加例外 `!docs/tdd/tools/*.py`、`!docs/scripts/**/*.py`,再由研发提交一次;测试侧脚本需随之入库。**注意:`.gitignore` 属研发所有,测试角色不代改** | 测试(62 轮实测登记) | 2026-11-06 23:10 | 待处理 |
+| B-34 | LangGraph 问卷生成 100% 失败降级(`GenerateRequest` 缺 `prompt_template`) | 研发 | **P0 生产缺陷**。`c3925c97e feat(langgraph): 全部提示词迁移到Java后端可配置` 只给 `cfc-langgraph/src/schemas/tongue.py:14` 的 `TongueRequest` 加了 `prompt_template`,**未给 `src/schemas/questionnaire.py:39 GenerateRequest` 加**;而 `src/graphs/questionnaire.py:39 build_prompt` 直接读 `req.prompt_template` → 每次调用必抛 `AttributeError`。链路:Java `AiGateway:321` 恒发送 `prompt_template` → pydantic 静默丢弃额外字段 → 图节点必抛 → 接口 500 → `AiGateway` catch 后返回 null → 调用方**静默降级模板**。即 `/api/family/questionnaire` 的 AI 生成能力 100% 不可用。`c3925c97e` 已在 `origin/cfclub` 祖先链 → 现网同样受影响。65 轮 pytest 实测 2 例必红即此因。修复:`GenerateRequest` 增 `prompt_template: Optional[str] = Field(default=None, ...)`(与 `TongueRequest:14` 对齐);`build_prompt` 可加 `getattr` 防御。闭环:`pytest tests/test_graph.py` 2 例转绿 + `/api/v1/questionnaire/generate` 返回 200 且 `questionnaire_json` 非空 + `AiGateway` 不再打「调用失败」warn | 测试(65 轮实测登记) | 2026-11-07 02:15 | 待处理 |
+| B-35 | DAN 报告解析 A1/A2/B4 仍失效(修复提交未覆盖该版式) | 研发 | `DanReportParseServiceTest` 65 轮全量实测 **4 例红**:`testParseA2_standardCoreLiteracyFormat:262`(姓名 `expected 俊辰 but null`)、`testParseB4_regression:280`(仍走降级 `expected false but true`)、`testParseA1_shouldFallbackToGenericPattern`、`testParseA1_shouldExtractCognitiveDimensionFromDetailPage`(`expected not null`)。而 `c611ec55d fix(dan): 修复 A1/B4 认知维度解析失效` 声称已修 → **修复未覆盖这两种版式**(`testParseA2_regression` 同批绿、`standardCoreLiteracy` 版式红,说明是版式分支漏配)。健康报告解析为核心链路(AGENTS.md「健康报告 PDF 上传与解析」)。建议按真实样本补版式分支 + 回归样本入库。闭环:4 例转绿 + 用 3 份真实报告样本走 `/api/health/report/parse` 人工比对字段 | 测试(65 轮实测登记) | 2026-11-07 02:15 | 待处理 |
+| B-36 | 根级黑盒 API 套件由「12 恒红」转为「默认 skip」,接口层覆盖归零 | 测试/环境 | WIP 将 `tests/integration/mini-games-api.spec.js:6-11`、`plan-chain.spec.js:21-22` 改为 `CFC_API_E2E==='1' && CFC_API_TOKEN` 门控(原写死 `Bearer test-token` 打真服务 → 恒 401/500)。方向正确(消除 12 个伪红),但 65 轮实测 **23 例全部 skip、0 执行**(`Tests: 23 skipped`)→ 接口层验收从「假红」变「真空」,且 `plan-chain` 仍依赖空的 `ADMIN_PHONE/ADMIN_PASSWORD`。建议:新增 `tests/.env.test` + seed 账号,`globalSetup` 自动登录取 token 写入 `process.env.CFC_API_TOKEN`,CI 注入 `API_BASE_URL=http://127.0.0.1:9082`。闭环:本地 9082 在听时 `CFC_API_E2E=1 npm test` 23 例实跑且红例有归因;CI 出绿灯记录 | 测试(65 轮实测登记) | 2026-11-07 02:15 | 待处理 |