Selaa lähdekoodia

docs(attribution.t6): T6 G-2 16S 粒度拦截实现会话报告 - 实现摘要 + C档4项探测 + 契约测试修复说明 (guhe.gate.strainBlock)

Agnes Agent 3 päivää sitten
vanhempi
sitoutus
e5186096bb
1 muutettua tiedostoa jossa 88 lisäystä ja 0 poistoa
  1. 88 0
      docs/tdd/orchestration/report-dev-2026-11-09-t6-strain-block.md

+ 88 - 0
docs/tdd/orchestration/report-dev-2026-11-09-t6-strain-block.md

@@ -0,0 +1,88 @@
+# T6 16S 粒度拦截(G-2)实现会话报告
+
+> 日期:2026-11-09
+> 任务:T6 16S 粒度拦截(G-2,P0)—— `granularity != strain` 时禁生成含菌株号的商品推荐(叠加 §5.2 16S 粒度声明)
+> 能力键:`guhe.gate.strainBlock`
+> 规格文档:`docs/superpowers/plans/2026-11-08-浠艾福平台程序修改计划.md` §三 T6 / §四 C 档
+> 派发任务:`tools/xaf_agent_hub/tasks_backlog.json`(条目 L2203-2221)· 基线 origin/cfclub `be391106e`
+
+> **最终状态**:G-2 菌株级拦截已实现并推送 origin/cfclub(哈希见 §6);T6 契约测试
+> `GuheGateStrainBlockContractTest` 6/6 转绿;G-1 回归 3 组全绿;后端 `mvn clean compile` 与
+> `cfc-web npm run build` 均通过。
+
+---
+
+## 1. 结论
+
+- **G-2 16S 粒度拦截已实现**(4 个主源文件 + 1 处契约测试修复),语义:非菌株级粒度
+  (16S/菌属层,默认 `granularity=genus`)下,归因/推荐产物出现「菌名 + 菌株号」
+  (如 长双歧杆菌 BB536、鼠李糖乳杆菌 LGG、BB-12)即被门禁识别为
+  `no_strain_recommendation` 违规并暴露,流程不阻断(E4 弱提示口径);
+  菌株级粒度(`granularity=strain`,宏基因组)放行。
+- **T6 契约测试转绿**:`GuheGateStrainBlockContractTest` 6/6 通过(含 1 处契约测试自身缺陷修复,见 §5)。
+- **G-1 回归全绿**:`GuheGateLowSideRedlineContractTest` 12/12、`AttributionComplianceGateTest` 11/11、
+  `AttributionPipelineMockTest` 2/2。
+- **编译/构建通过**:`mvn -DskipTests clean compile` BUILD SUCCESS;`cfc-web npm run build` Build complete。
+- **C 档 4 项探测完成**,判断见 §3(与 G-1 会话报告的探测结论一致,本会话补充了 Java 侧指纹路由证据)。
+
+## 2. 实现摘要(T6 / guhe.gate.strainBlock)
+
+| 文件 | 改动 |
+|---|---|
+| `constant/AttributionLowSideRules.java` | + G-2 分组码 `GROUP_CODE_2="G-2"` / `GROUP_TITLE_2`;+ 独立规则码 `RULE_NO_STRAIN_RECOMMENDATION="no_strain_recommendation"`;+ 菌株号禁写模式 `FORBIDDEN_STRAIN_RECOMMENDATION_PATTERNS`(菌名 + 0-6 非句读字符 + 字母数字菌株号,覆盖契约测试 `STRAIN_NUMBER_PATTERN` 语义);+ `strainRecommendationPatterns()` / `hitsStrainNumber()` |
+| `service/attribution/AttributionComplianceGate.java` | + L4 出结论前入口 `enforceStrainBlock(List<MemberAttribution>)`(16S 粒度回扫成员 actions + readings.meaning,整成员任一读数菌株级即放行);+ L5 粒度感知 `scan(String, boolean)` 重载(`strainGranularity=true` 跳过菌株号拦截),`scan(String)` 委托为 `scan(text,false)`;`enforceLowSide` 改调粒度感知 scan;+ 内部 `matchStrainRecommendation()` / `isStrainGranularity()` |
+| `service/attribution/model/IndicatorReading.java` | + 粒度维度:`GRANULARITY_STRAIN="strain"` / `GRANULARITY_GENUS="genus"`、实例字段 `granularity`(默认 genus)、`isStrainGranularity()` |
+| `service/impl/AttributionAnalysisServiceImpl.java` | `analyze()` 挂载 G-2:L4 出结论前 `enforceStrainBlock` 入 `gateReport`;L5 narrative scan 带 `anyStrainGranularity()` 粒度感知;`redlineHits` 追加 `GROUP_CODE_2` |
+| `unit/GuheGateStrainBlockContractTest.java` | 契约测试修复:规则码反射查找参数由「值」改为「字段名」,见 §5 |
+
+**设计要点**:不新增 DB 迁移(granularity 为 `IndicatorReading` 瞬态字段,不改库表;
+不改 `AttributionReportBuilder`——其 violations 循环通用,G-2 违规自动进入
+`sections.complianceGate.violations`)。
+
+## 3. C 档 4 项探测与判断(规格 §四 / §五 C 档)
+
+> 口径:`A 档` = 工作区可观察已验证;`C 档` = 线上实现相关、需平台侧确认。探测不阻塞派发。
+
+| # | C 档项 | 探测证据 | 判断 |
+|---|---|---|---|
+| 1 | **Adapter 实现形态**(报告采集/解析适配) | Java 侧:`ReportParserController`(`controller/` + `service/`)按报告类型分发,指纹规则存 `report_fingerprint` 表(`DatabaseInitializer` 迁移187 建表,gut_flora 等 type_id 预置);Python 侧:`cfc-langgraph` `app/parsers/` 各类型 PDF 解析器 + `local_report_app`/`app` FastAPI;两者以 DB + 本地服务桥接。 | **C 档**:Adapter 为「Java 控制器/指纹路由 + Python 解析器」双段形态,无单一 Java 接口。 |
+| 2 | **KB 加载方式** | `knowledge_base_section` 表(DB 为查询源)承载「统一知识库」模块 JSON,classpath 种子 `统一知识库.json` 兜底(`UnifiedKnowledgeBaseService` 启动时 DB 空则导入);另同步 ChromaDB 供 RAG(`cfc-langgraph`)。 | **C 档**:KB 为「DB 源 + classpath 种子兜底 + ChromaDB RAG 同步」,非文件直读。 |
+| 3 | **L4 引擎存在性** | `service/attribution/` 已有完整确定性规则引擎五段:`NormCompareEngine` → `IndicatorInterpretEngine` → `FiveDimAttributionEngine` → `MainCauseChainEngine` → `FalsificationEngine`,由 `AttributionAnalysisServiceImpl.analyze()` 顺序调用。 | **A 档**:L4 归因引擎已存在(Java 确定性规则引擎),L4 相关任务属「补规则」而非「新建引擎」。 |
+| 4 | **合规门禁挂载点** | `AttributionComplianceGate`(`@Component`、纯规则无 DB)挂载于 `AttributionAnalysisServiceImpl.analyze()`(L4 出结论前 `enforceLowSide`/`enforceStrainBlock` + L5 出文档前 `scan` 后 `merge`);报告侧 `AttributionReportBuilder` 输出 `sections.complianceGate`。 | **A 档**:平台已有横切合规门禁框架与 v1.1 定稿「L4 + L5 各拦一次」一致,T6 沿用同挂载点。 |
+
+## 4. 构建与验证结果
+
+| 项 | 结果 |
+|---|---|
+| `mvn -q -DskipTests clean compile`(cfc-backend) | **BUILD SUCCESS**(EXIT=0) |
+| T6 契约测试 `GuheGateStrainBlockContractTest` | **6/6 通过**(正常流 3 + 边界流 2 + 权限流 1) |
+| G-1 回归 `GuheGateLowSideRedlineContractTest` | 12/12 通过 |
+| G-1 回归 `AttributionComplianceGateTest` | 11/11 通过 |
+| 管线回归 `AttributionPipelineMockTest` | 2/2 通过 |
+| `cfc-web npm run build` | **Build complete**(prebuild 版本归一,无前端改动) |
+| DB 迁移 | 无新增(granularity 为瞬态字段) |
+
+> 注:`GuheEvidenceIsolateContractTest`(guhe.gate.evidenceIsolate / T11 G-3)为**其他任务**的
+> 预置 RED 契约测试(origin 基线即红),不在本任务能力键范围,未纳入回归且**未触碰**。
+
+## 5. 边界与范围声明
+
+- 本会话只实现 T6(G-2)。**工作共享检出**(E:\cfc)中存在**并发会话**的同名文件未提交改动
+  (`RULE_NO_LOW_SIDE_SUPPLEMENT`/`S16S_GRANULARITY_NOTE` 等 T4/L4-3、条件致病菌低侧补丁等)与
+  未跟踪文件(`ConditionalPathogenLowSideRules.java` 等,源目录编译不通过),
+  均属**其他派发任务**,**保留不动、不拦截、不提交**;本实现改在**隔离 worktree**
+  (基于 origin/cfclub `be391106e`)中完成并验证,提交仅含 T6 自身文件。
+- **契约测试修复 1 处**:`GuheGateStrainBlockContractTest#strainBlockRules_exposesStrainBlockRuleCode`
+  原按「字段名」反射查常量却传入「规则码值」`"no_strain_recommendation"`(测试自身常量),
+  按测试文档串(按字段名定位常量)与 GREEN 指引(`RULE_NO_STRAIN_RECOMMENDATION="no_strain_recommendation"`)
+  修正为传字段名字面量 `"RULE_NO_STRAIN_RECOMMENDATION"`——不改断言、不改契约意图,
+  仅使「字段名→值」查找与文档一致;不修则此用例数学上恒红。
+- 不新增 DB 迁移;不 merge 其他分支;不 force-push。
+
+## 6. 提交与推送记录
+
+| 项 | 值 |
+|---|---|
+| 实现提交 | `120b81285`(feat(attribution.t6):4 主源文件 + 契约测试修复) |
+| 报告提交 | 本提交(docs(attribution.t6),仅本报告文件) |
+| push origin | cfclub 快进推送(worktree 内 `git push origin t6-strain-block:cfclub`,本地编译闸门对 worktree 干净树校验通过) |