Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/cfclub' into cfclub

E2E Test Bot 5 dienas atpakaļ
vecāks
revīzija
9359de39a5

+ 5 - 1
.gitignore

@@ -67,10 +67,14 @@ worktrees/
 !web/business/*.png
 
 # Python
-*.py
+/*.py
 __pycache__/
 # TDD 用例脚本化生成器(产物需团队可复现,例外放行)
 !tests/scripts/scriptize_tc.py
+# 白名单:docs/tdd/tools、docs/scripts、tools 下的 Python 度量/解析脚本需入库(B-15/B-32/B-33 闭环)
+!docs/tdd/tools/
+!docs/scripts/
+!tools/
 
 # OpenCode
 .opencode/

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-b3a975111fef68060261797a1a9fdc29bc2e552f
+1d163ad98107397966cf57dcdde8de145367bee0

+ 2 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.2160",
+  "version": "1.0.2163",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.2160",
+      "version": "1.0.2163",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.2161",
+  "version": "1.0.2164",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 21 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,27 @@
 
 ---
 
+## v1.0.2164 (2026-11-07)
+
+### 文档
+- 研发负责人 错峰03 1025轮汇报 + O-12 契约缺口裁决(G-1/2/3、A-04/14/19/20/21 待主理人确认)
+
+
+## v1.0.2163 (2026-11-07)
+
+### 测试
+- 报告闭环 23 SC 三类流 e2e 证据补建 | 25 用例全绿(正常8/异常9/权限8) + 契约 JUnit 82/82 复验 | 新增 report-closedloop-contract.spec.js、CFC_API_BASE 本地复验回退、automation-run 证据文档
+
+### 文档
+- 研发负责人1 第47轮闭环巡检汇报(O-11 派发 + B-29/34/35/37 核验 + SC 15/241)
+
+
+## v1.0.2162 (2026-11-07)
+
+### 测试
+- 报告闭环 23 SC 三类流契约证据 | 82 JUnit 全绿(11类,0失败) + 8 LangGraph pytest 全绿(SC-B-04/B-11) | SC-S-09 映射 listTypeLinks(未实现端点ProviderController缺) | 基线2af4829b1已并入b3a975111
+
+
 ## v1.0.2161 (2026-11-07)
 
 ### 文档

+ 22 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.2161
+> 当前版本: v1.0.2164
 
 ## 历史版本
 
@@ -8,6 +8,27 @@
 
 ---
 
+## v1.0.2164 (2026-11-07)
+
+### 文档
+- 研发负责人 错峰03 1025轮汇报 + O-12 契约缺口裁决(G-1/2/3、A-04/14/19/20/21 待主理人确认)
+
+
+## v1.0.2163 (2026-11-07)
+
+### 测试
+- 报告闭环 23 SC 三类流 e2e 证据补建 | 25 用例全绿(正常8/异常9/权限8) + 契约 JUnit 82/82 复验 | 新增 report-closedloop-contract.spec.js、CFC_API_BASE 本地复验回退、automation-run 证据文档
+
+### 文档
+- 研发负责人1 第47轮闭环巡检汇报(O-11 派发 + B-29/34/35/37 核验 + SC 15/241)
+
+
+## v1.0.2162 (2026-11-07)
+
+### 测试
+- 报告闭环 23 SC 三类流契约证据 | 82 JUnit 全绿(11类,0失败) + 8 LangGraph pytest 全绿(SC-B-04/B-11) | SC-S-09 映射 listTypeLinks(未实现端点ProviderController缺) | 基线2af4829b1已并入b3a975111
+
+
 ## v1.0.2161 (2026-11-07)
 
 ### 文档

+ 10 - 0
docs/tdd/dev/evidence-report-closedloop-evd7-20261107.md

@@ -139,3 +139,13 @@ Tests run: 3,  Failures: 0, Errors: 0, Skipped: 0 - ReportParserProviderConnectC
 - `cfc-backend/src/test/java/com/etotem/cfc/unit/ReportParserProviderConnectContractTest.java`(SC-S-09,本次新增)
 - `cfc-langgraph/tests_contract/test_growth_report_contract.py`(SC-B-04/B-11,本次新增;置于 `tests_contract/` 避免 `tests/conftest.py` 引入 `app.main`→`faster_whisper`→`ctranslate2` 原生 DLL 依赖)
 - `docs/tdd/dev/evidence-report-closedloop-evd7-20261107.md`(本记录)
+
+## 8. EVD-7 后续补强(2026-11-07)
+
+EVD-7 在 EVD-7R 契约 JUnit 基础上补建 **API 级 e2e 三类流**,详见
+`docs/tdd/test/automation-run-evd7-report-closedloop-2026-11-07.md`:
+
+- 新增 `tests/e2e/api/report-closedloop-contract.spec.js`(25 用例:正常流 8 / 异常流 9 / 权限流 8)。
+- 执行环境:本地 `cfc-backend` @ 9082 + 测试库 `192.168.16.251:3306/zxyj`(远端 `cfc.iwintrue.com` 本窗口 DNS 不可解析)。
+- 实测结果:**e2e 25/25 通过(10.5s)**;同日复跑本批 11 类契约 JUnit → **82/82 通过**。
+- 未修改任何 `src/main` 业务实现;仅新增测试资产与证据文档。

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
docs/tdd/orchestration/pending.md


+ 169 - 0
docs/tdd/orchestration/report-dev-2026-11-07-0954.md

@@ -0,0 +1,169 @@
+# 研发负责人1 工作汇报(第 47 轮 · ce26ad68 实例)
+
+> 模板版本:v1.1(2026-11-03)|字段经 `--status` / `--inspect` / `git log` / `--changes` 实测填充,无留空占位。
+
+## 基本信息
+
+| 项目 | 内容 |
+|------|------|
+| 汇报人 | 研发负责人1(本自动化 ce26ad68 实例,第 47 轮) |
+| 汇报周期 | 2026年11月07日 09:36 ~ 09:54(第 47 轮,本实例计数;多槽位并发编号沿用主理人裁定=文件名时间戳全局唯一) |
+| 负责模块/单元范围 | 全量(scope 空) |
+
+---
+
+## 一、本轮工作数据汇总
+
+### 1.1 问题接收与处置
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 收到的测试反馈问题数 | 4 个 | B-34(LangGraph 问卷生成 100% 降级,P0)/ B-35(DAN 报告解析 A1/A2/B4 失效)/ B-37(sleep.config.tags blank-key 实现缺口,阻断该键转 GREEN)/ B-29(WIP 校准批次 3 行 Mockito 误用,P0,O-5 收口归研发负责人1)。来源全为 `docs/tdd/test/blockers.md` |
+| 已解决问题数 | 4 个 | **B-34** 已修复(`1b15b67d2` S-cfc-33,GenerateRequest 补 prompt_template,IN origin/cfclub ✓);**B-35** 已修复(`9628df3d9` S-cfc-34,DanReportParseService 版式分支补齐,IN CHAIN ✓);**B-37** 已修复(`41f1fc93` PublicConfigController.getValue 校验 `key.trim().isEmpty()`,契约 1 红转绿,IN CHAIN ✓);**B-29** 已解除(65 轮实测转正 95.78%:隔离树代入 21 测试资产 + 3 行修正后 1847 例/1769 绿,本轮复核 **21 个测试资产已全部入库 origin/cfclub**——ArticleControllerTest 等位于 integration/controller 包、主工作树已无 Test.java WIP) |
+| 待解决研发问题数 | 3 个 | **B-31**(P0 安全:application.yml 7 处明文凭据)——O-10 已裁决(${ENV} 占位 + 本地 .env + 运维侧轮换),**依赖运维侧生成新凭据并注入环境变量后研发方可改配置**,暂缓执行;**B-33**(.gitignore:70 `*.py` 全局忽略)——O-11 已裁决(`*.py`→`/*.py` + 白名单 `!docs/tdd/tools/` `!docs/scripts/` `!tools/`),**本轮已派发执行(见 1.2)**;**B-36**(根级黑盒 API 23 例全 skip)——测试/环境类,测试侧自处置(seed 账号 + globalSetup + CI 注入),未派研发 |
+
+### 1.2 任务分发与会话管理
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 分派任务数 | 1 个 | **O-11(.gitignore 细化 / B-33 执行)** → local-45278 复用会话 `ses_e99a1aec1ffeGpHpFfMBizz1O3`(标题「T08 仓库卫生与 .gitignore」,相似度 0.22 智能匹配)→ 09:5x 异步投递 ✅,指令含:`*.py`→`/*.py` + 白名单 3 行、只改 .gitignore 一个文件、禁止 git add .、commit 信息含 O-11/B-33、push origin/cfclub、主工作树其他 WIP 一律不碰 |
+| 恢复智能体会话数 | 0 个 | 轮初 `--inspect`:5 节点 250 会话全空闲(busy=0 idle=50 interrupted=0),无中断/卡死会话需恢复 |
+| 当前在用会话数 | 1 个 | O-11 派发后 1 个在途(local-45278 ses_e99a1aec);其余 249 空闲 |
+| 会话平均利用率 | ~2% | 研发侧 TDD 任务池空(无新增能力键/无 RED/无真实现缺口),efficient 利用集中在测试侧 EVD 队列 |
+
+### 1.2b 各会话当前工作状态列表
+
+| 会话标签 | 会话 ID | 当前状态 | 当前任务 | 静默/空闲时长 | 工作目录 | 备注 |
+|---|---|---|---|---|---|---|
+| lan-189 | (50 会话) | idle | — | 全空闲 | 干净 | 配额 0/3,剩余 3 |
+| lan-204 | (50 会话) | idle | — | 全空闲 | 干净 | 配额 0/3,剩余 3 |
+| local-lan-4090 | (50 会话) | idle | — | 全空闲 | 干净 | 配额 0/3,剩余 3 |
+| mes-local-45278 | (50 会话) | 1 running + 49 idle | O-11 .gitignore 细化(ses_e99a1aec1ffeGpHpFfMBizz1O3) | 1 个刚派发 | 不干净(主工作树 43 处 ?? 用户交付材料) | 复用 T08 会话 |
+| pub-iwintrue | (50 会话) | idle | — | 全空闲 | 干净 | 配额 0/3,剩余 3 |
+
+> 状态口径:`--inspect`(测试角色只读)逐节点核实,busy=0 idle=50 / 实例,配额占用 0/3。任务账本(.workbuddy/tasks.json)34 条 = 33 done + 1 failed(S-cfc-20 tokens=0),0 pending / 0 dispatched。
+
+### 1.3 变更感知与新任务建立
+
+| 指标 | 数量 | 说明 |
+|------|------|------|
+| 感知需求/设计变更数 | 30 个 | `--changes --days 2`:200 提交/226 文件(设计文档 93 处——EVD-10/11 契约、huawei-health 方案、CI 文档等;测试用例文档 17 处——EVD-3/4/5/6/8R 证据提交、测试负责人 63~68 轮汇报等);**无新增能力键(0→0,变更为既有键内容/状态变化)** |
+| 新增入池任务数 | 0 个 | `--add-task` 需合法 `unit.domain.action` 键,本轮 0→0 无新键可入池;O-11 属共享配置文件项(非能力键),按 O-10/O-11 裁决走研发独立 commit / hub 派发通道,不入 TDD 任务池 |
+| 既有键状态流转数 | 9 次 | YELLOW→GREEN ×7(admin.auth.login / health.report.upload / health.report.createReport / dan.assessment.getActiveMaterial / task.history.view / growth.history.view / achievement.grid.fiveCol)+ 新登记 YELLOW→GREEN ×2(langgraph.questionnaire.generate `1b15b67d2` / dan.report.parseFormat `9628df3d9`,O-9 脚本修复 + 回补登记后由测试侧复验转 GREEN);`sleep.config.tags` 维持 YELLOW(B-37 已修复待测试侧复验 mark-green) |
+
+### 1.4 本轮 git 提交与推送证据(真理证据)
+
+> 本实例本轮为只读核查 + 派发轮,以下为本轮**核验确认的推进证据**(皆已推 origin/cfclub),非本实例产出。
+
+| 提交 sha | 关联任务/能力键 | 阶段 | 触及文件类型 | 目标分支 | 已推送远端 | 备注 |
+|---|---|---|---|---|---|---|
+| `1b15b67d2` | langgraph.questionnaire.generate(S-cfc-33/B-34) | YELLOW→GREEN | 实现(cfc-langgraph/src) | cfclub | 是 | `git merge-base --is-ancestor` = YES ✓(O-9 已回补登记) |
+| `9628df3d9` | dan.report.parseFormat(S-cfc-34/B-35) | YELLOW→GREEN | 实现(cfc-backend/src/main) | cfclub | 是 | IN CHAIN ✓(O-9 同口径登记) |
+| `41f1fc93` | sleep.config.tags(B-37) | 修复(契约 1 红转绿) | 实现(PublicConfigController.java) | cfclub | 是 | IN CHAIN ✓;`key.trim().isEmpty()` 校验 |
+| `dceeaaeaf` | 游客域 SC-G-01/03/04/05/07/08/09/10/11/12(10 SC) | GREEN 证据 | 测试(71 例三类流契约) | cfclub | 是 | IN CHAIN ✓,sc-key-map 已登记跑通 |
+| `7f9b978c2` | EVD-8R 测评-方案 43 SC | 契约证据 | 测试(10 JUnit 156 全绿) | cfclub | 是 | IN CHAIN ✓(TR-12 回收) |
+| `77026df42` | EVD-10 规划师域 32 SC | 契约核对产出 | 文档(planner-zone-contract) | cfclub | 是 | IN CHAIN ✓(TR-13 回收,29 完全满足 + 3 子缺口 G-1/2/3) |
+| `9abed8e11` | EVD-11 平台运营 25 SC | 契约核对产出 | 文档(admin-ops-contract) | cfclub | 是 | IN CHAIN ✓(TR-14 回收,缺口 5 条 A-04/14/19/20/21 待产品侧确认) |
+| sleep.config.tags 证据链 | 04d87cfd1 / 93aad0152 / f8b145d3a / 4734bcf45 / f11062b42 | YELLOW | 实现+契约 | cfclub | 全部 IN CHAIN ✓ | mark-green 前置证据齐备(注:yellow_sha 04d87cfd1 为历史误配,真实实现 93aad0152 等已核验) |
+
+### 1.5 状态机阶段分布与部署状态
+
+| 阶段 | 键数 | 备注 |
+|------|------|------|
+| UNTRACKED | 0 | — |
+| RED | 0 | 无待开发 |
+| YELLOW | 1 | sleep.config.tags(B-37 已修复,待测试侧复验 mark-green,TR-11 已送达) |
+| GREEN | 9 | admin.auth.login / health.report.upload / health.report.createReport / dan.assessment.getActiveMaterial / dan.report.parseFormat / task.history.view / growth.history.view / achievement.grid.fiveCol / langgraph.questionnaire.generate |
+| DONE | 12 | auth.guest.jwtGuard / auth.guest.wechatLogin / dimension.registry.getTree / dimension.registry.mapLegacyCode / family.familyMembers.addMember / family.familyMembers.listMembers / family.parent.switchRole / guide.trainingPlan.getPlanDetail / guide.trainingPlan.getPlanList / reward.cfEstimate.expectedCf / task.parent.createTask / task.parent.review |
+
+| 部署项 | 值 | 说明 |
+|--------|-----|------|
+| 本轮部署次数 | 0 次 | 本实例未派发部署 |
+| 最新 last_deployed | 292087771 | .tdd/deploy_state.json:confirmed 20 + pending 1(292087771 done at 11-06 19:22);⚠ tasks.json 顶层 last_deployed=None(其他槽位重写 tasks.json 时字段丢失,建议下轮核对回填) |
+| GREEN 部署链验证 | 部分通过 | **部署缺口 8 提交**在 292087771 后未确认 testing 部署:41f1fc934(B-37)/ ba6b48d28(B-4 F1/F2)/ 9628df3d9(B-35)/ 1b15b67d2(B-34)/ def9c83a3(商品标签)/ 30ae86d7d(引导浮层)/ 895e500e1(标签选择器 cfc-web)等,**登记待部署侧核对**(测试侧已在干净 worktree 旁路复验主要键,不阻断 GREEN 证据) |
+
+### 1.6 数据源健康度
+
+| 数据源 | 读取键数 | 是否正常 | 备注 |
+|--------|----------|----------|------|
+| 需求侧(⏳ wish) | 0 | 正常 | 目标池 0 键(非静默失效,`--status` 实测:⏳ 0/契约 0/用例∩⏳ 0/回填 0) |
+| 契约常量(contract) | 0 | 正常 | CFC 当前启用发现/跟踪模式,契约常量仅作标注用 |
+| 测试用例引用(test_case_map) | 0 | 正常 | — |
+| 执行结果回填(case_results) | 0 | 正常 | — |
+
+---
+
+## 二、下一步需要研发处理的事项
+
+| 序号 | 事项描述 | 依赖/前置条件 | 预估完成时间 | 优先级 | 状态 |
+|------|----------|---------------|--------------|--------|------|
+| 1 | 回收 O-11 产出(.gitignore 细化提交,闭环 B-15/B-32/B-33 放行规则) | local-45278 T08 会话完成 + push | 11-07 当日 | P1 | 进行中(本轮已派发) |
+| 2 | sleep.config.tags `--mark-green` 收口跟进 | 测试侧复验 SleepConfigTagsMechanismContractTest 10/10(TR-11/EVD-1) | 11-07 当日 | P1 | 待测试处理 |
+| 3 | 规划师域 G-1/2/3 实现缺口决策(SC-T-10 no-show 无独立端点 / SC-T-22 方案归档 / SC-T-29 批量导出) | 与产品/测试侧对齐验收方式 | 11-08 前 | P1 | 待启动(TR-13 已登记) |
+| 4 | B-31 配置改造(application.yml `${ENV}` 占位 + 7 处凭据去明文) | **运维侧生成新凭据 + 部署环境变量注入就绪**(O-10 已裁决) | 运维就绪后 1 轮 | P0 | 待启动(阻塞=运维) |
+| 5 | 部署缺口 8 提交确认 testing 部署 | 部署侧核对确认 | 11-07 当日 | P2 | 待部署侧 |
+
+---
+
+## 三、阻塞与风险
+
+| 阻塞项 | 影响范围 | 阻塞类型 | 处置进展 | 需要协调 |
+|--------|----------|----------|----------|----------|
+| B-31 application.yml 7 处明文凭据在库 | 全环境安全(P0) | 研发/运维 | 已裁决(O-10:${ENV} + .env + gitleaks CI 扫描 + 凭据轮换);**待运维侧注入环境变量后研发改配置** | 主理人协调运维侧先行生成新凭据 |
+| O-3 工作目录门禁 | SC 跑通第三判据 | 流程 | 主工作树 43 处 `??`(全为用户交付参考材料 v2.1~v2.10 等 + 运行产物 dep_*.json),`--clean-check` 退出 1;按纪律④不代提交/清理 | 主理人定主工作树收口责任人(或确认判据③已按 O-3/O-5 裁决"SC 关联提交级"执行) |
+| 部署缺口 8 提交(last_deployed=292087771 后) | testing 环境版本滞后 | 部署 | 已登记待部署侧核对;测试侧干净 worktree 旁路复验不阻断证据 | 部署侧确认后回填确认 |
+| tasks.json `last_deployed` 字段丢失(顶层=None) | 部署账本可追溯性 | 编排 | 从 deploy_state.json 可推导(292087771);建议下轮由编排侧回填 | 编排侧回填 |
+| 多槽位并发编号口径混乱 | 汇报追溯 | 流程 | 沿用主理人裁定(文件名时间戳全局唯一,"第 N 轮"为实例内计数) | — |
+| B-36 根级黑盒 23 例全 skip | 接口层验收覆盖 | 测试/环境 | 测试侧自处置(seed 账号 + globalSetup + CI 注入) | 测试侧闭环 |
+
+---
+
+## 四、下轮工作规划
+
+| 计划项 | 预计完成时间 | 前置依赖 | 涉及会话标签 | 备注 |
+|--------|--------------|----------|--------------|------|
+| 核验 O-11 .gitignore 提交(IN CHAIN + 触及文件复核) | 11-07 下一轮 | 会话完成 | local-45278 | git 真理核验 |
+| 跟进 sleep.config.tags GREEN 收口 | 11-07 下一轮 | 测试侧 mark-green | — | 若未收口则回填 TR 状态 |
+| 回收 EVD-9/12 契约核对产出(孩子端 26 SC / 服务商 6 SC)转测试侧 | 11-07 下两轮 | 会话完成 | lan-189 / local-45278 | 按 TR-12/13 节奏 |
+| G-1/2/3 实现缺口评估(规划师域) | 11-08 前 | 产品验收口径 | — | 评估补端点 or 标注仅登记 |
+| 主轴:241 SC 端到端(当前 15/241 跑通),P0/P1 批次契约补建滚动推进(O-7 授权链) | 持续 | EVD 队列 | 全节点 | EVD-1~12 在途,测试侧按 sc-key-map 滚动登记 |
+
+---
+
+## 附录
+
+### 附录 A:收到的测试反馈问题明细
+
+| 问题 ID | 能力键/任务号 | 问题类型 | 来源 | 接收时间 | 处置状态 | 关联 sha |
+|---------|---------------|----------|------|----------|----------|----------|
+| B-34 | langgraph.questionnaire.generate(S-cfc-33) | 实现缺陷(P0) | blockers.md | 11-07 02:1x | 已解决 | 1b15b67d2(IN CHAIN) |
+| B-35 | dan.report.parseFormat(S-cfc-34) | 实现缺陷 | blockers.md | 11-07 03:0x | 已解决 | 9628df3d9(IN CHAIN) |
+| B-37 | sleep.config.tags | 实现缺陷 | blockers.md | 11-07 05:50 | 已解决(待测试复验 mark-green) | 41f1fc93(IN CHAIN) |
+| B-29 | —(测试资产收口) | 流程(O-5 裁决归研发负责人1) | blockers.md | 11-06 23:10 | 已解除(95.78% 转正 + 测试资产已入库 origin,主工作树无 Test.java WIP) | — |
+
+### 附录 B:任务分派与会话恢复明细
+
+| 任务号 | 目标会话标签 | 任务类型 | 分派时间 | 当前状态 | 恢复会话标签 | 恢复原因 | 恢复时间 |
+|--------|--------------|----------|----------|----------|--------------|----------|----------|
+| O-11 | local-45278(ses_e99a1aec1ffeGpHpFfMBizz1O3,复用 T08 会话) | 配置任务 | 11-07 09:5x | running(异步投递) | — | — | — |
+
+### 附录 C:新增入池任务明细
+
+| 任务号 | 能力键 | 需求溯源 | 设计溯源 | 创建时间 | 状态 |
+|--------|--------|----------|----------|----------|------|
+| (无) | — | — | — | — | 本轮 0→0 无新增能力键;O-11 非能力键走 hub 通道 |
+
+### 附录 D:变更感知明细(来自 `--changes --days 2`)
+
+| 变更文档 | 文档类型 | 变更日期 | 新增能力键 | 是否已入池 |
+|----------|----------|----------|------------|------------|
+| docs/superpowers/api/API_REFERENCE.md(9abed8e1) | 设计 | 11-07 | 0 | — |
+| docs/superpowers/specs/2026-11-07-planner-zone-contract.md(77026df4) | 设计 | 11-07 | 0(16 建议键映射,不新建状态机键) | — |
+| docs/superpowers/specs/2026-11-07-admin-ops-contract.md(9abed8e1) | 设计 | 11-07 | 0(25 映射含既有键复用) | — |
+| docs/tdd/ci/CI_READINESS_2026-11-05.md 等 81+ 文档 | 设计/其他 | 11-06~07 | 0 | — |
+| docs/tdd/test/automation-run-*(63~68 轮等 17 处) | 测试用例 | 11-06~07 | 0(既有键状态变化) | — |
+| cfc-backend/src/main/**(41f1fc93/9628df3d9/ba6b48d2 等) | 实现 | 11-07 | 0 | — |
+
+---
+
+**场景覆盖矩阵(本轮口径)**:sc-key-map.md 唯一 SC ID=主表行数=**241**(O-8 归一已落地);**累计已跑通 15/241**(O-3 收口 5:G-02/G-06/P-03/P-10/P-11 + 2026-11-07 游客域补证 10:G-01/03/04/05/07/08/09/10/11/12,证据 `dceeaaeaf` 71 例三类流全绿,IN CHAIN ✓)。**DEV_GOAL 顶层目标 241 SC 端到端跑通,当前 15/241;未跑通 226**。EVD-1~12 队列(测试侧契约核对/证据补建)滚动推进中:EVD-1(10 YELLOW 复验+GREEN 收口)/ EVD-2(家庭 15)/ EVD-3(任务心愿 22)/ EVD-4(商城 18)/ EVD-5(五维 12)/ EVD-6(CI 接入)/ EVD-7(报告 23)/ EVD-8(测评 43)/ EVD-9(孩子端 26)/ EVD-10(规划师 32,产出 77026df42 已回收)/ EVD-11(平台运营 25,产出 9abed8e11 已回收)/ EVD-12(服务商 6)。研发侧当前无新实现缺口(O-7:P0 批次端点 100% 实现,0 缺失;P1/P2 批次待 P0 滚动后核对),池空 + 无新增能力键 → 本轮从待处理阻塞(O-11/B-33)设计 1 个可执行任务并派发,符合「池空不是收手理由」铁律。

+ 172 - 0
docs/tdd/orchestration/report-dev-2026-11-07-1025.md

@@ -0,0 +1,172 @@
+# 研发负责人工作汇报(研发负责人 · 错峰03 · 2026-11-07 10:25 轮)
+
+> **说明**:本报告依据 `tdd-orchestrator` 研发负责人模板填写,数据来自本轮(`2026-11-07 10:25`)只读核查(`--status` / `--changes --days 7` / `--clean-check`)、git 真理核验(`git fetch` + `git merge-base --is-ancestor`)与远端 `docs/tdd/**` 文档复核。
+> **角色纪律**:本轮为只读检查 + 调度决策 + 汇报汇总;未代写实现、未改业务代码、未动 `.tdd/state.json` 与他人 WIP(纪律④)。
+
+---
+
+## 基本信息
+
+| 项目 | 内容 |
+|------|------|
+| 汇报人 | 研发负责人(tdd-orchestrator · 错峰03 自动化) |
+| 汇报周期 | 2026年11月07日 09:54 ~ 10:25(错峰03 槽位,文件名时间戳全局唯一) |
+| 负责模块/单元范围 | cfc 全量(scope 空) |
+
+---
+
+## 一、本轮工作数据汇总
+
+### 1.1 问题接收与处置
+
+| 指标 | 数量 | 填写说明 |
+|------|------|----------|
+| **收到的测试反馈问题数*** | `0` 个 | 本轮 `--changes --days 7` + 远端 `blockers.md` 复核:无新增 `B-*` 阻塞(既有 B-31/B-33/B-36/B-37 均为前轮已登记项,非本轮新接收) |
+| **已解决问题数*** | `1` 个 | **O-11(B-33)已闭环**:`.gitignore` 细化 `fb5412e92` 已推 origin/cfclub(`*.py`→`/*.py` + 白名单 `!docs/tdd/tools/` `!docs/scripts/` `!tools/`),`git merge-base --is-ancestor` = YES ✓,联动闭环 B-15(脚本丢失)/ B-32(口径跨轮漂移) |
+| **待解决研发问题数** | `5` 个 | ① B-31(P0 安全,application.yml 7 处明文凭据)——O-10 已裁决,**阻塞=运维侧生成新凭据并注入环境变量**;② 规划师域 G-1/2/3 实现缺口(SC-T-10/22/29)——本轮已出裁决意见(O-12,待主理人确认);③ 平台运营域 A-04/14/19/20/21 无 HTTP 载体——待产品侧确认验收方式(TR-14);④ B-37 已修复待测试侧复验 `--mark-green`(sleep.config.tags,TR-11 已送达);⑤ B-36 根级黑盒 23 例全 skip——测试侧自处置(seed 账号 + globalSetup + CI 注入) |
+
+> **已解决明细**:O-11 共享配置修订 `fb5412e92`(chore(O-11): .gitignore 细化…)已推 origin/cfclub;主工作树 `git status` 复核该提交为远端唯一 O-11 落地(此前本地 HEAD=fb5412e92,origin/cfclub 领先 1 提交 cd35657f6 EVD-7 证据,不冲突)。
+
+### 1.2 任务分发与会话管理
+
+| 指标 | 数量 | 填写说明 |
+|------|------|----------|
+| **分派任务数*** | `0` 个 | 本轮 0 派发:① 能力键 TDD 池空(⏳ 0,账本 0 pending / 0 dispatched);② O-11 已于前轮派发并在本轮核验闭环;③ O-7 契约补建下一批受 G-1/2/3 及 A-04/14/19/20/21 决策门控,新契约未合入、不满足 `--add-task` 溯源铁律 |
+| **恢复智能体会话数*** | `0` 个 | 无中断会话需恢复(最近可达快照 5 节点 250 会话全部 `idle`,busy=0 interrupted=0) |
+| **当前在用会话数** | `0` 个 | 本环境无可达 opencode 会话(config.json 会话 id 为占位符);远程会话由 dispatcher 通道管理 |
+| **会话平均利用率** | `N/A` | 能力键池空 + 契约批次被决策门控 → 本轮无派发对象;黑窗 429 已于 08:00 解除,首个可派发窗口已开启 |
+
+> **R2「不留空闲」核验**:能力键池空 + 无中断会话 + 契约批次门控 → 本轮无派发对象,非「会话空闲未派」。
+
+### 1.2b 各会话当前工作状态列表
+
+> 本环境无法直连远程 opencode 客户端(会话 id 为占位符),沿用最近可达快照(2026-11-07 09:54 巡检,5 节点 250 会话全 idle):
+
+| 会话标签 | 会话 ID | 当前状态 | 当前任务 | 静默/空闲时长 | 工作目录 | 备注 |
+|----------|---------|----------|----------|---------------|----------|------|
+| lan-189 | (50 会话) | `idle` | — | 长 | 干净 | 配额 0/3,剩余 3 |
+| lan-204 | (50 会话) | `idle` | — | 长 | 干净 | 配额 0/3,剩余 3 |
+| local-lan-4090 | (50 会话) | `idle` | — | 长 | 干净 | 配额 0/3,剩余 3 |
+| mes-local-45278 | (50 会话) | `idle` | — | 长 | 干净 | 配额 0/3,剩余 3;O-11 已于 09:5x 会话执行完毕(fb5412e92 落地) |
+| pub-iwintrue | (50 会话) | `idle` | — | 长 | 干净 | 配额 0/3,剩余 3;CFC 部署/契约核对主通道 |
+
+> **任务账本**(.workbuddy/tasks.json):34 条 = 33 done + 1 failed(S-cfc-20 tokens=0),0 pending / 0 dispatched。
+
+### 1.3 变更感知与新任务建立
+
+| 指标 | 数量 | 填写说明 |
+|------|------|----------|
+| **感知需求/设计变更数*** | `200` 提交 / `238` 文件 | `--changes --days 7`:设计文档 94(EVD-10/11 契约、huawei-health 方案、预警/CI 等)+ 测试用例文档 16(EVD-3/4/5/6/7R/8R 证据、测试负责人 63~68 轮汇报)+ 其他 128;**无新增能力键(0→0),变化集中在既有键** |
+| **新增入池任务数*** | `0` 个 | `--add-task` 需合法 `unit.domain.action` + `--requirement`/`--design` 溯源,本轮 0→0 无新键可入池;O-11 属共享配置走独立 commit 通道不入 TDD 池 |
+| **既有键状态流转数** | `0` 次 | 状态机自 06:16 轮稳定(DONE12 / GREEN9 / YELLOW1 / RED0),本轮无阶段流转 |
+
+### 1.4 本轮 git 提交与推送证据(真理证据)
+
+> 本实例本轮为只读核查 + 汇报轮,以下为本轮**核验确认的推进证据**(皆已推 origin/cfclub,非本实例产出)。
+
+| 提交 sha | 关联任务/能力键 | 阶段 | 触及文件类型 | 目标分支 | 已推送远端 | 备注 |
+|----------|-----------------|------|--------------|----------|------------|------|
+| `fb5412e92` | O-11 / B-33(.gitignore 细化) | 闭环 | 共享配置 | cfclub | 是 | IN CHAIN ✅,放行 Python 度量/解析脚本入库 |
+| `41f1fc93` | sleep.config.tags(B-37 修复) | YELLOW 证据 | 实现(PublicConfigController.java) | cfclub | 是 | IN CHAIN ✅;`key.trim().isEmpty()` 校验,契约 1 红转绿 |
+| `1b15b67d2` | langgraph.questionnaire.generate(B-34) | GREEN | 实现(cfc-langgraph/src) | cfclub | 是 | IN CHAIN ✅(O-9 已纳入 main 归口) |
+| `9628df3d9` | dan.report.parseFormat(B-35) | GREEN | 实现(cfc-backend/src/main) | cfclub | 是 | IN CHAIN ✅ |
+| `dceeaaeaf` | 游客域 SC-G-01/03/04/05/07/08/09/10/11/12(10 SC) | GREEN 证据 | 测试(71 例三类流契约) | cfclub | 是 | IN CHAIN ✅,sc-key-map 已登记跑通(累计 15/241) |
+| `77026df42` | EVD-10 规划师域 32 SC 契约核对 | 契约产出 | 文档(planner-zone-contract) | cfclub | 是 | IN CHAIN ✅;29 完全满足 + 3 子缺口 G-1/2/3 |
+| `9abed8e11` | EVD-11 平台运营 25 SC 契约核对 | 契约产出 | 文档(admin-ops-contract) | cfclub | 是 | IN CHAIN ✅;缺口 5 条 A-04/14/19/20/21 待产品确认 |
+| sleep.config.tags 证据链 | 93aad0152 / f8b145d3a / 4734bcf45 / f11062b42 | YELLOW | 实现+契约 | cfclub | 全部 IN CHAIN ✅ | mark-green 前置证据齐备(yellow_sha 04d87cfd1 为历史误配,真实实现已核验) |
+| `cd35657f6` | EVD-7 报告闭环 23 SC 三类流 e2e 证据 | GREEN 证据 | 测试(25 用例全绿 + 契约 82/82) | cfclub | 是 | IN CHAIN ✅(origin/cfclub 当前 HEAD) |
+
+### 1.5 状态机阶段分布与部署状态
+
+| 阶段 | 键数 | 备注 |
+|------|------|------|
+| UNTRACKED | `0` | 已发现未入池 |
+| RED | `0` | 无待开发 |
+| YELLOW | `1` | sleep.config.tags(B-37 已修复,待测试侧复验 mark-green,TR-11 已送达) |
+| GREEN | `9` | admin.auth.login / health.report.upload / health.report.createReport / dan.assessment.getActiveMaterial / dan.report.parseFormat / task.history.view / growth.history.view / achievement.grid.fiveCol / langgraph.questionnaire.generate |
+| DONE | `12` | auth.guest.jwtGuard / auth.guest.wechatLogin / dimension.registry.getTree / dimension.registry.mapLegacyCode / family.familyMembers.addMember / family.familyMembers.listMembers / family.parent.switchRole / guide.trainingPlan.getPlanDetail / guide.trainingPlan.getPlanList / reward.cfEstimate.expectedCf / task.parent.createTask / task.parent.review |
+
+| 部署项 | 值 | 说明 |
+|--------|-----|------|
+| 本轮部署次数 | `0` 次 | 本实例未派发部署 |
+| 最新 `last_deployed` | `292087771` | .tdd/deploy_state.json:confirmed 20 + pending 1(292087771 done at 11-06 19:22);⚠ tasks.json 顶层 `last_deployed=None`(其他槽位重写 tasks.json 时字段丢失,可从 deploy_state 推导,下轮编排侧核对回填) |
+| GREEN 部署链验证 | 部分通过 | **部署缺口 8 提交**在 292087771 后未确认 testing 部署:41f1fc93(B-37)/ ba6b48d2(B-4 F1/F2)/ 9628df3d9(B-35)/ 1b15b67d2(B-34)/ def9c83a3(商品标签)/ 30ae86d7d(引导浮层)/ 895e500e1(标签选择器 cfc-web)等,登记待部署侧核对(测试侧已在干净 worktree 旁路复验主要键,不阻断 GREEN 证据) |
+
+### 1.6 数据源健康度
+
+| 数据源 | 读取键数 | 是否正常 | 备注 |
+|--------|----------|----------|------|
+| 需求侧(⏳ wish) | `0` | 正常 | 目标池 0 键(`--status` 实测:⏳ 0/契约 0/用例∩⏳ 0/回填 0),非静默失效 |
+| 契约常量(contract) | `0` | 正常 | CFC 当前启用发现/跟踪模式,契约常量仅作标注用 |
+| 测试用例引用(test_case_map) | `0` | 正常 | — |
+| 执行结果回填(case_results) | `0` | 正常 | — |
+
+---
+
+## 二、下一步需要研发处理的事项
+
+| 序号 | 事项描述 | 依赖/前置条件 | 预估完成时间 | 优先级 | 状态 |
+|------|----------|---------------|--------------|--------|------|
+| 1 | 规划师域 G-1/2/3 实现缺口落地(SC-T-10 no-show / SC-T-22 方案归档 / SC-T-29 批量导出) | **O-12 裁决意见待主理人确认**;G-3 若立契约任务需先补设计契约 + 测试用例 | 11-08 前 | P1 | 待启动(O-12 待确认) |
+| 2 | 平台运营域 A-04/14/19/20/21 验收方式确认(无 HTTP 载体 4 条 + 关系类型 CRUD 表已 DROP 1 条) | 产品侧确认验收方式(TR-14 已登记) | 11-08 前 | P1 | 待产品侧确认 |
+| 3 | sleep.config.tags `--mark-green` 收口跟进 | 测试侧复验 SleepConfigTagsMechanismContractTest 10/10(TR-11) | 11-07 当日 | P1 | 待测试处理 |
+| 4 | B-31 配置改造(application.yml `${ENV}` 占位 + 7 处凭据去明文) | **运维侧生成新凭据 + 部署环境变量注入就绪**(O-10 已裁决) | 运维就绪后 1 轮 | P0 | 待启动(阻塞=运维) |
+| 5 | 部署缺口 8 提交确认 testing 部署 + tasks.json `last_deployed` 回填 | 部署侧核对确认 | 11-07 当日 | P2 | 待部署侧/编排侧 |
+
+---
+
+## 三、阻塞与风险
+
+| 阻塞项 | 影响范围 | 阻塞类型 | 处置进展 | 需要协调 |
+|--------|----------|----------|----------|----------|
+| B-31 application.yml 7 处明文凭据在库 | 全环境安全(P0) | 研发/运维 | 已裁决(O-10:${ENV} + .env + gitleaks CI 扫描 + 凭据轮换);**待运维侧注入环境变量后研发改配置** | 主理人协调运维侧先行生成新凭据 |
+| O-3 工作目录门禁 | SC 跑通第三判据 | 流程 | 主工作树 140 处未提交(1 M + 139 `??`,多为用户交付参考材料与运行产物),`--clean-check` 退出 1;按纪律④不代提交/清理;按 O-3/O-5 裁决判据③「SC 关联提交级」执行不阻断 | 主理人确认判据口径继续沿用 |
+| 部署缺口 8 提交(last_deployed=292087771 后) | testing 环境版本滞后 | 部署 | 已登记待部署侧核对;测试侧干净 worktree 旁路复验不阻断证据 | 部署侧确认后回填确认 |
+| tasks.json `last_deployed` 顶层字段丢失 | 部署账本可追溯性 | 编排 | 可从 deploy_state.json 推导(292087771);下轮由编排侧核对回填 | 编排侧回填 |
+| 契约核对批次门控(EVD-12 服务商 6 SC 在途) | 契约补建滚动节奏 | 流程 | EVD-12 已派 local-45278(TR-13 ②),产出合入后转测试侧补证据;G-1/2/3 + A-* 决策先行 | — |
+
+---
+
+## 四、下轮工作规划
+
+| 计划项 | 预计完成时间 | 前置依赖 | 涉及会话标签 | 备注 |
+|--------|--------------|----------|--------------|------|
+| 回收 EVD-12 服务商域 6 SC 契约核对产出并转测试侧 | 11-07 当日 | local-45278 会话完成 + push | local-45278 | 产出后按 sc-key-map 登记 |
+| 依 O-12 裁决落地 G-1/2/3(组合补证 / 立契约任务 / 产品确认) | 主理人确认后 1 轮 | O-12 主理人最终确认 | — | 防假 RED 前提 |
+| 跟进 sleep.config.tags mark-green + 部署缺口核对 | 11-07 当日 | 测试侧复验 + 部署侧确认 | — | — |
+
+---
+
+## 附录
+
+### 附录 A:收到的测试反馈问题明细
+
+| 问题 ID | 能力键/任务号 | 问题类型 | 来源 | 接收时间 | 处置状态 | 关联 sha |
+|---------|---------------|----------|------|----------|----------|----------|
+| B-37 | sleep.config.tags | 实现缺陷 | blockers.md(复验派发) | 2026-11-07 05:50 | 已修复待测试复验 | `41f1fc93` |
+| B-31 | application.yml 凭据 | 实现缺陷(安全) | blockers.md(62 轮) | 2026-11-06 23:10 | 已裁决待运维 | — |
+| G-1/2/3 | SC-T-10/22/29 | 实现缺口 | TR-13(EVD-10) | 2026-11-07 09:05 | 待裁决(O-12) | `77026df42` |
+| A-04/14/19/20/21 | SC-A-04/14/19/20/21 | 需求口径 | TR-14(EVD-11) | 2026-11-07 09:10 | 待产品确认 | `9abed8e11` |
+
+### 附录 B:任务分派与会话恢复明细
+
+| 任务号 | 目标会话标签 | 任务类型 | 分派时间 | 当前状态 | 恢复会话标签 | 恢复原因 | 恢复时间 |
+|--------|--------------|----------|----------|----------|--------------|----------|----------|
+| O-11 | mes-local-45278 | 共享配置修订 | 2026-11-07 09:5x | `done`(fb5412e92 已推) | — | — | — |
+
+### 附录 C:新增入池任务明细
+
+| 任务号 | 能力键 | 需求溯源 | 设计溯源 | 创建时间 | 状态 |
+|--------|--------|----------|----------|----------|------|
+| (无) | — | — | — | — | 本轮 0 新增(无新能力键 + 契约批次门控) |
+
+### 附录 D:变更感知明细(来自 `--changes --days 7`)
+
+| 变更文档 | 文档类型 | 变更日期 | 新增能力键 | 是否已入池 |
+|----------|----------|----------|------------|------------|
+| docs/superpowers/specs/2026-11-07-admin-ops-contract.md(EVD-11) | 设计 | 2026-11-07 | 0(25 SC 映射既有键) | 否 |
+| docs/superpowers/specs/2026-11-07-planner-zone-contract.md(EVD-10) | 设计 | 2026-11-07 | 0(16 建议键定稿登记) | 否 |
+| docs/superpowers/api/API_REFERENCE.md(EVD-10/11 端点回填) | 设计 | 2026-11-07 | 0 | 否 |
+| 其余 196 提交 | 设计/用例/其他 | 2026-11-06~07 | 0(既有键状态变化) | 否 |
+
+---

+ 148 - 0
docs/tdd/test/automation-run-evd7-report-closedloop-2026-11-07.md

@@ -0,0 +1,148 @@
+# EVD-7 报告闭环批次(23 SC)自动化执行记录 · 三类流 e2e + 契约复验
+
+> 归属:契约补建 P0「报告闭环 · 23 SC」· 会话:EVD-7(承接 EVD-7R 契约 JUnit)· 日期:2026-11-07
+> 开工包:`docs/tdd/orchestration/report-closedloop-kickoff-20261106.md`
+> 前置证据:`docs/tdd/dev/evidence-report-closedloop-evd7-20261107.md`(EVD-7R:11 类 JUnit 82 用例 + LangGraph pytest 8 用例)
+> 本记录只补**执行证据**:新增 API 级 e2e spec + 复跑结果 + 环境说明,未改任何业务实现代码。
+
+## 1. 执行环境与基线
+
+| 项 | 内容 |
+|---|---|
+| 工作树 | `C:\Users\Administrator\AppData\Local\Temp\opencode\cfc-evd7`(隔离 worktree) |
+| 分支 | `feature/evd7-report-closedloop-contract`(基于 `origin/cfclub`) |
+| 基线 | `origin/cfclub` @ `7ecb11d02`(开工时 HEAD,`git merge-base --is-ancestor 7ecb11d02 HEAD` → exit 0) |
+| 后端 | 本地 `cfc-backend` @ `http://127.0.0.1:9082`(`mvn spring-boot:run`,实际连测试库 `192.168.16.251:3306/zxyj`) |
+| 远端 | `http://cfc.iwintrue.com` 在本窗口 **DNS 不可解析**(`未能解析远程名称`),故远端 e2e 不可执行;改用本地真实后端 + 真实测试库 |
+| 数据库口径 | 仅测试库,不代表生产;用例只自注册临时账号、只读写自身数据 |
+
+> 说明:EVD-5 的 API e2e 记录跑在远端 `cfc.iwintrue.com`。本轮远端不可达,为拿到**可复现的真实 HTTP 证据**,
+> 在隔离 worktree 启动本地后端(端口 9082,未触碰他人正在运行的进程),并用 `CFC_API_BASE` 指向本地运行同一份 spec。
+> `playwright.config.api.js` 仅新增 `process.env.CFC_API_BASE || 'http://cfc.iwintrue.com'` 的默认值回退,远端行为不变。
+
+## 2. 契约 JUnit 复验(确定性,纯 Mockito / 无 Spring / 无 DB)
+
+命令:
+
+```bash
+cd cfc-backend
+mvn -q -DskipTests test-compile          # EXIT=0
+mvn -DskipTests=false -Dtest='HealthReportAuditContractTest,ReportViewPermissionContractTest,ReportShareGrantContractTest,ReportTransferContractTest,DanReportUploadContractTest,AssessmentComparisonContractTest,GlobalSearchScP82ContractTest,ReportParserAdminContractTest,ReportConfirmRefreshFiveDimContractTest,ReportDietRecommendContractTest,ReportParserProviderConnectContractTest' surefire:test
+```
+
+实测输出:
+
+```
+Tests run: 6,  Failures: 0, Errors: 0, Skipped: 0 - AssessmentComparisonContractTest
+Tests run: 11, Failures: 0, Errors: 0, Skipped: 0 - DanReportUploadContractTest
+Tests run: 5,  Failures: 0, Errors: 0, Skipped: 0 - GlobalSearchScP82ContractTest
+Tests run: 8,  Failures: 0, Errors: 0, Skipped: 0 - HealthReportAuditContractTest
+Tests run: 3,  Failures: 0, Errors: 0, Skipped: 0 - ReportConfirmRefreshFiveDimContractTest
+Tests run: 8,  Failures: 0, Errors: 0, Skipped: 0 - ReportDietRecommendContractTest
+Tests run: 5,  Failures: 0, Errors: 0, Skipped: 0 - ReportParserAdminContractTest
+Tests run: 3,  Failures: 0, Errors: 0, Skipped: 0 - ReportParserProviderConnectContractTest
+Tests run: 11, Failures: 0, Errors: 0, Skipped: 0 - ReportShareGrantContractTest
+Tests run: 11, Failures: 0, Errors: 0, Skipped: 0 - ReportTransferContractTest
+Tests run: 11, Failures: 0, Errors: 0, Skipped: 0 - ReportViewPermissionContractTest
+Tests run: 82, Failures: 0, Errors: 0, Skipped: 0
+BUILD SUCCESS
+```
+
+结论:**82/82 通过**,与 EVD-7R 记录一致(本轮重新实跑,非引用旧结果)。
+
+## 3. API 级 e2e 执行(真实 HTTP + 真实测试库)
+
+新增 spec:`tests/e2e/api/report-closedloop-contract.spec.js`(25 用例)
+
+命令:
+
+```bash
+cd tests
+npm ci
+# 远端可用时省略 CFC_API_BASE
+CFC_API_BASE=http://127.0.0.1:9082 npx playwright test api/report-closedloop-contract.spec.js \
+  -c playwright.config.api.js --project=desktop
+```
+
+实测输出:
+
+```
+25 passed (10.5s)
+```
+
+按流分布:
+
+| 流 | 用例数 | 覆盖断言 |
+|---|---:|---|
+| 正常流 | 8 | 报告列表/家庭报告/趋势结构/授权-查询-撤销闭环/DAN 列表/解析类型链接/转交列表/teacher 代传闸门 |
+| 异常流 | 9 | 缺 memberId、缺 reportId、reportId 不存在、缺 filePath、缺授权参数、无两次测评、缺 uploadId、缺 requestId、草稿不存在 |
+| 权限流 | 8 | 无 token 401(报告/转交/代传)、非法 token 401(DAN/解析)、家长非代传角色→无权、非草稿所有者→无权确认、跨家庭成员查询→空列表不泄露 |
+
+> 首轮执行 23 passed / 2 failed,均为**断言口径写错**而非实现缺陷:
+> ① 转交审批缺参实际文案为「申请ID不能为空」(首轮写成「请求ID不能为空」);
+> ② 原「teacher 查授权列表应被拒」不成立——`direct-register` 的 teacher 会自建家庭并成为该家庭管理员,返回自身家庭空列表 200。
+> 修正为「跨家庭成员报告查询返回空列表」后 25/25 全绿(修正只改 spec,未改实现)。
+
+## 4. LangGraph 结构契约(SC-B-04/B-11)
+
+EVD-7R 已实跑 `cfc-langgraph/tests_contract/test_growth_report_contract.py` → **8 passed**。
+本轮隔离 worktree **无 `.venv`、系统 Python 无 `langgraph` 依赖**,未重复执行;测试文件未改动,证据沿用 EVD-7R 记录。
+
+## 5. 23 SC → 三类流证据矩阵(JUnit + e2e)
+
+| SC | 角色 | 场景 | JUnit | e2e | 三类流 |
+|---|---|---|---|---|---|
+| SC-A-02 | 平台运营 | 报告解析中台(类型/聚类) | `ReportParserAdminContractTest` | 解析类型链接 + 缺 filePath | ✅/✅/✅ |
+| SC-A-16 | 平台运营 | 解析自学习/未知类型标注 | `ReportParserAdminContractTest` | 解析类型链接 + 缺 filePath | ✅/✅/✅ |
+| SC-B-04 | AI 教练 | 成长报告智能解读 | — | pytest(EVD-7R) | ✅/—/✅ |
+| SC-B-11 | AI 教练 | 报告细节追问 | — | pytest(EVD-7R) | ✅/✅/✅ |
+| SC-C-06 | 孩子 | 查看能量与报告(只读) | `ReportViewPermissionContractTest` | 报告列表 + 跨成员隔离 | ✅/✅/✅ |
+| SC-C-07 | 孩子 | 查看 DAN 测评报告 | `DanReportUploadContractTest` | DAN 列表 + 非法 token 401 | ✅/✅/✅ |
+| SC-P-24 | 家长 | 多报告管理/对比 | `AssessmentComparisonContractTest` + `ReportViewPermissionContractTest` | 报告列表/家庭报告/指标缺参 | ✅/✅/✅ |
+| SC-P-25 | 家长 | 报告趋势查看 | `ReportViewPermissionContractTest` | 趋势结构 + 缺 memberId | ✅/✅/✅ |
+| SC-P-26 | 家长 | 基于报告饮食推荐 | `ReportDietRecommendContractTest` | —(JUnit 覆盖) | ✅/✅/✅ |
+| SC-P-39 | 家长 | 查看测评结果(DAN 报告) | `DanReportUploadContractTest` | DAN 列表 | ✅/✅/✅ |
+| SC-P-67 | 家长 | 报告代传 | `HealthReportAuditContractTest` | 代传无 token 401 + 非代传角色无权 | ✅/✅/✅ |
+| SC-P-82 | 家长 | 全局搜索 | `GlobalSearchScP82ContractTest` | —(MCP 需 `Mcp-Api-Key`,junit 覆盖) | ✅/✅/✅ |
+| SC-P-84 | 家长 | 分享报告给家人/规划师 | `ReportShareGrantContractTest` | 授权-查询-撤销闭环 + 缺参 + 跨成员隔离 | ✅/✅/✅ |
+| SC-P-91 | 家长 | 报告入库刷新五维 | `ReportConfirmRefreshFiveDimContractTest` | reportId 不存在 | ✅/✅/✅ |
+| SC-S-09 | 商品服务商 | 解析服务接入 | `ReportParserProviderConnectContractTest` | types/links + 非法 token 401 | ✅/✅/✅ |
+| SC-T-03 | 规划师 | 代传 + 确认入库 | `HealthReportAuditContractTest` | teacher 代传闸门 + 非所有者确认拒绝 | ✅/✅/✅ |
+| SC-T-11 | 规划师 | DAN 上传与解析 | `DanReportUploadContractTest` | —(上传依赖真实文件/JUnit 覆盖) | ✅/✅/✅ |
+| SC-T-12 | 规划师 | DAN 八类报告查看 | `DanReportUploadContractTest` | DAN 列表/对比缺参/非法 token | ✅/✅/✅ |
+| SC-T-21 | 规划师 | 报告对比分析 | `AssessmentComparisonContractTest` | 无两次测评→业务错误 | ✅/✅/✅ |
+| SC-T-23 | 规划师 | 报告代传(代客户传) | `HealthReportAuditContractTest` | 家长非代传角色无权 | ✅/✅/✅ |
+| SC-X-02 | 跨角色 | 报告闭环 | `HealthReportAuditContractTest` + `ReportTransferContractTest` | 报告列表/家庭报告/无 token 401 | ✅/✅/✅ |
+| SC-X-10 | 跨角色 | 报告对比趋势闭环 | `ReportViewPermissionContractTest` | 趋势结构 + 无两次测评 | ✅/✅/✅ |
+| SC-X-13 | 跨角色 | 报告代传跨角色闭环 | `ReportTransferContractTest` | 转交列表 + 缺 requestId + 无 token 401 | ✅/✅/✅ |
+
+> 三类流口径:正常流(主链路成功)/ 异常流(非法参数、空数据、不存在)/ 权限流(登录闸门、角色闸门、归属隔离)。
+> 「—」= 该 SC 的 e2e 分支不适用,由 JUnit/pytest 提供确定性证据(非缺口)。
+
+## 6. 观察记录(只登记,不修实现)
+
+| 观察 | 证据 | 说明 |
+|---|---|---|
+| `/api/health/report/audit/pending` 对任意登录用户返回**全平台**待审草稿(不限家庭/角色) | e2e 正常流 `audit/pending` 实测返回多个其他家庭(familyId 2009/2979)草稿 | 列表端点无家庭过滤;确认动作仍受 `validateDraftOwnership` 限制(非所有者确认被拒,已由 e2e 权限流验证)。建议后续治理列表可见范围 |
+| 代传确认对无权限角色返回业务码 500 +「无权」,而非 HTTP 403 | e2e `proxy-confirm` 权限流 | 与项目 `Result.error` 统一口径一致,非缺陷;登记供前端提示文案对齐 |
+
+## 7. 改动文件清单(仅测试资产 + 证据文档)
+
+```
+tests/e2e/api/report-closedloop-contract.spec.js      (新,25 用例 × 三类流)
+tests/playwright.config.api.js                        (改,baseURL 支持 CFC_API_BASE 本地复验回退)
+docs/tdd/test/automation-run-evd7-report-closedloop-2026-11-07.md(新,本记录)
+docs/tdd/dev/evidence-report-closedloop-evd7-20261107.md(改,追加第 8 节指向本记录)
+```
+
+未新增 DB 迁移、未修改任何 `src/main` 业务实现。
+
+## 8. 复验命令
+
+```bash
+# 契约 JUnit(本地确定性)
+cd cfc-backend && mvn -DskipTests=false -Dtest='HealthReportAuditContractTest,ReportViewPermissionContractTest,ReportShareGrantContractTest,ReportTransferContractTest,DanReportUploadContractTest,AssessmentComparisonContractTest,GlobalSearchScP82ContractTest,ReportParserAdminContractTest,ReportConfirmRefreshFiveDimContractTest,ReportDietRecommendContractTest,ReportParserProviderConnectContractTest' test
+
+# API e2e(远端可用时;或先本地启动 9082)
+cd tests && npx playwright test api/report-closedloop-contract.spec.js -c playwright.config.api.js --project=desktop
+```

+ 241 - 0
tests/e2e/api/report-closedloop-contract.spec.js

@@ -0,0 +1,241 @@
+/**
+ * EVD-7 报告闭环批次(23 SC)— 三类流 API 级 e2e
+ * ================================================================
+ * 覆盖 SC:SC-A-02/A-16、SC-C-06/C-07、SC-P-24/P-25/P-39/P-67/P-84/P-91、
+ *         SC-S-09、SC-T-03/T-11/T-12/T-21/T-23、SC-X-02/X-10/X-13。
+ * 与 cfc-backend/src/test/java/com/etotem/cfc/unit/*Report*ContractTest 契约 JUnit 互补:
+ *   - JUnit:Service/Controller 分支级契约(纯 Mockito,确定性);
+ *   - 本 spec:真实 HTTP + 真实 DB,验证「登录 → 家庭上下文 → 端点 → Result 外壳」主链路。
+ * 不在本 spec 覆盖:SC-B-04/B-11(LangGraph 报告解读/追问,见
+ *   cfc-langgraph/tests_contract/test_growth_report_contract.py)、SC-P-82(MCP JSON-RPC
+ *   需 Mcp-Api-Key,见 GlobalSearchScP82ContractTest)。
+ *
+ * 运行(默认远端;可用 CFC_API_BASE 指向本地 9082):
+ *   npx playwright test api/report-closedloop-contract.spec.js \
+ *     -c playwright.config.api.js --project=desktop
+ *   CFC_API_BASE=http://127.0.0.1:9082 npx playwright test api/report-closedloop-contract.spec.js \
+ *     -c playwright.config.api.js --project=desktop
+ *
+ * 安全约定:用例只自注册临时账号、只读写自己的数据;不打印 token / 手机号。
+ */
+const { test, expect } = require('@playwright/test');
+const { registerRole, apiPost, pickMemberByUserId, uniqueSuffix } = require('../helpers/api');
+
+test.describe('EVD-7 报告闭环 三类流(23 SC)', () => {
+  let parent;
+  let teacher;
+  let selfMemberId;
+  let teacherMemberId;
+
+  test.beforeAll(async ({ request }) => {
+    parent = await registerRole(request, 'parent', 'QA-EVD7-P' + uniqueSuffix());
+    const list = await apiPost(request, '/api/family/member/list', {}, parent.token);
+    expect(list.code, list.message).toBe(200);
+    const self = pickMemberByUserId(list.data, parent.userId);
+    expect(self, '成员列表应包含登录用户自身').toBeTruthy();
+    selfMemberId = self.id;
+
+    teacher = await registerRole(request, 'teacher', 'QA-EVD7-T' + uniqueSuffix());
+    const teacherList = await apiPost(request, '/api/family/member/list', {}, teacher.token);
+    expect(teacherList.code, teacherList.message).toBe(200);
+    const teacherSelf = pickMemberByUserId(teacherList.data, teacher.userId);
+    expect(teacherSelf, 'teacher 成员列表应包含自身').toBeTruthy();
+    teacherMemberId = teacherSelf.id;
+  });
+
+  // ==================== 正常流 ====================
+
+  test.describe('正常流', () => {
+    test('SC-C-06/P-24 报告列表按成员返回数组(只读)', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/list', { memberId: selfMemberId }, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data)).toBe(true);
+    });
+
+    test('SC-P-24/X-02 家庭报告列表返回数组', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/reports/family', {}, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data)).toBe(true);
+    });
+
+    test('SC-P-25/X-10 报告趋势返回 scores/dates 结构', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/nutrition/trend', { memberId: selfMemberId }, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(r.data && Array.isArray(r.data.scores)).toBe(true);
+      expect(r.data && Array.isArray(r.data.dates)).toBe(true);
+    });
+
+    test('SC-P-84 授权→查询→撤销闭环(成员级报告权限)', async ({ request }) => {
+      const grant = await apiPost(request, '/api/health/report/member-permission/grant',
+        { targetMemberId: selfMemberId, granteeUserId: parent.userId }, parent.token);
+      expect(grant.code, grant.message).toBe(200);
+      expect(grant.data).toBe(true);
+
+      const byMember = await apiPost(request,
+        '/api/health/report/member-permission/members/' + selfMemberId, {}, parent.token);
+      expect(byMember.code, byMember.message).toBe(200);
+      expect(byMember.data.map(String)).toContain(String(parent.userId));
+
+      const all = await apiPost(request, '/api/health/report/member-permission/list', {}, parent.token);
+      expect(all.code, all.message).toBe(200);
+      expect(Array.isArray(all.data)).toBe(true);
+
+      // 家庭管理员 visible-members 返回 null(全部可见语义);普通成员返回集合
+      const visible = await apiPost(request,
+        '/api/health/report/member-permission/visible-members', {}, parent.token);
+      expect(visible.code, visible.message).toBe(200);
+      expect(visible.data === null || Array.isArray(visible.data)).toBe(true);
+
+      const revoke = await apiPost(request, '/api/health/report/member-permission/revoke',
+        { targetMemberId: selfMemberId, granteeUserId: parent.userId }, parent.token);
+      expect(revoke.code, revoke.message).toBe(200);
+      expect(revoke.data).toBe(true);
+    });
+
+    test('SC-C-07/P-39/T-12 DAN 报告列表返回数组', async ({ request }) => {
+      const r = await apiPost(request, '/api/dan-report/list', { memberId: selfMemberId }, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data)).toBe(true);
+    });
+
+    test('SC-S-09/A-02 报告解析类型↔商品链接列表(服务商接入真实契约)', async ({ request }) => {
+      const r = await apiPost(request, '/api/report-parser/types/links', {}, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data)).toBe(true);
+    });
+
+    test('SC-X-13 报告转交请求列表返回 incoming/outgoing', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/transfer/list', {}, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data && r.data.incoming)).toBe(true);
+      expect(Array.isArray(r.data && r.data.outgoing)).toBe(true);
+    });
+
+    test('SC-T-03/T-23 代传确认(teacher 角色通过权限闸门后进入参数校验)', async ({ request }) => {
+      // teacher 属于代传上传者角色:通过 isProxyUploader 后,缺 draftId 返回业务错误而非「无权」
+      const r = await apiPost(request, '/api/health/report/proxy-confirm', {}, teacher.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('draftId');
+    });
+  });
+
+  // ==================== 异常流 ====================
+
+  test.describe('异常流', () => {
+    test('SC-P-25 趋势缺 memberId → memberId不能为空', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/nutrition/trend', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('memberId不能为空');
+    });
+
+    test('SC-P-24 指标对比缺 reportId → reportId不能为空', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/indicators', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('reportId不能为空');
+    });
+
+    test('SC-P-91 指标对比 reportId 不存在 → 报告不存在', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/indicators', { reportId: 999999999 }, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('报告不存在');
+    });
+
+    test('SC-A-02/A-16 解析检测缺 filePath → filePath 不能为空', async ({ request }) => {
+      const r = await apiPost(request, '/api/report-parser/detect', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('filePath');
+    });
+
+    test('SC-P-84 授权缺参数 → targetMemberId/granteeUserId 不能为空', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/member-permission/grant', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('不能为空');
+    });
+
+    test('SC-T-21/X-10 新成员无两次测评 → 对比返回业务错误', async ({ request }) => {
+      const r = await apiPost(request, '/api/assessment/compare/by-child', { memberId: selfMemberId }, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('两次');
+    });
+
+    test('SC-C-07/T-12 DAN 对比缺 uploadId → 缺少 uploadIdA 与 uploadIdB', async ({ request }) => {
+      const r = await apiPost(request, '/api/dan-report/compare', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('uploadIdA');
+    });
+
+    test('SC-X-13 转交审批缺 requestId → 请求ID不能为空', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/transfer/approve', {}, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('申请ID不能为空');
+    });
+
+    test('SC-T-03/X-02 确认不存在的草稿 → 草稿不存在或已归档', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/audit/confirm', { draftId: 999999999 }, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('草稿不存在');
+    });
+  });
+
+  // ==================== 权限流 ====================
+
+  test.describe('权限流', () => {
+    test('SC-C-06/X-02 报告列表无 token → 401', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/list', { memberId: selfMemberId }, null);
+      expect(r.status).toBe(401);
+    });
+
+    test('SC-X-13 转交列表无 token → 401', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/transfer/list', {}, null);
+      expect(r.status).toBe(401);
+    });
+
+    test('SC-P-67/T-03 代传确认无 token → 401(LOGIN_REQUIRED_PATHS 闸门)', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/proxy-confirm', { draftId: 1 }, null);
+      expect(r.status).toBe(401);
+    });
+
+    test('SC-C-07/T-12 DAN 列表非法 token → 401', async ({ request }) => {
+      const r = await apiPost(request, '/api/dan-report/list', { memberId: selfMemberId }, 'invalid-token-value');
+      expect(r.status).toBe(401);
+    });
+
+    test('SC-S-09 解析类型链接非法 token → 401', async ({ request }) => {
+      const r = await apiPost(request, '/api/report-parser/types/links', {}, 'invalid-token-value');
+      expect(r.status).toBe(401);
+    });
+
+    test('SC-P-67/T-23 家长非代传角色调用代传确认 → 无权', async ({ request }) => {
+      const r = await apiPost(request, '/api/health/report/proxy-confirm', { draftId: 1 }, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('无权');
+    });
+
+    test('SC-T-03/X-02 非草稿所有者确认他人草稿 → 无权确认他人创建的草稿', async ({ request }) => {
+      const pending = await apiPost(request, '/api/health/report/audit/pending', { page: 1, size: 20 }, parent.token);
+      expect(pending.code, pending.message).toBe(200);
+      const othersDraft = (pending.data || []).find((d) => String(d.userId) !== String(parent.userId));
+      if (!othersDraft) {
+        test.skip(true, '当前测试库无他人待审草稿,跳过越权确认用例');
+        return;
+      }
+      const r = await apiPost(request, '/api/health/report/audit/confirm',
+        { draftId: othersDraft.id }, parent.token);
+      expect(r.code, r.message).not.toBe(200);
+      expect(String(r.message)).toContain('无权确认他人创建的草稿');
+    });
+
+    test('SC-P-84/C-06 跨家庭成员报告查询 → 空列表(成员级权限隔离,不泄露)', async ({ request }) => {
+      // parent 传 teacher 家庭的成员 ID:非本人、非本家庭管理员、未授权 → 返回空列表而非他人报告
+      const r = await apiPost(request, '/api/health/report/list', { memberId: teacherMemberId }, parent.token);
+      expect(r.code, r.message).toBe(200);
+      expect(Array.isArray(r.data)).toBe(true);
+      expect(r.data.length).toBe(0);
+
+      const dan = await apiPost(request, '/api/dan-report/list', { memberId: teacherMemberId }, parent.token);
+      expect(dan.code, dan.message).toBe(200);
+      expect(Array.isArray(dan.data)).toBe(true);
+      expect(dan.data.length).toBe(0);
+    });
+  });
+});

+ 2 - 1
tests/playwright.config.api.js

@@ -23,7 +23,8 @@ module.exports = {
   outputDir: path.join(__dirname, '.api-artifacts'),
   reporter: [['list']],
   use: {
-    baseURL: 'http://cfc.iwintrue.com',
+    // 默认远端;本地复验时用 CFC_API_BASE 指向已启动的 cfc-backend(如 http://127.0.0.1:9082)
+    baseURL: process.env.CFC_API_BASE || 'http://cfc.iwintrue.com',
     headless: true,
     ignoreHTTPSErrors: true,
     actionTimeout: 15000,

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels