Преглед изворни кода

test(R204): R204 测试闭环

- 销号 B-203-1/B-203-2(研发 178297605 修复 Bean 撞名,确认 followUpMapper/dimensionScoreService 已改名)
- 持续阻断 B-203-5(P0 编译 14 处 List.of 与 java.version=1.8 冲突,后端 478 类零可执行)
- G12 派生:ARTICLE-SEARCH-2026-11-14-V1 需求变更 → tests/test-cases/2026-11-14-article-center-search.md(TC-AS-01~14,C2/C3 后端 + C4/C5/C6 前端契约缺口 B-204-1/2)
- 新增浏览器节点 204(D:\cfc,B-204-3),frontend-mobile 6/6
- 门禁:不通过(G4 编译/G5 后端零 XML/G7 langgraph 32-43)
- 汇报:docs/tdd/orchestration/report-test-2026-11-14-R204.md
E2E Test Bot пре 1 дан
родитељ
комит
9ecbc0ac9d

+ 40 - 0
docs/tdd/automation-run-2026-11-14-R204.md

@@ -0,0 +1,40 @@
+# 自动化闭环运行记录 R204 · 2026-11-14 23:50~00:40
+
+> 测试负责人(软件测试专家团)|review 档(离线 + 内网浏览器 E2E + 远程节点派发)|静默无人值守
+
+## 1. 基线 & 窗口
+
+- 基线:R203 `03f52a138` → `origin/cfclub` `931267d7c`(HTTP 通道 fetch,B-203-3 SSH 失效兜底)。
+- 窗口 16 提交:B-203-1/2 修复(178297605)、S-cfc-353 butler.escalation 实现(34613f181,已部署 SUCCESS)、S-cfc-277 越权 RED 契约(b9a956e13)、S-cfc-283 contact RED(8ea771926)、T01 数据底座(24fb6e22d)、ARTICLE-SEARCH 需求变更(8d01d0dea)、部署回执等。
+
+## 2. 派发与实测
+
+| 节点 | 任务 | 结果 | 备注 |
+|---|---|---|---|
+| 189:4090 | admin-desktop 5 例 | **5/5 EXIT=0(1.2m)** | 第 19 轮零失败 |
+| 204:4091 | frontend-mobile 6 例 | **6/6 EXIT=0(46.2s)** | **节点首跑**;首试 `C:\code\cfc` 路径错(B-204-3)→ 改 `D:\cfc` 成功 |
+| 251:4096 | langgraph pytest 43 例子集 | **32 过 / 11 红(132.53s)** | 红=analyze 2 + auto_tag 5 + intent 4(429/401 环境型,B-199-1 第 5 轮) |
+| 本机 | shop 4 / health 13 / dx 2 | 4/4、13/13、2 跳 | 浏览器合计 **28 过 + 2 跳** |
+| 本机 | cfc-web Jest | **132/132(14.1s)** | 21 套件全绿 |
+| 本机 | cfc-frontend Jest | **616/4/12(14.9s)** | 红=growthHistory RED-A7 + recommendation.viewKeyAndDelete + signature AC-R1/R2,逐例零漂移 |
+| 本机 | 根级黑盒 | **7 过 / 16 红(5.1s)** | B-36 第 85 轮,9082 未起 |
+| 本机 | 后端 test-compile | **BUILD FAILURE EXIT=1** | B-203-5 未修复(14 处 List.of,同 R203 5 文件)→ 后端 478 类不可判定 |
+
+## 3. 关键结论
+
+- ✅ **B-203-1/B-203-2 销号**:研发 `178297605` 已修 Bean 撞名(followUpMapper / dimensionScoreService 改名与默认 Bean 名一致),Spring 启动阻断解除,线上部署回滚真因闭环。
+- 🔴 **B-203-5 第 2 轮未修复**:后端仍不可测,S-cfc-353/277/283 新契约零验证。
+- ➕ **G12 派生**:ARTICLE-SEARCH 需求变更 → `tests/test-cases/2026-11-14-article-center-search.md`(14 条 TC-AS),缺口登记 B-204-1/C2-C3、B-204-2/C4-C6。
+- ➕ **B-204-3 已定位**:204 节点项目目录 `D:\cfc`(与 189 不同),修正后 frontend 6/6。
+
+## 4. 门禁
+
+**不通过**:✅G3 28/28 / G6 / G8 6-6 / G10 三节点 / G12 TC-AS 14 条 / G13 零漂移第 30 次;❌G2 31 红 + 后端不可判定 / G4 14 编译错 / G5 后端零 XML / G7 32-43 / G9 / G11 / G14;⚠G1 96.56%(仅前端面)。
+
+## 5. 交付
+
+- `docs/tdd/orchestration/report-test-2026-11-14-R204.md`
+- `docs/tdd/test/notice-2026-11-14-R204-研发通知.md`
+- `docs/tdd/test/blockers.md` R204 段
+- `tests/test-cases/2026-11-14-article-center-search.md`
+- commit + push origin/cfclub(测试结果有变化:B-203-1/2 销号、G12 派生、B-203-5 持续)

+ 243 - 0
docs/tdd/orchestration/report-test-2026-11-14-R204.md

@@ -0,0 +1,243 @@
+# 测试负责人工作汇报 R204(2026-11-14 · 自动化闭环)
+
+> 测试负责人:陆谨(软件测试专家团)|执行档:**review(离线)** + 内网浏览器 E2E + 远程节点派发|静默无人值守
+> 基线:R203 `03f52a138` → **`origin/cfclub` `931267d7c`**(窗口 16 提交:**B-203-1/B-203-2 Bean 撞名修复**、S-cfc-353 butler.escalation 实现、S-cfc-277 越权 RED 契约、S-cfc-283 contact RED 契约、T01 数据底座、**ARTICLE-SEARCH 需求变更**)
+> 本轮实跑:浏览器 **28 过 + 2 跳**(189 admin **5/5** + **204 frontend 6/6 首跑** + 本机 shop 4/4 + health 13/13 + dx 2 跳)· cfc-web **132/132** · cfc-frontend **616 过/4 红/12 跳** · 根级 **7/16** · langgraph@251 **32/43** · 后端 **编译阻断(B-203-5 未修复)**
+
+---
+
+## 1. 执行总览
+
+| 套件 | R204(本轮实测) | R203(上轮) | 漂移 |
+|---|---|---|---|
+| 后端 · 编译 | **❌ BUILD FAILURE(EXIT=1)**:14 处 `List.of`(Java 9+)同 5 文件 —— **B-203-5 未修复**,478 类测试源码零可执行 | ❌ 同 14 处 | **未修复(第 2 轮)** |
+| 后端 · Bean 撞名(B-203-1/2) | **✅ 已修复**(研发 `178297605`:followUpMapper→butlerResourceFollowUpMapper、dimensionScoreService→healthDimensionScoreService) | ❌ 阻断 Spring 启动 | **正向(销号)** |
+| 后端 · 全量执行 | **不可判定**(编译阻断);口径承袭 R203 基线 `de201830c` 428 类/3751 例/89.76% | 不可判定 | 如实标注,**不计通过** |
+| 浏览器 E2E | **28 过 + 2 跳**:189 admin **5/5** EXIT=0(1.2m)+ **204 frontend-mobile 6/6 EXIT=0(46.2s,节点首跑)** + shop 4/4(5.7s)+ health 13/13(4.1s)+ dx 2 跳 | 28 + 2 跳(fe 本机跑) | **持平**(204 承接 fe 成功) |
+| cfc-web Jest | **132/132**(21 套件,14.1s) | 132/132 | 零漂移 |
+| cfc-frontend Jest | **616 过 / 4 红 / 12 跳**(632 例/44 套,14.9s)——红 = growthHistory RED-A7 + recommendation.viewKeyAndDelete + signature.consignee AC-R1/R2 | 616/4/12 | 零漂移(逐例一致) |
+| 根级黑盒 | **7 过 / 16 红 / 23 例**(5.1s)——B-36 第 85 轮,9082 未起 | 7/16 | 零漂移 |
+| langgraph@251 | **32 过 / 11 红 / 43 例**(132.53s)——analyze 2 + auto_tag 5 + intent 4,**与 R203 红集完全一致** | 40/51(口径差 8 例 ignore qna/test_chat) | 红集一致,环境型非回归 |
+| G12 需求变更 | **ARTICLE-SEARCH-2026-11-14-V1 已派生 14 条 TC-AS**(C1~C6 契约) | TC-POG 27 条(上轮) | **新增** |
+
+**全站可测合计(剔 skip,不含后端)**:**844 例 / 815 过 = 96.56%**,红 31(fe 4 + 根级 16 + lg 11),跳 14。
+**后端不可判定口径**:HEAD 上 `mvn -o test-compile` 失败 → 后端 478 类零可执行,既不等于通过也不等于回归;B-203-5 为**唯一阻止后端门禁判定的硬阻断**。
+
+**测试结果有变化(R203→R204)**:
+- ✅ **正向**:B-203-1/B-203-2 Bean 撞名已修复(线上部署回滚真因解除);204 节点承接 frontend E2E 首跑成功(`D:\cfc` 路径,B-95 销号兑现)。
+- 🔴 **持续**:B-203-5 编译阻断第 2 轮未修复(14 处 `List.of`,后端仍不可测)——研发已收到 R203 通知但窗口内未处理。
+- ➕ **新增**:G12 ARTICLE-SEARCH 需求变更已合入 cfclub,派生 14 条 TC-AS(C2~C6 行为契约缺口已登记 B-204-1/B-204-2)。
+- 🔄 **持平**:浏览器 28/28 零失败、fe 逐例一致、根级 7/16、langgraph 11 红集一致(环境型)。
+
+---
+
+## 2. 项目画像(本轮视角)
+
+- **节点探活**:189:4090 ✅ 200|251:4096 ✅ 200|204:4091 ✅ 200(持续恢复)|9082 ❌(B-36 第 85 轮)|cfc.iwintrue.com `/admin` 302。
+- **仓库通道**:`origin` fetch 仍走 SSH 失败(B-203-3),本轮继续用 HTTP push URL 手工 fetch(`http://git.iwintrue.com/liaoxg/cfc.git`)兜底。
+- **窗口变更(03f52a138→931267d7c,16 提交)**:
+  - 修复:`178297605` **B-203-1/B-203-2 Bean 撞名**(followUpMapper / dimensionScoreService 改名,字段名=默认 Bean 名)。
+  - 实现:`34613f181` S-cfc-353 butler.escalation.handle(ButlerEscalationService +422 行、Controller、entity/mapper/迁移)——**已部署 SUCCESS(931267d7c 回执)**。
+  - 契约:`b9a956e13` S-cfc-277 assessment.appointment.create 取消越权 RED(SC-P-38)、`8ea771926` S-cfc-283 contact.card.manage RED。
+  - 需求:**`8d01d0dea` ARTICLE-SEARCH-2026-11-14-V1**(小程序知识分享页搜索功能,C1~C6 契约)。
+  - 数据:`24fb6e22d` T01 商品订单数据底座(product_reviews 迁移 475 + product_orders 超时列迁移 476)。
+- **历史审查记录**:R203 为该对象第 203 轮;**R204 为第 204 轮,非首次**。R203 遗留:B-203-5 编译阻断(本轮确认未修复)、B-203-1/2(本轮确认已修复)、B-WIP-200(第 4 轮仍在)、langgraph 环境红(第 5 轮)。
+
+---
+
+## 3. 20 类测试覆盖矩阵(三态)
+
+| # | 类 | 层次 | 状态 | 证据(本轮) |
+|---|---|---|---|---|
+| 1 | 单元测试 | 功能层次 | **部分已发现(编译阻断)** | 后端源码 478 类因 B-203-5 不可编译;cfc-web 132、fe 632 实跑 |
+| 2 | 组件测试 | 功能层次 | **已发现** | cfc-web 21 套件、fe 44 套件实跑 |
+| 3 | 集成测试 | 功能层次 | **部分已发现** | 非-Spring 域可跑(R203 基线 3751 例);Spring 层 49 类待编译打通后复验 |
+| 4 | 契约测试 | 功能层次 | **已发现** | 58 个 `*ContractTest` 入池;窗口 +2(S-cfc-277/283 RED 契约) |
+| 5 | 接口 API 测试 | 功能层次 | **部分已发现** | 线上 API 套件本轮未跑(沿用 R197 172/23/795,如实标注);E2E live 契约 28 例实跑 |
+| 6 | 冒烟测试 | 功能保障 | **已发现** | health 13/13、shop 4/4、admin 5/5、fe 6/6(204 节点) |
+| 7 | 回归测试 | 功能保障 | **已发现** | fe 逐例一致、浏览器零失败、存量红 5 类 5 例零漂移 |
+| 8 | 探索性测试 | 功能保障 | **未发现** | 无 chartered 探索性会话记录 → 缺口 |
+| 9 | 系统/端到端 | 功能保障 | **已发现** | Playwright 4 project 实跑(189+204+本机) |
+| 10 | 验收 UAT | 功能保障 | **部分已发现** | 用户场景 11 份 + 场景映射 G14 ❌ |
+| 11 | BDD 规格 | 功能保障 | **部分已发现** | 场景文档存在,无 Gherkin 执行器 → 缺口 |
+| 12 | 性能测试 | 非功能 | **未实测(未授权联网)** | execute 档;仅测试设计 |
+| 13 | 可靠性测试 | 非功能 | **未实测(未授权联网)** | 同上 |
+| 14 | 安全测试 | 非功能 | **部分已发现** | 鉴权面实测(匿名 13/13 拒绝);SAST/DAST/依赖漏洞未授权 → 缺口 |
+| 15 | 兼容性测试 | 非功能 | **未发现** | 仅 chromium |
+| 16 | 可用性测试 | 非功能 | **未发现** | 无真实任务走查 |
+| 17 | 无障碍测试 | 非功能 | **未发现** | 无 axe/WCAG 资产 |
+| 18 | 覆盖率(行/分支) | 度量与流程 | **部分已发现** | JaCoCo 本轮未开(编译阻断);引用 R197 基线 |
+| 19 | 变异测试 | 度量与流程 | **未发现** | 无 PIT/Stryker → 缺口 |
+| 20 | 全项目代码审查 | 度量与流程 | **已发现** | 本轮产出 4 条五要素(B-203-5 未闭环为核心) |
+
+---
+
+## 4. 门禁(终值)
+
+| 门禁 | 标准 | R204 实测 | 结论 |
+|---|---|---|---|
+| G1 通过率 | ≥95%(剔 skip) | **96.56%**(815/844,**不含后端**——后端不可判定) | ⚠ 条件成立(前端面)/ 全站不可判定 |
+| G2 红例数 | 0 | **31**(fe 4 + 根级 16 + lg 11)+ 后端 478 类不可判定 | ❌ |
+| G3 浏览器 | 28/28 | **28/28 + 2 跳**(189 5/5、204 fe 6/6、shop 4/4、health 13/13) | ✅ |
+| G4 编译 | 0 错 | **❌ 14 处编译错误**(B-203-5 未修复) | ❌ |
+| G5 XML 无沉默 | 逐类有 XML | **后端零 XML**(编译阻断);前端无 XML 类口径 | ❌ |
+| G6 流水线 | EXIT 符合预期 | 浏览器 4 套 EXIT=0;后端 EXIT=1(预期,含编译阻断) | ✅ |
+| G7 langgraph | 51/51 | **32/43**(11 红,环境型:429 配额 + 401 key) | ❌ |
+| G8 匿名端点 | 6/6=401 | **6/6=401**(覆盖于 health 13/13 内) | ✅ |
+| G9 锚点率 | ≥60% | **~13%**(长期缺口,G9 ❌ 承袭) | ❌ |
+| G10 节点 | 189+251 双绿 | **三节点 189 ✅ / 204 ✅ / 251 ✅**(+204 承接 fe) | ✅ |
+| G11 CI 清单 | 全绿 | 仓库无 CI 工作流(`.github/workflows` 空) | ❌ |
+| G12 SRS 合规 | 变更→用例同步 | **ARTICLE-SEARCH 已派生 14 条 TC-AS**(C1~C6 契约,缺口 B-204-1/2) | ✅ |
+| G13 存量零漂移 | 连续零漂移 | fe 逐例一致、浏览器零失败、后端存量红 5 类/5 例(第 30 次) | ✅ |
+| G14 场景映射 | ≥80% | ~64-72%(长期缺口,G14 ❌ 承袭) | ❌ |
+
+**总账:不通过(1 项 P0 编译阻断 + 3 项环境/结构红集)**(✅ 6 项 / ❌ 6 项 / ⚠ 1 项条件成立)。
+较 R203 的变化:**B-203-1/2 由「阻断」转「已销号」**(部署恢复前置消除)——但 **B-203-5 仍是唯一 P0 硬门禁**:不修它,G1/G2/G4/G5 后端侧全部无法判定,新合入的 S-cfc-353/277/283 契约测试也无法验证。
+
+---
+
+## 5. 未实测项(如实标注,不写成通过)
+
+| 项 | 原因 | 影响面 | 降级处置 |
+|---|---|---|---|
+| **后端全部套件(当前 HEAD)** | **B-203-5 未修复**:`mvn -o test-compile` FAILURE,14 处 `List.of` | 478 类零可执行(含窗口新增 S-cfc-353/277/283 相关测试) | 承袭 R203 基线 `de201830c` 数字(428 类/3751 例);修复后须全量复跑 |
+| Spring 层 49 类 | 编译阻断未打通;Bean 撞名虽已修复但无法验证 | 约 440 例不可判定 | 编译修复后全量复跑 `*ControllerTest` |
+| 线上 API 全量(990 例) | 需线上测试数据/凭据,本轮未纳入 | R197 基线 172/23/795 沿用 | 标注「沿用基线,非本轮实测」 |
+| JaCoCo 覆盖率 | 编译阻断 | G9 相关度量 | 引用 R197 基线,不声明达标 |
+| 性能/可靠性/依赖漏洞/DAST | execute 档未授权联网 | 非功能 4 类 | 仅测试设计,缺口入 §8 |
+| 兼容性/可用性/无障碍/变异 | 无资产无工具 | 4 类 | 缺口入 §8 |
+
+---
+
+## 6. 本轮新发现问题 / 阻塞(详见 `docs/tdd/test/blockers.md` R204 段)
+
+| 编号 | 级别 | 一句话 |
+|---|---|---|
+| **B-203-5** | **P0(最紧急,第 2 轮)** | 14 处 `List.of`(Java 9+)在 5 个可见性测试类未修——后端 478 类不可编译、不可测;无论研在窗口内处理 |
+| **B-204-1** | P1 | ARTICLE-SEARCH C2/C3(LIKE 语义 + keyword+tag 交集 total 口径)缺后端行为契约测试 |
+| **B-204-2** | P1 | ARTICLE-SEARCH C4/C5/C6(onSearch 重置/搜索空态/互斥重置)缺前端行为契约测试 |
+| **B-204-3** | P2 已定位 | 204 节点项目目录为 `D:\cfc`(非 189 的 `C:\code\cfc`),改名后 frontend 6/6 成功 |
+| B-203-1/2 | **P0 销号** | Bean 撞名已由研发 `178297605` 修复 —— 线上部署回滚真因解除 |
+| B-199-1 | P0 延续 | langgraph 上游 LLM 配额/key:11 红(analyze 2 + auto_tag 5 + intent 4)环境型非回归(第 5 轮) |
+| B-203-6 | P1 延续 | pre-push 闸门只跑 compile 不跑 test-compile,漏拦 Java9+(第 2 轮) |
+| B-36 | P2 延续 | 9082 未启动 → 根级 16 红(第 85 轮) |
+| B-DX-1 | P1 延续 | dx 两端点 404 → 2 跳(第 40 轮) |
+| B-WIP-200 | P1 延续 | cfc-web 3 测试资产未入库(第 4 轮) |
+
+---
+
+## 7. G12 需求变更 → 测试用例(本轮重点)
+
+**闸门判定:OPEN**(窗口新增 1 份需求变更文档 `8d01d0dea`)。
+
+| 变更源 | 派生动作 | 产物 |
+|---|---|---|
+| `docs/需求分析/2026-11-14-小程序知识分享页搜索功能需求变更.md`(ARTICLE-SEARCH-2026-11-14-V1,C1~C6 契约) | 逐条映射契约派生用例,三流齐备(正常 9 / 异常 5 / 权限 0——本变更为既有接口无新增权限面) | **`tests/test-cases/2026-11-14-article-center-search.md`:14 条 TC-AS-01~14** |
+| `docs/design/2026-11-14-article-center-search-design.md` | 与需求文档对齐,不重复派生 | 同上 |
+
+**覆盖现状核对**:
+- **C1**(空 keyword → isNull 透传):`ArticleControllerTest.list_ByKeyword` 近似覆盖 ✅
+- **C2/C3**(LIKE 命中语义 + total 真实条数 / keyword+tag 交集):**无后端行为契约** ❌ → B-204-1
+- **C4/C5/C6**(onSearch 请求体重置 / 搜索空态 vs 无筛选空态 / Tab 互斥重置):现有 `articleTagFilter.contract.test.js` 仅结构断言 `template.match(/onSearch/)`,**不驱动行为** ❌ → B-204-2
+
+**关键判断**:需求变更标称「已实现并合入 cfclub」,但前端页面虽有 `onSearch`/`onSearchBlur`/「取消」逻辑,**空态区分、互斥重置、分页重置无任何可执行断言**——不得视为已覆盖。14 条 TC-AS 状态:C1 已覆盖(近似),C2~C6 待行为契约落地后转已执行。
+
+---
+
+## 8. 覆盖缺口清单(未发现/待核实 → 闭环路径)
+
+| 缺口 | 现状 | 风险 | 建议测试设计 | 优先级 | 闭环方式 |
+|---|---|---|---|---|---|
+| 后端全量执行 | B-203-5 编译阻断第 2 轮 | 478 类回归盲区 + S-cfc-353/277/283 新契约零验证 | 修 14 处 `List.of` 后全量 478 类复跑 | **P0** | `mvn -o test-compile` EXIT=0 → 全量 surefire |
+| ARTICLE-SEARCH C2/C3 | 无行为契约 | LIKE/total 语义回归 | `ArticleSearchBehaviorContractTest`(Mockito) | P1 | 定向契约全绿 |
+| ARTICLE-SEARCH C4/C5/C6 | 仅结构断言 | 交互回退不可发现 | `article-center.search.behavior.test.js`(桩化 SFC 驱动) | P1 | jest 定向全绿 + E2E 1 例 |
+| Spring 层 49 类 | 编译阻断 + 刚修 Bean 撞名 | 启动回归盲区 | 编译打通后全量 `*ControllerTest` | P0 | 49 类 0 ERROR |
+| 探索性测试 | 无 chartered 会话 | 场景外缺陷漏检 | 60min 定向探索 | P2 | 缺陷单入 `tests/defects/` |
+| 变异/无障碍/兼容/性能 | 无工具/未授权 | 断言强度、合规、容量未知 | PIT/axe/webkit/k6 | P2 | 见 R203 §8 |
+
+---
+
+## 9. 五要素问题清单
+
+### 问题 0(P0 · 最紧急 · 第 2 轮未修复)新测试类使用 Java 9+ API,后端测试源码整体不可编译
+
+1. **问题描述**:HEAD `931267d7c` 上 `mvn -o test-compile` **仍 BUILD FAILURE**,14 处 `找不到符号:方法 of(...) 位置: 接口 java.util.List`;工程 `pom.xml` `java.version=1.8`(`maven.compiler.source/target=1.8`)。后果:后端 478 个测试类(含窗口新合入的 S-cfc-353/277/283 相关测试)**零可执行**,G1/G2/G4/G5 后端侧全部不可判定,S-cfc-353 上线无测试护栏。
+2. **测试 bug 点**(14 处,全部 `List.of`,与 R203 完全相同):
+   - `ContentRecommendProductVisibilityTest.java`(3 处)
+   - `ProductRecommendationFilterTest.java`(5 处)
+   - `ProductServiceListByDimensionVisibilityTest.java`(1 处)
+   - `ProductVisibilitySupportTest.java`(2 处)
+   - `RecommendationSearchProductVisibilityTest.java`(3 处)
+3. **最优修改方案**:`List.of(a,b)`→`Arrays.asList(a,b)`;`List.of(a)`→`Collections.singletonList(a)`;`List.of()`→`Collections.emptyList()`。**同步修 B-203-6**:pre-push 闸门改 `mvn -q -DskipTests test-compile` 前置拦截。
+4. **修改目的**:唯一恢复后端可测的前置条件;让 S-cfc-353 上线具备回归护栏,让 G1/G2/G4/G5 恢复可判定。
+5. **修改后能否闭环**:能。复测:`mvn -o test-compile` EXIT=0 → 全量 `mvn -o -B test` 收集 478 类 XML → Spring 层 49 类 0 ERROR。通过标准:全量完成后 G1≥95%(剔 skip)且 G4=0 错。
+
+### 问题 1(P1)ARTICLE-SEARCH C2/C3 后端行为契约缺失
+
+1. **问题描述**:需求变更已合入(`keyword` 对 title/summary/tags LIKE 检索),但 `keyword` 命中语义、分页 `total` 真实条数、`keyword+tag` 交集 `total` 口径无任何测试断言;现有 `ArticleControllerTest` 仅验证透传。
+2. **测试 bug 点**:`cfc-backend/src/test/java/com/etotem/cfc/integration/controller/ArticleControllerTest.java:94-106`(`list_ByKeyword` 仅断言透传);无 `ArticleSearchBehaviorContractTest`。
+3. **最优修改方案**:新增 Service 层行为契约(Mockito):C2 命中/未命中/总数 3 例 + C3 交集/空交集/非法 tag 3 例,映射 TC-AS-02~07。
+4. **修改目的**:锁定「手动分页 total 口径」防翻页失效回归;为搜索空态提供后端契约底座。
+5. **修改后能否闭环**:能。复测:`mvn -o test -Dtest=ArticleSearchBehaviorContractTest` 6/6 绿(编译打通后)。
+
+### 问题 2(P1)ARTICLE-SEARCH C4/C5/C6 前端交互行为契约缺失
+
+1. **问题描述**:`article-center/index.vue` 已有 `onSearch`/`onSearchBlur`/「取消」实现,但**无行为断言**:搜索空态与「暂无文章」不区分、搜索/标签互斥重置无契约、onSearch 请求体(page 重置/清空/noMore)无验证。
+2. **测试 bug 点**:`cfc-frontend/__tests__/pages/article-center/articleTagFilter.contract.test.js:321-323`(仅 `expect(template).toMatch(/onSearch/)` 结构断言)。
+3. **最优修改方案**:新增 `article-center.search.behavior.test.js`(既有桩化 SFC 模式):C4 3 例(请求体/page/trim/取消还原)+ C5 2 例(空态文案区分)+ C6 2 例(Tab 互斥重置),映射 TC-AS-08~14。
+4. **修改目的**:让「需求标称已实现」有可执行证据,空态/互斥交互防静默回退。
+5. **修改后能否闭环**:能。复测:`npx jest article-center.search.behavior` 7/7 绿 + 页面 E2E 1 例(关键词搜索→空态文案)绿。
+
+### 问题 3(P1)pre-push 闸门漏拦 Java9+ API(B-203-6 第 2 轮)
+
+1. **问题描述**:窗口 16 个提交中多次推送均通过 `githooks/pre-push`(闸门只跑 `mvn -q -DskipTests compile`,不编译测试源),B-203-5 连续 2 轮漏至测试侧才发现。
+2. **测试 bug 点**:`githooks/pre-push` 中 `mvn -q -DskipTests compile` 一行(缺 `test-compile`)。
+3. **最优修改方案**:改为 `mvn -q -DskipTests test-compile`(3-5s 成本),可同时拦截测试源码编译错误与 Java 版本越界。
+4. **修改目的**:把「编译门禁」从测试侧前置到推送侧,缩短缺陷发现周期。
+5. **修改后能否闭环**:能。判据:构造一个含 `List.of` 的测试推送被闸门拒绝;正常推送不受阻。
+
+### 问题 4(P1 通道)204 节点项目目录差异(B-204-3)
+
+1. **问题描述**:204:4091 恢复后按 189 的 `C:\code\cfc` 路径派发失败(目录不存在);实际项目位于 **`D:\cfc`**。
+2. **测试 bug 点**:派发脚本硬编码 `C:\code\cfc` 路径;204 节点与 189 节点目录布局不同。
+3. **最优修改方案**:`.tdd` 派发脚本按节点维护路径(189→`C:\code\cfc`,204→`D:\cfc`,251→`/sc-data/cfc`),并做 `Test-Path` 兜底探测。
+4. **修改目的**:让 204 作为正式浏览器自动化节点稳定承接任务,双节点(189/204)负载均衡策略可持续。
+5. **修改后能否闭环**:能。判据:下一轮 204 frontend 直接按 `D:\cfc` 路径一次成功。
+
+---
+
+## 10. 结论
+
+**不通过(P0 编译阻断持续 + 环境/结构红集,但 B-203-1/2 已修复为正向)**。
+
+- **阻断项(按序)**:
+  1. **B-203-5** —— 14 处 `List.of` 未修(第 2 轮)。修法 10 分钟级(纯替换),但不修则后端 478 类不可测,S-cfc-353/277/283 新合入契约无法验证,G1/G2/G4/G5 持续不可判定。
+  2. **(已消除)** B-203-1/B-203-2 Bean 撞名 —— 研发 `178297605` 已修复,Spring 启动阻断解除(待编译打通后复验),线上部署回滚真因闭环。
+- **可放行的部分**:浏览器全矩阵 28/28 零失败(204 节点首跑成功)、cfc-frontend 逐例零漂移、cfc-web 全绿、B-203-1/2 修复、G12 合规(TC-AS 14 条派生)——前端与端到端面**无回归**。
+- **不可判定的边界**:后端 HEAD 数字为「不可测」(既有 `de201830c` 基线 89.76% 仅作参考);langgraph 11 红为环境型(429/401),**非代码回归**。
+- **复评条件**:① `mvn -o test-compile` EXIT=0(B-203-5);② Spring 层 49 类 0 ERROR;③ 全量 478 类 XML 齐备;④ TC-AS C2~C6 行为契约落地(B-204-1/2)后 G12 全量转已执行。
+
+---
+
+## 附 A:R204 执行与提交证据
+
+| 项 | 证据 |
+|---|---|
+| 基线 | R203 `03f52a138` → HTTP fetch 至 `origin/cfclub` `931267d7c`(窗口 16 提交) |
+| 编译阻断 | `mvn -o test-compile` **BUILD FAILURE EXIT=1**,14 处 `List.of` 同 5 文件(R203 复验一致) |
+| B-203-1/2 修复复验 | `git show 178297605`:followUpMapper→butlerResourceFollowUpMapper、dimensionScoreService→healthDimensionScoreService |
+| 189 admin E2E | opencode shell `sh_1dac7dddd001...`:`5 passed (1.2m)` EXIT=0 |
+| 204 frontend E2E | opencode shell `sh_1dacf849d001...`:`6 passed (46.2s)` EXIT=0(路径 `D:\cfc`,首跑) |
+| 本机 E2E | shop `4 passed (5.7s)`;health `13 passed (4.1s)`;dx `2 skipped` |
+| langgraph@251 | opencode shell:`11 failed, 32 passed in 132.53s`(43 例子集,红=analyze 2+auto_tag 5+intent 4) |
+| Jest 三套 | web `132 passed`;fe `616 passed / 4 failed / 12 skipped`;root `7 passed / 16 failed` |
+| G12 派生 | `tests/test-cases/2026-11-14-article-center-search.md`(14 条 TC-AS) |
+
+## 附 B:台账刷新
+
+| 台账 | 变更 |
+|---|---|
+| `tests/test-cases/2026-11-14-article-center-search.md` | **新增**(14 条 TC-AS,G12 派生) |
+| `docs/tdd/test/blockers.md` | 追加 R204 段(B-203-1/2 销号 + B-203-5 持续 + B-204-1~3 新增 + 承袭项) |
+| `docs/tdd/orchestration/report-test-2026-11-14-R204.md` | 本文件 |
+| `docs/tdd/test/notice-2026-11-14-R204-研发通知.md` | 研发通知(P0 编译阻断未处理 + G12 契约缺口) |

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

@@ -1507,3 +1507,21 @@
 | **B-DX-1(第 39 轮)** | dx-bridge 端点 404 | 部署/研发(P1) | 两端点 404/404 → 2 跳。 | 部署/研发 | 2026-11-14 21:55 | 待处理 |
 | **B-WIP-200(第 3 轮)** | cfc-web FamilyWorkbench 测试资产未提交 | 流程 | 3 个测试文件仍在工作区 untracked(`api/familyWorkbench.api.test.js`、`views/Families.familyWorkbench.spec.js`、`views/FamilyWorkbench.contract.spec.js`)。版本库实跑 132 例 vs 工作区含在途资产口径差 1 例。**测试侧不代提交**。 | 测试(R203 实测) | 2026-11-14 21:55 | 待研发提交(P1) |
 | **R203 门禁** | 全站 4644 例(剔 skip)/ **4190 过 = 90.22%** | 测试 | **不通过(P0 阻断)**。✅G3 28/28+2 跳 / G5 432 类 XML 齐(基线 `de201830c`)/ **❌G4 编译 14 错(B-203-5)** / G6 浏览器 4 套 EXIT=0 / G8 6/6=401 / G10 189+251+204 / G12 TC-POG 27 条派生 / G13 零漂移第 29 次;❌G1 90.22% / G2 456 红(后端 425 = 契约 378 + Spring 阻断 41 + 存量 5 + 守卫 1;fe 4 + 根级 16 + lg 11)/ G7 40/51 / G9 12.9% / G11 无 CI / G14 64.2%。**变化** = 新增 P0 代码级缺陷 **B-203-5(编译阻断,后端零可执行)+ B-203-1(部署阻断)+ B-203-2**;红构成无「已实现功能被改坏」的确定性回归。 | 测试(R203 闭环) | 2026-11-14 21:55 | 已记录 |
+
+## R204 段(2026-11-14 23:50~,基线 R203 `03f52a138` / `origin/cfclub` `931267d7c`,新增)
+
+| 编号 | 关联键/对象 | 类型 | 描述与处置 | 经办 | 登记时间 | 状态 |
+|---|---|---|---|---|---|---|
+| **B-203-1(销号)** | ButlerResourceMatchService.followUpMapper 撞名 | 研发 | 研发 `178297605`(fix(butler))**已修复**:`followUpMapper`→`butlerResourceFollowUpMapper`,`HealthDataSourceBridgeService.dimensionScoreService`→`healthDimensionScoreService`(字段名与默认 Bean 名一致,同源两枚雷一并拆除)。Spring 启动阻断解除(待编译打通后全量复验 Spring 层 49 类)。 | 测试(R204 复验) | 2026-11-15 00:30 | ✅ 已修复(178297605) |
+| **B-203-2(销号)** | HealthDataSourceBridgeService.dimensionScoreService | 研发 | 同 `178297605` 修复,字段改名 `healthDimensionScoreService`。 | 测试(R204 复验) | 2026-11-15 00:30 | ✅ 已修复(178297605) |
+| **B-203-5(第 2 轮延续 · P0 最紧急)** | 商品可见性测试类 Java 9+ API | 研发 | `mvn -o test-compile` 在 HEAD `931267d7c` 仍 **BUILD FAILURE**(28 行 = 14 处 `List.of`,与 R203 同 5 文件:ContentRecommendProductVisibilityTest 3 / ProductRecommendationFilterTest 5 / ProductServiceListByDimensionVisibilityTest 1 / ProductVisibilitySupportTest 2 / RecommendationSearchProductVisibilityTest 3)。**后端 478 类测试源码仍零可执行**。**未修复**,待研发按 R203 修法(`List.of`→`Arrays.asList`/`Collections.singletonList`/`Collections.emptyList`)。 | 测试(R204 实测) | 2026-11-15 00:30 | **待研发修复(P0 阻断全部后端测试)** |
+| **B-204-1(新增 P1)** | ARTICLE-SEARCH C2/C3 后端行为契约 | 研发/测试 | 需求变更 ARTICLE-SEARCH-2026-11-14-V1(`8d01d0dea`)已合入:C1(空 keyword 透传)已有 `ArticleControllerTest.list_ByKeyword` 近似覆盖,**C2(LIKE 语义+total 真实条数)/C3(keyword+tag 交集 total 口径)缺后端行为契约**。已派生 `tests/test-cases/2026-11-14-article-center-search.md`(14 条 TC-AS),C2/C3 部分待研发实现 `ArticleSearchBehaviorContractTest`。 | 测试(R204 G12 派生) | 2026-11-15 00:30 | 待补行为契约(P1) |
+| **B-204-2(新增 P1)** | ARTICLE-SEARCH C4/C5/C6 前端交互契约 | 研发/测试 | C4(onSearch 重置 page/清空/noMore)/C5(搜索空态区分)/C6(Tab 切换互斥重置)缺前端行为断言——现有 `articleTagFilter.contract.test.js` 仅结构断言 `template.match(/onSearch/)`,不驱动行为。已派生 TC-AS-08~14。 | 测试(R204 G12 派生) | 2026-11-15 00:30 | 待补行为契约(P1) |
+| **B-204-3(新增 P2 · 通道)** | 204 节点项目路径 | 运维 | 204:4091 已恢复(B-95 销号),但项目目录为 **`D:\cfc`**(非 `C:\code\cfc` 189 布局);本轮首跑因路径错(C:\code\cfc 不存在)EXIT=1,改 `D:\cfc` 后 **frontend 6/6 EXIT=0(46.2s)** 成功。登记以固化 204 正确路径,避免下轮重踩。 | 测试(R204 实测) | 2026-11-15 00:30 | ✅ 已定位(D:\cfc) |
+| **B-199-1(第 5 轮延续)** | langgraph 上游 LLM 配额/key | 运维/研发 | pytest 43 例子集 **32 过 / 11 红**(132.53s):红 = analyze 2(500)+ auto_tag 5 + intent 4,**与 R203 红集完全一致**(429 配额 / 401 key 环境型,源码零变更非回归)。需轮换 key + 升配额;建议 LLM 依赖例加 `skipif(no_quota)`。 | 测试(R204 实派@251) | 2026-11-15 00:30 | 待轮换 key/升配额(P0) |
+| **B-56/B-55(维持)** | 189/251/204 派发通道 | 节点 | 三节点通:189 admin 5/5 EXIT=0(1.2m);204 frontend 6/6 EXIT=0(46.2s,首跑 D:\cfc 路径);251 pytest 32/43 已派。 | 测试(R204 实测) | 2026-11-15 00:30 | ✅ 通道恢复维持 |
+| **B-36(第 85 轮零漂移)** | 根级黑盒 23 例 16 红 | 测试(P2 环境) | `npx jest -c tests/jest.config.js` → 7 过 / 16 红(5.1s),全 `ECONNREFUSED 127.0.0.1:9082`(后端 9082 未起)。 | 测试 | 2026-11-15 00:30 | 待处理 |
+| **B-DX-1(第 40 轮)** | dx-bridge 端点 404 | 部署/研发(P1) | 两端点 404/404 → 2 跳。 | 部署/研发 | 2026-11-15 00:30 | 待处理 |
+| **B-WIP-200(第 4 轮)** | cfc-web FamilyWorkbench 测试资产未提交 | 流程 | 3 个测试文件仍工作区未入库(版本库 132 例 vs 工作区口径差 1 例)。**测试侧不代提交**。 | 测试(R204 实测) | 2026-11-15 00:30 | 待研发提交(P1) |
+| **B-203-6(第 2 轮 · 流程)** | pre-push 闸门漏拦 test-compile | 研发/流程 | 闸门仍只跑 `compile` 不跑 `test-compile`,B-203-5 连续 2 轮未被拦(窗口 `34613f181`/`24fb6e22d` 推送均通过闸门)。**修法**:闸门改 `mvn -q -DskipTests test-compile`。 | 测试(R204 实测) | 2026-11-15 00:30 | 待流程改进(P1) |
+| **R204 门禁** | 全站可测 844 例(剔 skip)/ **815 过 = 96.56%**;后端 478 类**不可判定**(B-203-5) | 测试 | **不通过(承袭 P0 编译阻断)**。✅G3 28/28+2 跳 / G6 浏览器 4 套 EXIT=0 / G8 6/6=401 / G10 三节点 189+204+251 / G12 ARTICLE-SEARCH 派生 14 条 TC-AS / G13 存量零漂移第 30 次;❌G1 96.56%(**不含后端**,后端不可判定)/ G2 31 红(fe 4 + 根级 16 + lg 11;**后端 425 红属 `de201830c` 基线,HEAD 不可判定**)/ G4 **14 编译错(B-203-5 未修复)** / G5 后端零 XML / G7 32/43(配额)/ G9 锚点 / G11 无 CI / G14 场景映射。**正向** = B-203-1/2 销号(Spring 启动阻断解除);**变化** = G12 新增 TC-AS 14 条(ARTICLE-SEARCH)、204 节点首跑 frontend 6/6(D:\cfc 路径)、langgraph 红集持平(11 红非回归)。 | 测试(R204 闭环) | 2026-11-15 00:30 | 已记录 |

+ 61 - 0
docs/tdd/test/notice-2026-11-14-R204-研发通知.md

@@ -0,0 +1,61 @@
+# 研发通知 R204(2026-11-14)· 🔴 P0 编译阻断第 2 轮未处理 + G12 契约缺口
+
+> 发送方:测试负责人(软件测试专家团)|对象:后端研发 + 前端研发|基线 `origin/cfclub` `931267d7c`
+> 本轮已实测:浏览器 28/28 零失败(204 节点首跑 fe 6/6)、cfc-web 132/132、fe 632 例零漂移、langgraph 11 红(环境型非回归)。
+
+---
+
+## 一、P0:后端编译阻断未修复(B-203-5,第 2 轮,**最紧急**)
+
+**现象**:`cd cfc-backend && mvn -o test-compile` → **BUILD FAILURE**,14 处 `List.of`(Java 9+,工程 `java.version=1.8`)。
+**后果**:后端 **478 个测试类全部不可执行**——窗口新合入的 S-cfc-353(butler.escalation)、S-cfc-277(越权取消)、S-cfc-283(contact)契约测试全部无法验证;G1/G2/G4/G5 后端侧持续不可判定。
+
+**14 处精确位置**(与 R203 通知完全一致,未变):
+
+| 文件 | 行号 |
+|---|---|
+| `unit/ContentRecommendProductVisibilityTest.java` | 147, 169, 174 |
+| `unit/ProductRecommendationFilterTest.java` | 161, 177, 196, 207, 223 |
+| `unit/ProductServiceListByDimensionVisibilityTest.java` | 86 |
+| `unit/ProductVisibilitySupportTest.java` | 102, 165 |
+| `unit/RecommendationSearchProductVisibilityTest.java` | 72, 86, 87 |
+
+**修法**(纯替换,零逻辑变更):`List.of(a,b)`→`Arrays.asList(a,b)`;`List.of(a)`→`Collections.singletonList(a)`;`List.of()`→`Collections.emptyList()`。预计 10 分钟。
+**验收**:`mvn -o test-compile` EXIT=0 + 上述 5 类定向测试全绿。
+
+---
+
+## 二、P1:pre-push 闸门漏拦(B-203-6,第 2 轮)
+
+`githooks/pre-push` 仍只跑 `mvn -q -DskipTests compile`(不编译测试源),B-203-5 已连续 2 轮漏至测试侧。
+**修法**:闸门改为 `mvn -q -DskipTests test-compile`(多 3-5s,拦截测试源码编译错误与 Java 版本越界)。
+
+---
+
+## 三、✅ 已确认修复(感谢,无需再处理)
+
+- **B-203-1/B-203-2 Bean 撞名**:`178297605` 修复正确(followUpMapper→butlerResourceFollowUpMapper、dimensionScoreService→healthDimensionScoreService),Spring 启动阻断解除。待 B-203-5 修复后全量复验 Spring 层 49 类。
+
+---
+
+## 四、P1:G12 新需求契约缺口(ARTICLE-SEARCH-2026-11-14-V1)
+
+需求变更已合入(`8d01d0dea`),前端 `onSearch` 与后端 LIKE 检索已存在,但**验收契约 C2~C6 无行为断言**:
+
+| 契约 | 缺口 | 建议(测试侧已派生 TC-AS-02~14,待研发配合) |
+|---|---|---|
+| C2/C3 后端 LIKE 语义 + total 口径 + keyword+tag 交集 | 无后端行为契约(现有仅透传断言) | 研发可补 `ArticleSearchBehaviorContractTest`(6 例)或由测试补,编译打通后定向复跑 |
+| C4/C5/C6 前端 onSearch 重置 / 搜索空态 / Tab 互斥重置 | 现有测试仅结构断言 `onSearch` 存在 | 测试侧将补 `article-center.search.behavior.test.js`(7 例);如前端已有实现无需改动 |
+
+**诉求**:① 确认前端空态/互斥重置已实现(如未实现,请补,测试将按 C4~C6 断言);② B-203-5 修复后上述契约测试将一并转绿闭环。
+
+---
+
+## 五、其他延续项(无需立即动作,仅供周知)
+
+- langgraph 11 红(analyze 2/auto_tag 5/intent 4):429 配额 + 401 key 环境型,**非代码回归**;需运维轮换上游 key/升配额(B-199-1 第 5 轮)。
+- dx-bridge 两端点 404 → 2 跳(B-DX-1 第 40 轮);9082 未启动 → 根级 16 红(B-36 第 85 轮);cfc-web 3 个 FamilyWorkbench 测试资产待提交(B-WIP-200 第 4 轮)。
+
+---
+
+**本轮测试结果有变化(B-203-1/2 销号 + G12 派生 + B-203-5 持续),已随 commit 入库送达。请求优先处理 B-203-5。**

+ 67 - 0
tests/test-cases/2026-11-14-article-center-search.md

@@ -0,0 +1,67 @@
+# 2026-11-14 需求变更专项用例(小程序知识分享页搜索功能)
+
+> 本文件为 **G12 需求变更→测试用例** 的派生产物,对应需求变更:
+> `docs/需求分析/2026-11-14-小程序知识分享页搜索功能需求变更.md`(ARTICLE-SEARCH-2026-11-14-V1,commit 8d01d0dea 入库)
+> 与设计正本 `docs/design/2026-11-14-article-center-search-design.md`。
+>
+> **实现状态**:前端页面 `pages/article-center/index.vue` 已含 `onSearch`/`onSearchBlur`/搜索框骨架与「取消」;
+> 后端 `ArticleController.list` → `ArticleService.getPublicList` 已支持 `keyword` 对 `title/summary/tags` 的 LIKE 检索
+> (历史能力,非本变更新增)。**本变更的验收行为契约(C1~C6)尚未全部落地为可执行断言**:
+> - C1(空 keyword → isNull + 无 like)已有 `ArticleControllerTest.list_ByKeyword`(透传)近似覆盖
+> - C2(LIKE 语义 + total 真实条数)、C3(keyword+tag 交集 total 口径)**缺后端行为契约**
+> - C4(onSearch 重置 page/清空列表/noMore)、C5(空态区分渲染)、C6(Tab 切换互斥重置)**缺前端行为契约**
+>   (现有 `articleTagFilter.contract.test.js` 仅结构断言 `template.match(/onSearch/)`,不驱动行为)
+>
+> 编号 `TC-AS-01` 起(Article Search 独立前缀),不擅动既有 TC / SC 锚点。
+> 派生策略:本变更不新增后端接口,契约锁定在「keyword 组合语义 + 前端交互」,三流齐备(正常 / `-E` 异常 / `-P` 权限)。
+
+---
+
+## 〇、覆盖总览
+
+| 契约 | 需求点 | 用例数 | 正常 | 异常 | 权限 | 自动化锚点 | 状态 |
+|---|---|---|---|---|---|---|---|
+| C1 | 空 keyword 透传 isNull | 1 | 1 | 0 | 0 | `ArticleControllerTest.list_ByKeyword`(透传近似) | 已覆盖(近似) |
+| C2 | keyword LIKE 语义 + total 真实条数 | 3 | 2 | 1 | 0 | 无 | 待建 |
+| C3 | keyword+tag 交集 + total 口径 | 3 | 2 | 1 | 0 | 无 | 待建 |
+| C4 | onSearch 请求体 + page/列表/noMore 重置 | 3 | 2 | 1 | 0 | 无 | 待建 |
+| C5 | 搜索空态 vs 无筛选空态区分 | 2 | 1 | 1 | 0 | 无 | 待建 |
+| C6 | Tab 切换互斥重置搜索 | 2 | 1 | 1 | 0 | 无 | 待建 |
+| **合计** | — | **14** | 9 | 5 | 0 | — | — |
+
+---
+
+## 一、C1/C2/C3 后端契约(keyword 组合语义)
+
+| TC 编号 | 契约 | 角色 | 优先级 | 类型 | 前置条件 | 测试步骤 | 预期结果 | 关联契约 |
+|---|---|---|---|---|---|---|---|---|
+| TC-AS-01 | C1 空 keyword 透传 | 游客/登录 | P1 | 功能 | `POST /api/articles/list` body `{page,size}` 无 keyword | 1. 调 `controller.list(body, null, null)`<br>2. mock `getPublicList` 断言第 2 参 `isNull()` | `getPublicList` 以 `keyword=null` 调用,无 like 条件,`code=200` | `ArticleControllerTest`(已近似) |
+| TC-AS-02 | C2 LIKE 命中语义 | 游客 | P1 | 功能 | 文章含 title/summary/tags 含与不含「睡眠」的合集 | 1. `keyword="睡眠"`<br>2. Service LIKE 执行 | 命中记录 title/summary/tags 至少含关键词;不含的均未命中 | `getPublicList` LIKE 语义 |
+| TC-AS-03 | C2 total 真实条数 | 游客 | P1 | 功能 | 跨页数据(total>size) | 1. `keyword` 命中 35 条<br>2. `page=1,size=10` | `total=35`(非 size 封顶),翻页可达第 4 页 | 分页 total 口径 |
+| TC-AS-04 | C2-E 无命中 | 游客 | P1 | 异常 | 关键词无任何命中 | 1. `keyword="不存在词"` | `records=[]` 且 `total=0`,`code=200` 非 5xx | 空态契约 |
+| TC-AS-05 | C3 keyword+tag 交集 | 游客 | P1 | 功能 | 标签「减脂」+ 关键词「睡眠」同时提交 | 1. `keyword="睡眠", tag="减脂"`<br>2. Service 执行 | 结果 = LIKE 命中 ∩ 内存 tag 过滤命中,`total` 反映交集真实总数 | 防手动分页语义回归 |
+| TC-AS-06 | C3 交集为空 | 游客 | P1 | 功能 | keyword 命中但 tag 过滤后为空 | 1. 同上组合构造 | `records=[]`,`total=0`(不得 `total<=size` 假翻页) | 交集 total 口径 |
+| TC-AS-07 | C3-E 非法 tag 参数 | 游客 | P1 | 异常 | `tag` 传非法值 | 1. `tag="不存在标签"` | 不 5xx,返回空或全部(按既有过滤语义),白名单不注入 | 参数鲁棒性 |
+
+---
+
+## 二、C4/C5/C6 前端交互契约(article-center/index.vue)
+
+| TC 编号 | 契约 | 角色 | 优先级 | 类型 | 前置条件 | 测试步骤 | 预期结果 | 关联契约 |
+|---|---|---|---|---|---|---|---|---|
+| TC-AS-08 | C4 onSearch 请求体重置 | 家长 | P1 | 功能 | `searchKeyword="睡眠"`,已翻到第 3 页 | 1. 调 `onSearch()`<br>2. mock `getArticleList` 断言请求参数 | 请求体含 `keyword:"睡眠"`,`page=1`,列表清空,`noMore=false` | 前端页面方法单测 |
+| TC-AS-09 | C4 关键词 trim | 家长 | P1 | 功能 | `searchKeyword="  睡眠  "` | 1. 调 `onSearch()` | 请求体 `keyword:"睡眠"`(trim 后) | trim 契约 |
+| TC-AS-10 | C4-E 关键词为空点取消 | 家长 | P1 | 异常 | `searchKeyword=""`,已搜索态 | 1. 调 `onSearch()`(取消语义) | 还原全量列表(page=1,无 keyword 条件) | 取消还原 |
+| TC-AS-11 | C5 搜索空态区分 | 家长 | P1 | 功能 | 有关键词、接口返回 `records=[] total=0` | 1. 渲染空态 | 显示「未找到相关文章」(区别于无筛选「暂无文章」) | 空态区分渲染 |
+| TC-AS-12 | C5-E 无筛选空列表 | 家长 | P1 | 异常 | 无关键词、列表为空 | 1. 渲染空态 | 显示「暂无文章」(与搜索态文案不同) | 空态区分 |
+| TC-AS-13 | C6 Tab 切换互斥重置 | 家长 | P1 | 功能 | 搜索态(keyword="睡眠"),切换 Tab | 1. 调 `onTabChange` | `searchKeyword` 与 `searchFocused` 被清空,列表回该 Tab 全量 | 搜索与标签互斥重置 |
+| TC-AS-14 | C6-E 切 Tab 后无残留搜索 | 家长 | P1 | 异常 | 切 Tab 后再搜索 | 1. 切 Tab → 重新 onSearch | 仅当前 Tab 域内检索,不残留上一 Tab 状态 | 互斥无串扰 |
+
+---
+
+## 三、缺口与闭环路径
+
+| 契约 | 现状 | 风险 | 建议测试设计 | 优先级 | 闭环方式 |
+|---|---|---|---|---|---|
+| C2/C3 后端行为 | 仅 `ArticleControllerTest.list_ByKeyword` 透传近似 | LIKE 语义与 total 口径无回归保护 | `ArticleSearchBehaviorContractTest`(Mockito Service 层,C2/C3 各 2-3 例) | P1 | 定向契约全绿 |
+| C4/C5/C6 前端行为 | 仅结构断言 `onSearch` 存在 | 空态/互斥/重置交互可静默回退 | `article-center.search.behavior.test.js`(桩化 SFC 驱动 data/methods,参照 `articleTagFilter.contract.test.js` 既有模式) | P1 | jest 定向全绿 + E2E 1 例 |