Files
dpb/doc/桃育种系统统计引擎实施记录.md
T
34047007@qq.com b95053c52c init: 初始化 dpb 桃育种系统代码库
前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
2026-08-06 00:17:49 +08:00

269 KiB
Raw Blame History

桃育种系统 · 统计引擎实施记录

版本v1.42026-08-04 追加统计严谨·预测完整性与 MLOps 复现性:PA 落库 / 溯源 / germplasm_id 填充 / 砧木扩列 / Calo 相关校正 / 空间竞争协变量 + 组合得失漏斗) 定位:记录统计引擎多轮 P0/P1 落地 + 田间刚需(花粉档案)+ 决策正确性(无性系级指数)+ 统计严谨(配合力交配设计 / 相关校正 / 空间竞争)+ MLOps 复现性 + 组合得失漏斗的实现、验证与文件清单——G×E 交互引擎2026-08-03)、性状方向标注2026-08-04)、花粉档案2026-08-04)、无性系级指数2026-08-04)、配合力交配设计2026-08-04)、统计严谨·MLOps 复现性2026-08-04,①Calo②PA③溯源④germplasm_id⑤砧木⑥空间竞争)与组合得失漏斗2026-08-04,⑧ v_combination_funnel)。本文档为持续追加的落地台账,与规格文档 桃育种系统模块扩展需求规格.md(v2.10)配套;规格管"应该长什么样",本文管"实际落地了什么、怎么验证的"。 相关探针Temp/claude/e2e_gxe_20260803.pyG×E5 场景)· Temp/claude/e2e_direction_20260804.py(方向标注,7 组)· Temp/claude/e2e_pollen_20260804.py(花粉档案)· Temp/claude/e2e_clone_index_20260804.py(无性系级指数,6 组)· Temp/claude/e2e_combining_design_20260804.py(配合力交配设计,5 组)· Temp/claude/e2e_prediction_rigor_20260804.py(②③④,4 组)· Temp/claude/e2e_rootstock_20260804.py(⑤)· Temp/claude/e2e_corr_spatial_20260804.py(①⑥,3 组)· Temp/claude/e2e_combination_funnel_20260804.py(组合得失漏斗,3 组)。


一、G×E 交互引擎 P02026-08-03

1.1 背景与目标

复审清单第 2 条要求基因型×环境(G×E)交互随机效应显式建模。桃为多年生多年多点(MET)试验作物,同一克隆/家系在跨点、跨年表现往往相反(如 c1 在 A 站高、B 站低,c2 反之),若只估主效应会系统性误排 EBV。本轮在 run_ablup 上扩展 G×E 模式(method=GXEBLUP),并补齐可辨识性门禁与异步任务记录。

1.2 引擎能力(statistics/service.py::run_ablup

参数 取值 行为
gxe True / False True 走 GXEBLUP(含 G×E 随机互作);False 回归纯 ABLUPG×E 项关闭)
gxe_env site / year 环境维度。site 自动入固定效应 trial_studyyear 自动入固定效应 year
method GXEBLUP / ABLUP 按 gxe 开关自动落库;model_name 形如 GXEBLUP_{trait}_{env}_{ts}
fixed_effects 列表 调用方显式指定时与自动效应合并

G×E 落库输出(breeding_prediction.note JSON

  • sigma_gxe:G×E 方差分量 σ²gxe(>0 表示存在交互)
  • gxe_ratio:σ²gxe 占比
  • n_cross_env:跨环境基因型数(有多少基因型至少在 2 个环境中观测)
  • skipped:跳过明细(如缺站点株数)

记录级 vs 基因型级

  • 家系分组(无 clone)时基因型=组合,G×E 记录逐树;year 模式记录级 = (树,年) 逐条(train_n 为记录数,EBV 行按树写)。
  • 克隆坍缩(见 1.5)时基因型=clone,多株坍缩为基因型节点。

1.3 自动固定效应

gxe_env 自动固定效应 说明
site trial_study 站点由 trial_study_id 解析(缺站点的株记录跳过并写 skipped
year year 年份由观测 evaluate_year 解析

调用方仍可用 fixed_effects 显式追加(如 ["trial_study"]),引擎合并去重。

1.4 可辨识性门禁(G×E 不可辨识 → 409,拒绝运行)

门禁 触发 处置
无跨环境重复 没有任何基因型在 ≥2 个环境出现(n_cross_env == 0 G×E 不可辨识:无任何基因型跨环境重复。拒绝运行。
单元内无重复 每个(基因型×环境)单元仅 1 条观测,σ²gxe 与残差混杂 无任何基因型×环境单元内重复(每格仅 1 条观测…)
无可分环境记录 所有记录缺站点/年份 G×E 分析无可分环境的记录

门禁拒绝时在 StatisticsJobModel 落一条 status=FAILED + error_msg(同步 409 抛出,异步失败可查)。

1.5 克隆坍缩

同 clone 经扩繁的多株 tree 在 G×E 模式下坍缩为基因型节点 c{clone}G×E 专用系谱 gxe_pedigreec{clone} 为个体,父母指向组合亲本(或树亲本);record_map 全部映射到 c{clone}。同 clone 各株 EBV 一致(重复测量聚合,杜绝自由度虚高)。

1.6 异步任务记录(StatisticsJobModel

字段 说明
job_type GXE / ABLUP/ COMBINING 等) 任务类型
status SUCCESS / FAILED 任务状态
result_ref prediction id 关联结果
error_msg 文本 失败原因(可辨识性门禁消息亦落此)

1.7 验证(Temp/claude/e2e_gxe_20260803.py5 场景全过)

场景 数据 断言要点
[1] site-G×E 家系分组 2 组合×2 站×3 株,无 clone 自动 fixed={trial_study}method=GXEBLUP、σ²gxe>0、n_cross_env=2、train_n=12、EBV 行=12、job_type=GXE SUCCESS
[2] 不可辨识门禁 各组合仅单站 409 G×E 不可辨识:无任何基因型跨环境重复、job FAILED + error_msg
[2b] 单元内无重复 2 基因型×2 站每格 1 株 409 含 单元内重复、job FAILED
[3] year-G×E 2 clone×2 年交叉互作 自动 fixed={year}、train_n=16(记录级)、EBV 行=8(树级)、σ²gxe>0、n_cross_env=2
[5] 克隆坍缩(site 2 clone×2 站×每格 2 株 record_map 全为 c{clone}、同 clone EBV 相同、train_n=8、EBV 行=8
[4] 回归 gxe=False 同 [1] 数据 method=ABLUP、显式 fixed_effects=["trial_study"]、EBV 行=12、job_type=ABLUP SUCCESS

测试基座用 _spy_solve 包一层真引擎(monkeypatch blup.solve),捕获 fixed/record_map kwargs 后仍跑真解,验证引擎传参;GATE_RELAX=dict(min_clone_n=1, min_pedigree_rate=0.0, max_missing_rate=1.0) 放开数量门槛专注验证 G×E 逻辑。


二、性状方向标注 direction / into_ebv / default_h22026-08-04

2.1 缺陷背景(科学正确性硬伤)

bre_trait 原仅 stage/is_core无方向标注。选择指数与决策默认"高 EBV = 优",对低优性状(裂果率、病害级别、酸度——若目标是低酸)会选反Smith-Hazel 的 b 与加权 Z 隐含"越大越好"。用户确认缺陷属实,拍板修复范围:

  • 翻转范围:指数+决策+排行全翻转
  • into_ebv 范围'0' 仅从选种相关候选剔除(指数/EBV 排行/决策预览/ABLUP 下拉),describe/correlation/trait_values 不受影响;
  • default_h2 兜底zsum + smith_hazel 都兜底(无实测 h² 用先验,两者皆无才报错)。

2.2 数据模型变更

bre_trait 新增三列(幂等 ALTERbackend/sql/weld_trait_direction.sqlcreate_all 只建新表,新列须手写 SQL):

类型 默认 说明
direction varchar(16) 'desc' 性状方向:desc=越大越好 / asc=越小越好
into_ebv varchar(1) '1' 是否选种目标:1=进 EBV/指数/决策候选 / 0=仅记录
default_h2 double precision NULL 先验遗传力 h²(指数无实测 h² 时兜底;桃经典先验,可在性状字典改)

种子数据(backend/sql/bre_trait_seed.sqlINSERT 0 43ON CONFLICT DO UPDATE 含三新列)

  • 7 个数值 core 性状(max/avg_fruit_weight、longitudinal/transverse/lateral_dia、flesh_thickness、ssc):direction='desc'into_ebv='1'default_h2 取桃经典先验(果重/糖度 0.5、果径/肉厚 0.4/0.3);
  • 其余 categorical/date 性状:into_ebv='0'default_h2=NULL

ORM/API 透传TraitModel/TraitBaseSchema/TraitUpdateSchema/TraitOutSchema/TraitQueryParam 补齐三字段;batch_export mapping_dict、batch_import header_dict/fieldsdirection/into_ebv 缺省 'desc'/'1'、default_h2 _to_floatrequired_headers 仍只校验原 14 键,兼容旧模板)、import_template_download 选项同步。

2.3 后端翻转逻辑(statistics/service.py

辅助 _trait_meta_map(codes=None){trait_code: {direction, into_ebv, default_h2}},供指数/决策/排行共享方向语义。

模块 变更
list_traits(core_only, selection_only) select 新增三字段;selection_only=Truewhere(into_ebv == "1")controller 加 selection_only query 参数)
selection_index cols 剔除 into_ebv='0' 写入 extra["dropped"](用户可见提示)
_weighted_z_indexzsum z 标准化后对 asc 性状取负z = -z),统一"越大越优"use_h2 兜底 h = herit.get(c) or default_h2
_smith_hazel_index h² 取 h_eff[c] = 实测 h² or default_h2h_eff[c] is None 才 409缺实测且无先验 default_h2: …);a 归一化后对 asc 元素取负
run_ablup 写时 rank 排序 reverse=(direction != "asc")EBV 排行即优度序)
ebv_ranking 读时重排(见 §三)
clone_ranking 按当前方向重排 ebv_meanreverse=(direction != "asc")
decision_preview _top_ninto_ebv='0' 直接返回空集;ranked 按方向取最优前 N(asc 取 EBV 最小);op 缺省 <=asc/ >=desc),pheno 与 ebv 共用
compare_predictions 轮次对比 rank 排序方向感知(见 §三)

2.4 前端

文件 变更
api/module_bre/statistics.ts listTraits(coreOnly, selectionOnly)selection_only 参数
views/module_bre/statistics/index.vue selTraitslistTraits(true, true))仅用于指数权重/EBV 批次/ABLUP-G×E 性状下拉,与 describe/correlation 共享的 traitSel 解耦(后者保留全量);asc 性状标签加 '↓越小越优' 角标
views/module_bre/trait/index.vue 表单/表格/详情/搜索四处加 direction el-selectdesc/asc+文案)、into_ebv 开关、default_h2 输入
views/module_bre/selection_rule/index.vue conditions_json 文本框说明:"op 缺省按性状方向(desc≥ / asc≤),rank_top_n 按方向取最优前 N"

2.5 验证(Temp/claude/e2e_direction_20260804.py7 组全过)

基座 4 性状 dA(desc,1,0.5)/bB(asc,1,0.25)/cC(desc,0,None)/dD(desc,1,None) + 4 批次 pA(h²=0.5)/pB/pC/pD(h²=None) + 12 株 EBV=[10.0..32.0] 升序。

验证点 断言要点
[1] list_traits 三字段 + selection_only 返回 direction/into_ebv/default_h2selection_only=True 过滤 into_ebv='0'
[2] zsum 方向翻转 同数据 desc→asc 排名精确互反(top2 从最高 EBV 2 株翻为最低 2 株)
[3] into_ebv='0' 剔除 权重含 cC → 结果 traits 不含 cC、result_json.dropped 有提示
[4a] smith_hazel default_h2 兜底 批次 pD h²=None 但性状 dD 带 default_h2=0.25 → 成功
[4b] smith_hazel 无实测无先验 批次无 h² 且性状无 default_h2 → 409 缺实测且无先验
[5] decision rank_top_n 方向 asc 命中 EBV 最低 2 株、desc 命中最高 2 株;无 op 时 asc 走 <=
[6] ebv_ranking 读时重排 性状事后改方向后按当前方向重排(rank 按优度重编号)
[7] compare_predictions 方向感知 asc 反序两批 rank1=最低 EBV 株(cur_ebv=10.0)desc 反序两批 rank1=最高 EBV 株(32.0)

三、本轮修复的结构性 bug(方向盲区家族)

同一缺陷模式——"高 EBV = 优"硬编码——在排行/对比链路还有两处遗留,本轮一并修复:

3.1 ebv_ranking 方向盲区(读时重排)

原实现只在 direction=="asc" 时重排,desc 信任写时持久化 rank。当性状事后改方向(如 bB 由 asc 改 desc),已落库批次 rank 仍是 asc 序 → 读回倒序、最低 EBV 排第一。修复:读时始终按 predicted_value + 当前 direction 重排并重编号 rank,且 self.db.expunge(r)——因为 GET 会话走 session.begin()(退出自动提交),不 expunge 会把重排后的 rank 写回库,破坏"GET 纯读"。

3.2 compare_predictions 硬编码降序

原实现两处排序 reverse=True(写死高 EBV=rank 1)。对 asc 性状展示的 rank 列会把最差株显示为第 1(Spearman 相关/位移量对反转不变量,但暴露的 rank 列是错的)。修复:读 trait directionreverse = (direction != "asc") 同时用于 rank_cur 与 rank_prevcorr/flip 判定对反转不变量保持不变。


四、花粉档案 breeding_pollen2026-08-04

4.1 缺陷背景(田间刚需)

用户反馈:桃花期仅 37 天,父本花粉是杂交季命脉,但代码里没有 bre_pollen 表(仅在测试文件提及),bre_pollination 有花朵数/坐果数/去雄/套袋,却无花粉采集日期、贮藏方式(-20℃/液氮)、活力检测(TTC 染色率/离体萌发率%)、授粉窗口计划。后果:明年复盘"这批坐果为什么低"毫无抓手。核验属实(比描述更严重:一期文档规划的 pollination_method/pollen_source/pollen_viability 三字段也全未实现)。

4.2 架构决策(用户确认)

决策点 拍板 理由
父本锚点 树级 male_tree_id FK→bre_tree(与 pollination.male_tree_id 一致) 单父本溯源;混合/外地采集时为空 + source_type 区分
活力建模 单值+方法viability_method[ttc/germination]+viability_pct+viability_test_date 不建子表,够用且简单
窗口计划 派生有效期+校验collect_date+expiry_date;窗口=[采集日,失效日] 由 pollination 校验) 不建独立计划表;/bre/pollen/available_lots 提供"当前花期可用批次"

4.3 数据模型(backend/sql/weld_pollen.sql,幂等 DDL + create_all 注册)

新表 bre_pollenlot_code UNIQUE / male_tree_id FK SET NULL / source_type tree|mixed|external / collect_date / collect_method / quantity / storage_method fridge|minus20|minus80|liquid_n2 / viability_method ttc|germination / viability_pct / viability_test_date / expiry_date / remark+ ALTER bre_pollination ADD pollen_lot_id integer REFERENCES bre_pollen(id) ON DELETE SET NULL + ADD pollination_method varchar(32)(补一期文档规划但遗漏的授粉方式)。

ORMmodule_bre/pollen/ 五件套(model/schema/crud/service/controller),路由前缀 /bre/pollenmodule_bre/__init__.py 注册 PollenRoutercreate_all 经 import 链自动拾取新模型)。

4.4 服务层关键逻辑(pollen/service.py + pollination/service.py

逻辑 实现
去重 _check_code:批次号存在 → 409「已存在」(create/update/batch_import 均走)
FK 校验 assert_parents_exist(父本树不存在→409自动跳过 None,可空 male_tree_id 安全)
标签填充 _attach_fk_labelsmale_tree_id→tree_no;授粉侧 pollen_lot_id→lot_code
授粉窗口校验 _validate_pollen_window:授粉日期须在批次 [collect_date,expiry_date] 内,否则 409「授粉日期 X 不在花粉批次 Y 的授粉窗口 [A ~ B] 内」;update 时字段未变沿用库内现值
可用批次 available_lots(date_on):返回窗口内批次(label 含窗口区间+活力%),缺省今天

4.5 菜单/权限(backend/sql/bre_menu.sql

菜单 900056 花粉档案(parent 900030 杂交配组,hiddenroute /bre/pollencomponent module_bre/pollen/index
按钮 E 段 900601-900608module_bre:pollen:detail/query/create/update/delete/export/import/download
角色关联 SUPER_ADMIN/ADMIN 范围扩至 900600-900699

4.6 前端

文件 变更
api/module_bre/pollen.ts PollenAPI 全套 + getAvailableLots(授粉窗口下拉)
views/module_bre/pollen/index.vue 花粉 CRUD 页(贮藏/活力/采集方式下拉、采集/测定/有效期日期、活力% 数字)
views/module_bre/pollination/index.vue 表单/表格/搜索加 pollen_lot_id(批次下拉)+ pollination_method(授粉方式下拉)
views/module_bre/_shared/StageView.vue + stage_cross/index.vue 杂交配组第三标签「花粉档案」

4.7 验证(Temp/claude/e2e_pollen_20260804.py 全过 + vue-tsc

断言
[pollen.create] male_tree_no 标签=T015108、活力 85.5% 回填、窗口落库
[dup] 409「花粉批次号 … 已存在」
[fk] 409「采集父本树不存在或已被删除」
[list/detail/options/available_lots] 均含新批次;available_lots 返回窗口内批次
[pollination 窗口内] create 成功、pollen_lot_no 标签、授粉方式回填
[window 窗口外] 409 含「授粉窗口 [2026-07-01 ~ 2026-09-30]」
[update/delete] 授粉日期改窗口内仍通过;pollen update 活力/有效期生效;软删生效

五、选择指数·无性系级聚合(2026-08-04)

5.1 决策正确性背景

用户提出决策正确性缺陷:selection_index 对每个 tree_id 算指数并排名、apply_selection 写每株,但桃是无性繁殖——一个 clone 经扩繁的多株遗传同质,应聚合为一个遗传实体再排名。后果:同一个优系 3 株可能被拆成 3 个独立指数条目,可能只选中其中 1 株而漏掉该系其他株,也不利"系级决选"。用户拍板:指数前先按 clone 聚合 EBVmean/max 由可靠性加权),在 clone 级算 Smith-Hazel,再决定入选 clone。

自株退化(工程补充)tree.clone_id 在实生苗阶段可空(v2.2/A1 决策),若把无 clone 的株全部剔除,实生苗阶段选择会塌缩。故未晋升 clone 的实生株退化为自株单元key=-tree_id,每株独立参与指数与决选),入选命中规则 stage 时晋升建 clone。

5.2 数据模型变更

无表结构变更(复用 tree.clone_id + breeding_prediction_value 既有字段)。仅接口与计算层变更:

接口 变更
SelectionIndexIn.aggregate 新增:clone(默认,无性系级)/ tree(旧单株级行为保留)
selection_index 响应 每条 top 项含 clone_id/clone_code/n_trees/tree_idsclone 级);tree 模式含 tree_id;整体 "aggregate" 回显

5.3 聚合与排名逻辑(statistics/service.py

_clone_units(cols, tree_ids, ebv_by_trait, pheno_by_trait, rel_by_tree)——聚合单元构造:

  • tree.id/clone_id/tree_no(限定 tree_ids)→ 按 clone_id 分桶,空桶自株 key=-tree_id
  • 单元 ebv_src[c][key] = 可靠性加权 Σ(ebv×rel)/Σ(rel)(桶内每 trait 各算一份),全 rel=0 回退简单均值;
  • 单元 pheno_src[c][key] = 简单均值(smith_hazel 表型均值用);
  • 返回 [{key, clone_id, label, n_trees, tree_ids}]

排名单位切换zsum / Smith-Hazel 改为在单元 key 集上计算(ebv_src/pheno_src 取数),方向感知沿用 v2.3(统一越大越优);Smith-Hazel 的 G 矩阵 pair 相关仍由树级 ebv_by_trait 抽样估计,b = P⁻¹Ga 在 clone 单元上评分。响应组装把单元字段映射回每条 top(tree 模式还原 tree_id)。

apply_selection 按遗传实体写

  • top 项可能是 clone 级(tree_ids)或旧树级(tree_id),统一构建 units
  • 每单元 rel = min(rel_by_tree.get(t, 1.0) for t in u_tids)(保守:最弱证据株门控全系);
  • 写一条 selection_resultclone_id 指向全系(self 为 NULL+ tree_id 溯源一株(优先已有记录株)+ reason 含「系内N株」;
  • 入选单元命中规则 stage → _promote_tree_to_clone(首株, stage) 幂等晋升建 clone(复用既有 clone、推进 stage),self 株由此回填 clone_id

5.4 前端

文件 变更
api/module_bre/statistics.ts selectionIndex data 类型加 `aggregate?: 'clone'
views/module_bre/statistics/index.vue 工具栏「聚合:无性系级/单株级」radio(默认无性系级)+ 说明文案(桃无性繁殖默认;未晋升实生株按单株参与);clone 模式结果表显示 clone_code/clone_id/n_trees/涉及单株

5.5 验证(Temp/claude/e2e_clone_index_20260804.py6 组全过)

基座:目标/组合/2 cloneX=2株 T1T2、Y=2株 T3T4+ 2 自株(T5T6+ 2 性状 A(desc) B(asc) + 2 批次。A 系 EBVT1=10(rel.1)/T2=30(rel.9) 加权 28T3=20(rel.9)/T4=40(rel.1) 加权 22——可靠加权 X 排 Y 前,简单均值则 X20<Y30 反序,验证加权是有效差异而非巧合。

验证点 断言要点
[1] clone 聚合单元 + 可靠加权排名 6 株 → 4 单元;clone 单元 n_trees=2/tree_ids 正确;自株 key 独立;X(加权28) 排 Y(加权22) 前
[2] tree 模式兼容 aggregate="tree" 返回 6 条含 tree_iddesc 首=EBV 最高株 T4
[3] 方向翻转 clone 级 A 改 asc → top 精确互反,首=最低聚合 EBV 的 T5 自株
[4] smith_hazel clone 级 b 含 A/Btop 含 clone 单元(n_trees/tree_ids 正确)
[5] apply_selection clone 级写入 top_n=2 → 写 2 条决选:cloneX 一条(clone_id + 溯源 T1/T2 之一 + reason「系内2株」)+ self T6 一条
[6] apply 晋升建 clone top_n=4 含自株 → T5/T6 命中 sp 规则晋升建 cloneclone_id 回填);clone X 株 stage 推进 sp

科学正确性收口:指数排名单位与决选写入单位统一为遗传实体——同一优系多株不会再被拆散、单株误选漏选;自株退化保住实生苗阶段选择能力,且入选即晋升、天然补上 clone 归属。


六、配合力交配设计 design_type2026-08-04

6.1 缺陷背景(统计严谨)

用户指出统计严谨缺陷:combining.solve 只实现 Griffing 对称全双列model A),但 run_combiningbre_combining_ability没有 design_type 字段区分完全双列 / 部分双列 / line×tester(NCII) / NCIII。后果:用 line×tester 设计时,GCA/SCA 算法与 ANOVA 自由度都与全双列不同,当前一律按全双列算会算错(自由度错、GCA 含互反/自交效应)。用户拍板修复:bre_cross_combination / bre_combining_abilitydesign_typecombining.solve 按设计分支(line×tester 用 NCII 双因素模型)。

6.2 数据模型变更

bre_cross_combinationdesign_type varchar(16) NULL(缺省按 full_diallel 计);bre_combining_ability 同步落 design_type。取值硬编码校验(同 selection_index.method,非 sys_dict):full_diallel(完全双列,默认)/ partial_diallel(部分双列)/ line_testerline×tester NCII/ nciiiNCIII 测交)。DDL 见 backend/sql/weld_combining_design.sql(幂等 ALTER + COMMENT)。create/update 接受 code 或中文标签并归一化,非法值 409(交配设计取值不合法)。

6.3 求解器分支(scripts/breeding_stats/combining.py

设计 模型
full_diallel / partial_diallel Griffing 对称全双列 model Ay_ij = μ + g_i + g_j + s_ij,Σg=0 约束,最小二乘 BLUE
line_testerNCII 双因素模型 model By_ij = μ + l_i + t_j + (lt)_ijparent1=line(母本)、parent2=tester(父本),分别 Σl=0 / Σt=0SCA = line×tester 互作 = 残差
nciii 同一 model B,门槛 tester 恰好 2 个

工程要点:

  • 可辨识性tester 列从索引 1+n_l 起 → 显式列选择(非连续切片);基线列切出后吸收剩余列。
  • 顺序 ANOVASS 型)SS_lineintercept→line)→ SS_tester(→tester after line)→ SS_sca(残差);df_line=n_l-1、df_tester=n_t-1、df_sca=n-1-df_line-df_tester。输出 design/roles/df_line/df_tester/df_sca
  • 门禁:同亲本既作 line 又作 tester(角色重叠)→ ValueError → 任务 FAILED + CustomException「角色重叠」;NCIII tester≠2 → 拒绝。
  • gca_se 持久化GCA 标准误内嵌 anova_json["gca_se"](避免 DB 迁移,gca_json/sca_json 形状稳定);前端 GCA 表加 SE 列。

6.4 运行过滤与持久化(statistics/service.py::run_combining

run_combiningdesign_type 参数透传 combining.solve按设计过滤组合——只纳入 cc.design_type or 'full_diallel' == dt 的组合,杜绝全双列标注组合混入 line×tester 运行(混算根因)。bre_combining_ability.design_type 随结果落库,anova_jsondesign 供前端分显示。

6.5 前端

文件 变更
api/module_bre/statistics.ts RunStatsPayload.design_type?: string(配合力运行时下发)
api/module_bre/cross_combination.ts 查询/表格/表单类型加 design_type
views/module_bre/statistics/index.vue 运行对话框「交配设计」radioDESIGN_LABELS 四选项 + 说明);配合力批次表「设计」列;详情 ANOVA 按 a.design 分支——NCII/NCIII → line/tester/互作 F 与 p + roles 计数,双列 → GCA FGCA 表 SE 列;SCA 表展示
views/module_bre/cross_combination/index.vue 表单/表格/详情/搜索四处 design_typeradio + DESIGN_LABELS 中英映射,createInitialFormData 默认 full_diallel

6.6 验证(Temp/claude/e2e_combining_design_20260804.py5 组全过 + vue-tsc

基座:数值性状 + 目标 + 6 亲本;NCII 2×2line_tester 4 组合)+ NCIII 2×2nciii 4 组合)+ 1 条 full_diallel(应被 line_tester 运行排除)。

验证点 断言要点
[1] NCII line_tester 运行 design_type 落库;anova.design=line_testerdf 1/1/1roles.lines/testers 正确;平衡 2×2 精确解 gca{l1:-2,l2:+2,t1:-1,t2:+1}SCA 恰 4 条;E2EDTMIXfull_diallel)被排除;anova.gca_se 内嵌
[2] NCIII 分支 只纳入 nciii 标注组合;同一双因素模型;df_line/df_tester=1SCA 4 条;gca{n1:-2,n2:+2}
[3] 角色重叠 gate 同亲本作 line 又作 tester → 任务 FAILED + CustomException 含「角色重叠」
[4] create/update 校验 line_tester→原样、中文「完全双列」→归一化 full_diallelbogus_design→409、update→nciii
[5] 持久化复查 commit 后新会话 design_type / anova.design / gca_se 均真实落库

科学正确性收口:配合力计算不再默认"一律全双列"——line×tester(NCII)/NCIII 走双因素模型,GCA/SCA 与 ANOVA 自由度按设计正确计算;运行层按 design_type 过滤组合,杜绝混算;角色重叠直接拒绝,消除亲本角色语义错误。待办partial_diallelGriffing model 4,无互反)与 model 3(含互反、需单株表型)本轮未单独实现,随使用按需补。


七、统计严谨·预测完整性与 MLOps 复现性(v1.42026-08-04

7.1 缺陷背景(七条复审逐条核实)

用户抛出七条统计严谨/完整性复核主张,逐条对照代码核实均为真缺陷后按优先级落地(便宜且值得马上补 ②④ → 中期 ③⑤ → 需新能力 ①⑥):

# 主张(核实) 落地
bre_prediction_value 只存 reliability,未存预测准确度 PA pa = √reliability;批次 bre_prediction.accuracy 改填真 PA
PredictionValueModel.germplasm_id 永未填充run_ablup 只写 tree_id 写 EBV 行时回填 tree.germplasm_id,亲本级 EBV 查询可用
bre_prediction 无 data_version / 输入哈希 / 引擎版本,MLOps 溯源不全 加三字段 + 确定性输入哈希,同数据重跑一致、改观测必变
bre_rootstock 仅 code/name/remark,无矮化类、砧穗亲和性 dwarf_class + compatibility,全链路透传
Smith-Hazel 的 G 矩阵用"EBV 皮尔逊相关"近似(无真 MT-BLUP Calo 可靠性校正 r_g = r_EBV/√(rel_i·rel_j)(真 MT-BLUP 记遗留)
果园株间竞争 / 边缘效应未建模 run_ablup 新增 covariate="competition"Chebyshev 邻域株数)
前端 D 层 _coming_soon 占位页 保持占位属预期P2 远景,本轮不动)

7.2 数据模型变更(backend/sql/weld_prediction_rigor.sql + weld_rootstock.sql

类型 说明
bre_prediction_value pa double precision 预测准确度 PA = √reliability(每株每性状)
bre_prediction data_version varchar(32) 数据版本(_DATA_VERSION="v2.7"service.py
bre_prediction input_hash varchar(64) SHA256{tree_id}:{均值表型} + {个体}|dam|sire 确定性序列化(数据漂移可检测)
bre_prediction engine_version varchar(32) 引擎版本(blup.ENGINE_VERSION="1.0.0"
bre_rootstock dwarf_class varchar(32) 矮化类:矮化/半矮化/乔化/柱状/其他
bre_rootstock compatibility varchar(16) 砧穗亲和性:强/中/弱

accuracy 语义正名:原误填"均值 EBV 的平方根"(量纲不符),现改填真 PA = √(批次内可靠性均值)numeric(5,3)3 位小数),与 bre_prediction_value.pa(每株)口径一致。

7.3 引擎逻辑(statistics/service.py + blup.py

规格点 实现
② PA run_ablup 写 EBV 行 pa = √reliability;批次 accuracy = √(均值 rel)ebv_ranking 单株响应透出 pa
④ germplasm_id run_ablup 写 EBV 行 germplasm_id = tree.germplasm_id(晋升回填的种质;无种质株保持 NULL 合规)
③ 溯源 批次级落 data_version / input_hash / engine_versioninput_hash 覆盖全部参与树 × 全部观测(含 NULL 表型拼接),改 1 条观测哈希必变
① Calo _smith_hazel_index G 非对角改 r_g = r_EBV/√(rel_i·rel_j)(rel 取配对树该性状均值),钳制 [−1,1];可靠性缺失/近零 → 0(保守);extra["g_corr"](性状对)+ extra["g_note"]bre_selection_index.result_json 可审计;rel 数据即 ② 落库的 reliability
⑥ 空间竞争 run_ablup(covariate="competition"):同 (plot_id, block_no) 网格内 Chebyshev 距离 1(8 邻域,不含自身)株数作协变量;相邻越多竞争越强、边缘株相邻少隐式捕捉边缘效应;G×E 分支同步支持(三处 covariate == "crop_load" 泛化为 covariate 真值);全无 row/col → CustomException(显式数据需求);bre_tree.row_no/col_no 数据能力已全链路就位(模型/前端录入/表格/详情/导入导出)

7.4 前端

文件 变更
api/module_bre/statistics.ts 指数批次表/EBV 行类型加 germplasm_id/pa
views/module_bre/statistics/index.vue 指数批次表加 germplasm_id/pa 列;ABLUP 运行对话框协变量 el-checkbox 改 radio(无 / crop_load / competition+ 说明文案
api/module_bre/rootstock.ts + views/module_bre/rootstock/index.vue dwarf_class/compatibility 全量:常量、搜索、表格、详情、表单、handleSearch/onResetSearch

7.5 验证(三探针全过 + vue-tsc

e2e_prediction_rigor_20260804.py(②③④,4 组)

断言
[1] 每株 pa = √rel 逐条一致;批次 accuracy = √(均值 rel);溯源三字段(data_version=v2.7 / engine=1.0.0 / acc=0.439);germplasm 级查询(按 gA 查得 2 条);ebv_ranking 透出 pa
[2] 复现性:同数据重跑 input_hash 完全一致
[3] 数据漂移:改 1 条观测值后重跑哈希必变
[4] 跨会话持久化:commit 后新会话读取值/哈希仍在(全行扫描断言)

e2e_rootstock_20260804.py(⑤)create/detail/update/list(搜索 dwarf_class/options/export(含新列)/template(下拉选项)/DB 直查全过。

e2e_corr_spatial_20260804.py(①⑥,3 组)

断言
[1] Calo 校正值:g_corr 含性状对、g_note 含"可靠性校正"got_rg 与独立重算 clamp(r/√(rel_i·rel_j)) 一致(容差 1e-4),例 r=0.9966/rel 0.1925·0.1345 → r_g=1.0
[2] competition 消费验证:有坐标运行成功,EBV 与无协变量最大差异 0.5465(差分消费,非仅字段)
[3] 数据需求判定:全无 row/col → CustomException 含 row_no/col_no

7.6 遗留(已记账,不动引擎)

  • 真 MT-BLUP:多性状 G 需全新多变量 REML 求解器(Kronecker 积 G/R + 方差分量迭代,数值收敛风险大)。本轮用 Calo 可靠性校正顶上(业界对"EBV 相关替代 G"的标准修正),g_corr/g_note 落库可审计。后续要做即按此接口替换。 2026-08-04 追加加固:逐对独立估计的 r_g 在 ≥3 性状时可能违反三角不等式使 G 非正定 → _smith_hazel_index 构造 G 后做最近半正定投影Higham 特征值截断,np.linalg.eigh),b=P⁻¹Ga 才良性;新增稳定性警示 extra["warnings"](完整观测树 <30 / P 条件数 >1000 / G 非正定已投影 / r_g 钳到 [−1,1] 边界)随 result_json 落库可审计,不阻断。数值验证:0.9/0.9/0.9 相关阵 det<0 → 投影触发;2 性状正定场景无警示。
  • ⑦ 前端 D 层占位:分子育种/品种保护/AI 增强 _coming_soon 保持占位,属 P2 远景预期。

7.7 组合得失漏斗 v_combination_funnelv2.82026-08-04

缺陷背景(逐条复审第 8 条,最贴业务):数据本已齐全——bre_pollination.flower_count/effective_count(花→果)、bre_seed_lot.seed_count/germination_rate(种→苗)、bre_seedling.seedling_count(出苗)——但无任何按 bre_cross_combination 汇总的派生指标:结实率/出苗率/选择强度未滚到组合层,配合力第一手证据(组合得失链路)字段在但没合成进配合力上下文。核实属实:全库无 结实率/出苗率/选择强度/funnel 实现;唯一"选择强度链"是 seed_lot.used_count 机械累加(账本非派生指标);run_combining 只取 func.avg(value_numeric) 组合均值、combining.solve 只认 combo/parent1/parent2/value。用户拍板:补视图/派生表即可,数据已齐、风险极低。

六级链路与派生指标

环节 数据源(均按 combination_id 聚合) 派生
花→果 bre_pollination Σflower_count / Σeffective_count 结实率 fruit_set_rate = Σeff/Σflower×100
果→种 bre_seed_lot Σseed_count / AVG germination_rate 出苗基数
种→苗 bre_seedling Σseedling_count / Σstrong_seedling_count 出苗率 emergence_rate = Σseedling/Σseed×100
苗→定植 bre_planting Σtree_count 定植数
定植→树 bre_tree 非软删 COUNT 树数(评价群体基数)
树→入选 bre_selection_result 非软删 COUNT 选择强度 selection_rate = 入选数/树数×100

缺环节的组合比率列留 NULLbre_cross_combination 主表 LEFT JOIN 六源,按组合一行)。

实现

  • backend/sql/weld_combination_funnel.sqlv_combination_funnel 普通 VIEWDROP IF EXISTS + CREATE OR REPLACE 幂等,F2 决策保 fresh 不用 MV),psql 应用(create_all 只建 ORM 表,视图须手写 SQL)。
  • statistics/service.py::combination_funnel():查视图返回 {rows, n}Numeric→int/float 归一),视图未就绪 CustomException 提示。
  • statistics/controller.pyGET /statistics/combination-funnelmodule_bre:statistics:query 权限)。

验证(Temp/claude/e2e_combination_funnel_20260804.py3 组全过)

断言
[1] 全六级组合:150 花/50 果→结实率 33.33%、100 种(发芽率均值90%)/80 苗→出苗率 80%、55 定植/3 树/2 入选→选择强度 66.67%,逐计数精确断言
[2] 仅授粉组合:fruit_set=50.0% 算得出,种/苗/定植/树/入选 全 NULLLEFT JOIN 正确性)
[3] 跨会话持久化:commit 后新会话读同值

工程教训:首跑清理阶段 FK 崩——helper 里 db.add()未 flush 就取 .id 拿到 None,删除 WHERE id IN (None,…) 不命中留下孤儿行。修复:add 后先 await db.flush() 再取 id。此为探针自身 bug,非视图/端点缺陷。


八、分子育种「建数据能力」(2026-08-04)

分子层四表 DDL 早已在 backend/sql/bre_tables.sql(§3.7),但 module_bre 无 ORM/服务 → DNA 指纹/QTL/GWAS/GS 全 inert。用户拍板先建「数据能力」:四模块 CRUD + Excel 导入导出 + VCF 导入 + 指纹防错(无性系混杂检测)。GS/GWAS/GBLUP 引擎仍占位。菜单 900210-900213 由占位页切真实页面,900214 GWAS 保持 _coming_soon

8.1 DDL 缺口与补列

bre_genotype_sample 原 DDL 无样本名字段(只有 dataset_id/source_type/source_id/sample_type/sample_date/method/lab/remark)。VCF 表头映射、UI 展示、指纹报告都靠样本名 → 按 weld 惯例补列(create_all 只建新表、不改既有表):

ALTER TABLE bre_genotype_sample ADD COLUMN IF NOT EXISTS sample_name varchar(128);
COMMENT ON COLUMN bre_genotype_sample.sample_name IS '样本名称(VCF 表头/UI 展示,可空)';
CREATE INDEX IF NOT EXISTS ix_bre_genotype_sample_dataset_name ON bre_genotype_sample (dataset_id, sample_name);

8.2 四模块五件套

模块 关键列 / 约束 导入必填
marker bre_marker marker_name UNIQUEchromosome/position/marker_type/panel/assembly_version marker_name
genotype_dataset bre_genotyping_dataset dataset_name/platform/panel/purpose/run_date/lab dataset_name
genotype_sample bre_genotype_sample sample_nameweld 补)dataset_id FK→dataset sample_namedataset 名解析成 ID
genotype_call bre_genotype_call sample_id/marker_id 双 FK + UNIQUE(sample_id,marker_id)allele 按 VCF/GP 编码 sample_name/marker_name(解析成 ID/allele
  • 五件套model/schema/crud/service/controllermodule_bre/__init__.py 注册。ORM 严格对齐 bre_tables.sql——分子表无 status 列,模型覆盖 __table_args__Index("ix_bre_<表>_created_deleted", "created_time", "is_deleted"))跳基类默认 status 索引。
  • FK 存在性sample/call create/update 前 assert_parents_exist(父级软删也拦截→409「XX不存在或已被删除」)。
  • 名称透出get_list/detail 后查 ref_map 填 dataset_name / sample_name / marker_nameseed_lot combination_name 同款 _attach_fk_labels)。
  • Excel 导入导出header_dict 中文头→列,名称解析成 ID;导入模板/导出 mapping_dict 含 created_by 名解析。

8.3 VCF 导入(POST /bre/genotype_call/import/vcf

  1. 跳过 ## 行,定位 #CHROM 表头 → FORMAT 后为样本列,GT 在 FORMAT 子字段索引。
  2. markerID 非 . 用 ID、否则 CHROM:POS,按 UNIQUE 查重 → 缺失建号(marker_type=snp、panel=dataset.panel)。
  3. 样本:按 (dataset_id, sample_name) 查重 → 缺失建号(sample_type=vcf、method=genotypingsource 留空)。
  4. GT|/ 规范化;././././ 跳过;allele 存 GT 编码(0/0、0/1、1/1)。
  5. 内存 dict 以 (sample_id, marker_id) 去重(文件内重复 last-wins);已存在分型跳过 → 重跑幂等500/批批量 insert。
  6. 返回 {dataset_id, dataset_name, variants, samples, samples_created, markers_created, calls_inserted, skipped_missing}

8.4 DNA 指纹防错(GET /bre/genotype_call/fingerprint/check

纯数据层比对,无外部依赖:

  1. 取 dataset 内样本 + 分型结果,构建 {sample_id: {marker_id: allele}}allele 规范化。
  2. 两两比对:共同 marker < min_markers 跳过(信息量不足);否则 identity = 匹配数/共同数
  3. 判定:同源对(source_type+source_id 相同且非空)identity < threshold →「同源指纹不一致(疑似样品污染/取错)」;异源对 identity ≥ threshold →「异源指纹一致(疑似无性系混杂/标签互换)」。
  4. 返回按 identity 降序的 pair 行(样本名含来源、共同数、匹配数、identity、标记)。

8.5 菜单 / 权限 / 前端

  • bre_menu.sql900210-900213 component_path 由 _coming_soon/indexmodule_bre/{marker,genotype_dataset,genotype_sample,genotype_call}/indexF 段按钮 id=900700+seq*10+border(八按钮:查看/查询/新增/编辑/删除/导出/导入/下载模板),ON CONFLICT (id) DO NOTHING 幂等;SUPER_ADMIN/ADMIN 角色关联 64 行。
  • 前端:4 api .ts + 4 index.vue。genotype_sample 搜索/表单带 dataset 下拉;genotype_call 带 sample/marker 双下拉 +「导入 VCF」(dataset 下拉+文件上传,报计数)与「指纹检测」(dataset 下拉+min_markers+阈值,结果表两色标签:danger=同源不一致、warning=异源一致)两个自定义按钮/对话框。

8.6 e2e 验证(e2e_molecular_20260804.py

断言
[1] 四模块 CRUD 闭环:dataset→marker→sample→call create/detail/update/list/optionsFK 名称透出(sample.dataset_name、call.sample_name/marker_name
[2] 唯一键/父级:重复 (sample,marker)→409「已存在」;sample 引用不存在 dataset→409;重复 marker_name→409
[1b] 删除闭环:call→sample→marker→dataset 软删后 detail 不可见
[3] 指纹:6 样本 3 标记——同源对 1 处不一致→命中「同源指纹不一致」(identity 2/3);异源对全一致→2 对「异源指纹一致」(identity 1.0);同源全一致对不误报;共同 marker 不足(S-Y 仅 1 标记)对不出现
[3b] 空数据集指纹 samples=0/flagged=0
[4] VCF6 variant × 3 样本——markers_created=5/samples_created=3/calls_inserted=13/skipped_missing=2;文件内重复标记 last-wins(P01,V100)=1/1);自动建号元数据(V500 chrom=2/pos=500/type=snp/panel=dataset.panel);重跑幂等samples/markers/calls 均 0 新增)

清理按 FK 逆序物理删(call→sample→marker→dataset,前缀 E2EM-),重跑幂等。


九、精修项落地:DUS 数据能力 + stage 感知 + k-fold CV + 公平性报告(2026-08-04

9.1 缺陷背景(用户核实四条缺口,全部拍板落地)

用户核对后确认四条精修缺口属实并拍板「全部落地,更新文档,保留版本」:

  1. DUS/品种保护:无 DUS 模块、无 UPOV TG/53 描述符观测模板(菜单 900230 预留仍占位);档位=数据能力(三表)
  2. stage 感知bre_trait.stage(v2.0 定义)存在但 BLUP/选择指数/决策无视,童期/成株性状混用无警示。
  3. 模型外部验证:可靠性仅 PEV 法(内部);档位=ABLUP + GXEBLUP 双支持 k-fold CV(外部预测准确度)。
  4. AI 伦理·分组偏差:G×E 引擎已覆盖互作,缺按 site 的系统性 EBV 偏差/公平性报告。

9.2 DUS 数据能力(三表)

业务列 约束
bre_dus_descriptor descriptor_no(UPOV TG/53 特性号)、trait_id→bre_trait(可空=自由描述符)、trait_code 快照、descriptor_name、expression_type(QN/PQ/QL)、method、example_varieties(标准品种)、test_stage、required uq_descriptor_no
bre_dus_test test_name、germplasm_id→bre_germplasm、trial_study_id→bre_trial_study、tester、test_date、status(planning/testing/completed/report)、conclusion(pending/distinct/not_distinct)、report_path uq_test_name
bre_dus_observation dus_test_id→bre_dus_test、dus_descriptor_id→bre_dus_descriptor、value_numeric、value_text、expression_note uq(test,descriptor)
  • 表新建走 create_all(不在既有 DDL,无需 weld);五件套 module_bre/dus/ 注册 /bre/dus_test/*descriptor 9 端点含导入导出+模板,test 9observation 6)。
  • 种子 sql/bre_dus_seed.sqlUPOV TG/53 桃描述符 15 条trait_code → bre_trait LEFT JOIN 解析 trait_id8 条关联),ON CONFLICT(descriptor_no) DO NOTHING 幂等。
  • 菜单 sql/bre_menu_refine.sql900230 component 切真实页 module_bre/dus/indexG 段按钮 900800-900808perm module_bre:dus_test:*,八按钮含导入/下载模板)+ SUPER_ADMIN/ADMIN 角色关联。
  • FK 名称透出:trait_name / germplasm_name / trial_study_name / descriptor_no+descriptor_name;描述符导入按中文头「关联性状编码」→trait_id。

9.3 stage 感知

  • _trait_meta_map 读入 trait.stage(缺省 evaluation);PredictionModel.stage 落库(sql/weld_refine.sql 补列)+ 预测批次表展示(童期 warning / 成株 primary 标签)。
  • selection_indexstage 入参:传 juvenile/evaluation 只纳入该阶段性状(异阶段写入 skipped_stage,同阶段无性状→409 带剔除清单);不传且横跨两阶段 → stage_warning(童期/成株性状清单 + 「证据来自不同发育阶段,需人工复核」)。
  • decision_preview 同理:传 stage 时异阶段规则条件跳过(matched=None、reasons 不出现);不传且规则引用性状横跨两阶段 → stage_warning

9.4 k-fold CV(外部验证)

  • 求解器 scripts/breeding_stats/blup.py::kfold_cvsire 家系分层留出(同家系不进训练/测试双折避免乐观,无父本个体自成一系)、固定种子;每折训练子集重估方差组分 → 留出个体 EBV 由系谱预测(个体保留在 A 矩阵、仅掩蔽表型)→ pearson+RMSE;单折失败(train<2 / G×E 结构不可辨识)记 None+warning 不中断。
  • 落库 bre_cv_resultmethod=KFCV/ABLUP|KFCV/GXE、k/n_total/n_individuals/mean/pooled pearson/RMSE/cv_accuracy/h2+ bre_cv_fold 明细;MLOps 溯源 data_version/input_hash/engine_version 复用。
  • 端点:POST /bre/statistics/cv/runtrait_id/code/year/fixed/covariate/gxe/gxe_env/k 2~10ABLUP 与 GXEBLUP 同入口)、GET /bre/statistics/cv(批次)、GET /bre/statistics/cv/{id}(含折明细)。

9.5 公平性报告(只读,不建表)

GET /bre/statistics/fairness?prediction_id=&group_by=site&threshold_sd=1.0

  • site_summary:每 site n_trees/n_groups/n_individuals/EBV 分布(mean/sd/min/max/mean_reliability/deviation=site_meangrand_meanflagged=|deviation|>threshold_sd×grand_sd
  • rank_consistency:site 内组合均值 EBV 排名 vs 全体组合排名,共享组合 ≥2 时手写 Spearman。
  • gxe_pattern:组合×site 单元均值(单元 n≥2),暴露跨 site 排名翻转。

9.6 验证(e2e_refine_20260804.py 全过 + vue-tsc

断言
[1] DUS:三表 CRUD + 种子命中(15 条、TG/53/5=果形、≥1 条关联 trait_id)+ FK/唯一键/子表阻断删除/软删全 409 路径
[2] stageselection_index 无 stage→警示含两性状;juvenile→traits 只含童期 + skipped_stage=[成株]decision_preview juvenile→成株规则条件跳过(matched=None)、童期规则命中部分株;ABLUP 批次 stage 落库(juvenile/evaluation 各对)
[3] CVABLUP k=3 折 pearson 全非 Nonesire 家系留出→留出株 EBV 收缩到均值、pearson=0 为设计预期)+ GXE k=2 跨 site 跑通 + 幂等重跑新批次 + data_version=“v2.7”/engine/input_hash + job SUCCESS
[4] fairness2 site 9 株 site_summary 2 行(deviation 异号、flagged 布尔)+ rank_consistency 2 行(shared≥2、spearman 非 None+ gxe_pattern n≥2 单元

清理按 FK 逆序物理删(前缀 E2ER-),TG/53 种子描述符与既有数据不动。


十一、六项能力完善:MT-BLUP + GBLUP/ssGBLUP + DUS 特异性检验 + AMMI/FW 稳定性 + MLOps 重训回滚 + BLUP stage 拆分(2026-08-04

11.1 缺陷背景(用户两轮复核核实六条缺口、逐项拍板「全部落地」)

  1. MT-BLUPSmith-Hazel 的 G 非对角仍用 Calo 校正 EBV 相关近似(service.py 已诚实文档化为回退),缺真遗传相关估计 → 拍板成对双性状 BLUP(非全多变量 REML)。
  2. GBLUP/ssGBLUP:分子层只有数据能力(四模块 CRUD + VCF + 指纹),无 VanRaden G / 基因组选择引擎 → item 明确两者都做。
  3. DUS 特异性统计检验conclusion 纯人工(无判定端点)→ 拍板参照=同 trial_study 自动 + 可显式指定
  4. AMMI/Finlay-Wilkinson 稳定性:G×E 随机效应已估 σ²gxe,无跨环境稳定性排名。
  5. MLOps 自动重训 + 版本回滚APScheduler 在但统计无重训接线、无 is_active → 拍板漂移检测端点 + 手动触发,不注册 cron。
  6. BLUP stage 拆分run_ablup 只打标签(model_name 后缀)不按 stage 取数。

11.2 MT-BLUPscripts/breeding_stats/mtblup.py + statistics/service.py

  • mtblup.solve_bivariate(pedigree, phenos, code1, code2)ENGINE_VERSION=1.0.0):共享系谱复用 blup._order_pedigree/_build_ainv 建 A/A⁻¹;模型 y=[y1;y2] 堆叠、X/Z 块对角;Var(u)=G0⊗AG0=Va1,ρ√(Va1Va2)],[·,Va2)、Var(e)=diag(Ve1,Ve2)⊗I。降维Va1/Ve1、Va2/Ve2 取自各性状单性状 REML(=既有 herit 来源),仅对 ρ∈[0.99,0.99] 1-D golden-max 最大化精确 REML ll(复用 _golden_max + _solve_gxe 的 V=Z(G0⊗A)Z'+R、slogdet+yPy 模板)。返回 r_g/σa 矩阵/n_common/n_iter/converged/warning;单性状观测 <2 → 该性状 NAN。
  • run_genetic_corr(trait_ids, year)_gather_shared_phenos union 树集 + 树级均值 + 共享系谱;两两 bivariate,对角=单性状 h²·P_ii、非对角=r_g·√(G_ii·G_jj) 组装 G0Higham 特征值截断投影半正定;落 bre_genetic_corr_resulttrait_codes/matrix/sigma_a/heritability/pairs_json/n_common + data_version/input_hash/engine_version+ StatisticsJobModel(job_type="GENCORR")list_genetic_corr / genetic_corr_detail
  • _smith_hazel_indexg_method="calo"|"mtblup"selection_index 透传):mtblup 时逐对 solve_bivariate 填 G 非对角,单对不收敛回退 Calo + warning 清单(不阻断指数);≥3 性状 r_g 三角不等式违反 → 特征值截断投影半正定;extra["g_source"]="mtblup|calo" 落库可审计。
  • 端点:POST /statistics/genetic-corr/runtrait_ids 多选 + year)、GET /statistics/genetic-corrGET /statistics/genetic-corr/{cid}

11.3 GBLUP / ssGBLUPscripts/breeding_stats/genomic.py + statistics/service.py

  • build_g_matrix(genotypes, markers, *, maf_min, method=2, blend=0.02)dosage 0/1/2 样本×标记,缺格按列均值 2p 填充;MAF 过滤(maf>=maf_min,全滤 → ValueError);VanRaden method1 G=ZZ'/2Σp(1-p)diag≈1/ method2 G=ZDZ'D=1/[2p(1-p)]);blend 岭 G=(1−ω)G+ω·mean(diag)·I 保证可逆。
  • solve_gblup(pedigree, phenos, G, *, tol):仅基因型个体入模型,MME 用 G⁻¹ 替代 A⁻¹;σ²a 用 _golden_max profile(仿 blup.solve);返回 ebv/reliability(=1PEV/σ²a)/h2/σa/σe/converged/warning。
  • solve_ssgblup(pedigree, phenos, G, genotyped, *, tol)H⁻¹ = A⁻¹ + 0,0],[0, G⁻¹ A22⁻¹Aguilar et al. 2010);A22=A[genotyped,genotyped] 稠密子阵 np.linalg.inv(病态加 _RIDGE=1e-6);V 块必须用 H 协方差——按 Aguilar 块公式构造完整 HD=GA22H=A+A12A22⁻¹DA22⁻¹A21, A12A22⁻¹D],[D·A22⁻¹A21, D;非基因型块 += L·D·L'、交叉块 += L·D、基因型块 = G),REML 似然 V=ZH[z,z]Z'+RH⁻¹ 仅进 MME 系数矩阵。修复前 V 块误用 Hinv[z,z] 致似然失构。基因型+非基因型个体都出 EBV。
  • run_gblup(dataset_id, trait_id, trait_code, year=None, method="gblup"|"ssgblup", maf_min=0.05):取数 bre_genotype_call join bre_marker pivot sample×marker 剂量("0/0"→0/"0/1"→1/"1/1"→2,多等位跳过);样本→个体映射 source_type='tree' 直连 + sample_name↔tree.tree_no/germplasm.cultivar_name 名称兜底,未映射→跳过 + note warning 清单;genotyped = sorted(dosage) 对齐 build_g_matrix 内部 sorted(genotypes) 行序(修复前用全部映射树,零有效调用树会错位 G 索引静默污染 EBV);input_hash 覆盖(基因型矩阵哈希 + phenos + ped);落 PredictionModelmethod=GBLUP/ssGBLUPengine_version 落库)+ PredictionValueModel(每树 EBV/rel/pa/rank+ job_type="GBLUP"list_genotyping_datasetsgenotyping_dataset 列表 + n_samples)。
  • 端点:POST /statistics/gblup/runGET /statistics/gblup/datasets;批次/EBV 复用 list_predictions(按 method 过滤)+ ebv_ranking

11.4 DUS 特异性统计检验(dus/service.py + fdist.py

  • fdist.f_icdf(p, d1, d2)F-CDF 二分反解;t_crit(alpha, df)=√f_icdf(alpha, 1, df)t²=F(1,df))。
  • dus.distinctness(candidate_rows, reference_rows, descriptor_meta, alpha=0.01)
    • QN:候选 vs 参照单因素 ANOVA → MSE,df → LSD = t_crit(α,df)·√(MSE·(1/n_cand+1/n_ref))|cand_mean ref_mean| > LSD → 该描述符 distinct(逐参照比较,任一超 LSD 即 distinct)。
    • PQ/QL:表达状态众数——候选众数 ∉ 参照众数集 → distinct。
    • 汇总逐描述符 {descriptor_no, name, expression_type, candidate_value, ref_values, statistic, critical, distinct};总体建议=≥1 个 required 描述符 distinct → distinct,否则 not_distinct,数据不足→pending(不判)。
  • test_distinctness(test_id, reference_test_ids=None, alpha=0.01):默认参照=同 trial_study_id 其他非软删 test(候选自身分组:同 germplasm_id 的测试合并为重复),可显式覆盖;取候选+参照观测+描述符 → 判定 → analysis_json(逐描述符表+建议+参照集+alpha+运行时间);conclusion 当前 pending 时自动填建议(人工可改)。distinctness_report(test_id) 读已存分析;DusTestOutSchema 加 analysis_json。
  • 端点:POST /bre/dus_test/distinctness/{test_id}GET /bre/dus_test/distinctness/{test_id}

11.5 AMMI / Finlay-Wilkinson 稳定性(scripts/breeding_stats/stability.py + statistics/service.py

  • finlay_wilkinson(table):每基因型对环境指数(该环境全基因型均值 np.nanmean(Y, axis=0))回归 y_gj=b·I_j+alstsq)→ b/截距/R²/se_b/dev_msflag_stable = |b1| ≤ 2·se_b,且完美拟合(dev_ms≤1e-12·max(1,ptp(y)²))时 se_b 无信息量 → b≈1(|b−1|≤1e-6)才判稳(修复前浮点 b 永不精确=1 且 se_b=0 → 误判不稳)。
  • ammi(table, n_components=2):μ+g+e 两因素分解 → 残差 SVDnp.linalg.svd,首引)→ λ1/λ2、每基因型 IPC1/IPC2 得分、ASV=√((IPC1·SS_ipc2/SS_ipc1)²+IPC2²)Purchase 2000IPC1 按 SS 比例缩放)、Wricke ecovalence=Σ(y_ijy_i.y_.j+y..)²、ipc_variance(各 IPC 解释比例);rows 按 ASV 升序 + rank。
  • run_stability(trait_id, trait_code, gxe_env="site"|"year", year=None, methods=("ammi","finlay")):两向表 genotype=clone(缺则 combination,再退 tree)× env=site(trial_study_id)/year(evaluate_year),每格多株均值(仿 trait_values 取数);有效格子 <2×2 → 409;落 bre_stability_resultdetail_json + data_version/input_hash/engine_version+ job_type="STABILITY"list_stability / stability_detail
  • 端点:POST /statistics/stability/runGET /statistics/stabilityGET /statistics/stability/{sid}

11.6 MLOps 自动重训 + 版本回滚(statistics/service.py + sql/weld_advanced.sql

  • weldbre_prediction.is_active boolean default falserun_ablup/GXE/GBLUP 落库:同 trait 无 active 批次 → 本批 active=true,否则 false版本链语义)。
  • _gather_digest_inputs(trait_id, year):轻量抽取——仅组装进 _input_digest 的 phenos+pedigree(复用 run_ablup 的取数 SQL,不含 fixed/cov/门禁),供 drift 重算当前哈希(规避全量抽取风险)。
  • GET /statistics/model/drift?prediction_id=:从该批次 job params_json 取 (trait_id,year,gxe,gxe_env) → _gather_digest_inputs 重算 → {prediction_id, changed, current_hash, stored_hash, data_version}。
  • POST /statistics/model/retrain?prediction_id=漂移才重训——run_ablup(同 params) 建新批次并 await model_activate(new_id) 转移 active修复前新批次默认 inactive——旧批次仍 active,重训后新批次卡在非生效态,破坏版本链语义)→ {retrained, old_id, new_id, new_hash};无漂移 → {retrained:false, reason}。
  • POST /statistics/model/activate/{id}trait 内标 active(回滚原语);list_predictions/PredictionOut 加 is_active。

11.7 BLUP stage 拆分(statistics/service.py + sql/weld_advanced.sql

  • weldbre_trait_observation.stage varchar(16)(观测级发育阶段,缺省继承 trait.stage)。TraitObservationModel + schemacreate/update/out+ 前端观测表单 stage 下拉(juvenile/evaluation)。
  • run_ablup(stage=None) + RunStatsIn.stagestage 给定 → 取数 where(coalesce(obs.stage, trait.stage) == stage);过滤时 model_name 加 _{stage} 后缀 + PredictionModel.stage=生效 stage;未给定但数据 obs.stage 与 trait.stage 出现分歧 → note 警示("有 N 条观测标注了观测级 stage,但本次未按阶段拆分…",不阻断);GXE 分支同步应用;非法 stage → 409。

11.8 前端

  • statistics.tsrunGeneticCorr/listGeneticCorr/geneticCorrDetail + runStability/listStability/stabilityDetail + runGblup/getGblupDatasets + modelDrift/modelRetrain/modelActivate + 类型。
  • statistics/index.vue:新「遗传相关 MT-BLUP」(性状多选→相关矩阵表格)、「稳定性 AMMI/FW」(性状+env+methods→FW b/R²/flag 表 + AMMI IPC/ASV/rank 表)、「基因组选择 GBLUP」(dataset+性状+method radio+maf→批次/EBV 表)三 tabABLUP 运行对话框加 stage 三态(全部/童期/成株);Smith-Hazel 对话框加 g 矩阵来源 radioCalo/MT-BLUP);预测批次表加「当前版本」标签 + 漂移检测/自动重训/设为当前版本按钮。
  • dus/index.vue:DUS 测试行加「特异性判定」按钮→对话框(alpha + 参照默认同点 + 逐描述符结果表 + 建议)→「应用判定」写 conclusion。
  • vue-tsc --noEmit 通过(EXIT=0)。

11.9 验证(Temp/claude/e2e_advanced_*.py 6 组全过)

  • stability3 组合×3 站点 FW b=2.0/1.0/0.0、flag=F/T/FC1 稳定)、r²=1/C2 None(常量响应 R² 无定义)、AMMI 9 格 IPC1≥IPC2 rank 升序、year 维度、非法 methods 409、list/detail。
  • stagejuvenile/evaluation 各只含对应观测树 + model_name _{stage}、不传含全部 4 株 + note 警示、非法 stage 409。
  • mtblupr_g=0.99y2=2·y1 强正相关)对称、σa12>0、h²∈(0,1)、n_common=4、Smith-Hazel g_method=mtblup g_source 落库;顺带修 _smith_hazel_index 未定义变量 tid 真 bug
  • gblupGBLUP 5 EBV 非基因型株=0 + ssGBLUP 非零 + solve_ssgblupV 块用 H、g 亲本 EBV 有限、G method1 diag_mean≈1+ 样本 4 直连+1 名称兜底+1 全多等位(回归 genotyped 对齐修复)+1 未映射 warning + list_genotyping_datasets n_samples=6。
  • dus:自动参照同点 5 测试、D1 LSD=1.239 df=3 t_crit=5.8409 distinct、D2 PQ distinct、D3 非必测 not distinct、analysis_json+conclusion 自动建议、显式参照覆盖、无重复 pending+warning。
  • mlops:首批 active → 改观测 drift changed → retrain 新批次 active 旧 inactive → 无新漂移幂等 {retrained:false} → activate 旧批次回滚(直接断言 model_retrain 修复)。
  • 后端重启 + openapi 确认 6 组新端点 + 2 新表(bre_genetic_corr_result / bre_stability_resultcreate_allweld_advanced.sql psql -w 幂等。

11.10 本轮修的三处引擎级 bug(e2e 探针暴露)

  1. ssGBLUP V 块genomic.py):REML 似然 V=ZH[z,z]Z'+R 必须用 H 协方差Hinv[z,z] 是把逆矩阵喂给协方差位置 → 似然失构、h² 失真。H 按 Aguilar 块公式构造。
  2. genotyped 与 G 行序错位service.py):genotyped 必须 sorted(dosage) 对齐 build_g_matrix 内部 sorted(genotypes);用全部映射树时,零有效调用树(全多等位)会静默错位 G 索引污染 EBV。
  3. _smith_hazel_index 未定义 tidservice.py):mtblup 分支取系谱树集的集合推导式引用未定义变量 → 首次走 g_method=mtblup 即 NameError。改 {tid for tid, d in pheno_all.items() if any(c in d for c in cols)}
  4. model_retrain 不激活新批次service.py):重训后补 await model_activate(new_id),否则新批次默认 inactive 卡在旧批次下,版本链断裂。
  5. flag_stable 完美拟合误判stability.py):残差≈0 → se_b=0 → |b1|≤2·se_b 恒假(浮点 b≠1 精确)。改 dev_ms 阈值判定:完美拟合 → |b1|≤1e-6 判稳。

11.11 收尾修复:统计二级菜单深链(前端,用户反馈"4 个二级菜单页面都一样")

统计分析下 4 个二级菜单(统计计算/育种值/选择指数与决策/图形分析)的 component_path 均指向 module_bre/statistics/index,而该页是单页多 tabactiveTab 默认 batches)且不读路由 → 点谁都落在"模型批次"页。修复:statistics/index.vueuseRoute() + ROUTE_TAB_MAPactiveTab 初始值按路由取。关键坑:数据库 sys_menu.route_path 实为相对路径statistics/prediction_value/selection_decision/statistics_chart),经父级 /breeding 拼接后实际 URL 是 /breeding/statistics/...,与 seed SQL 写的 /bre/... 绝对路径不一致——故必须按 route.name 匹配StatisticsCalc→batches、PredictionValue→ebv、SelectionDecision→index、StatisticsChart→correlation),而非 route.path(首次按 path 匹配 /bre/... 全部落空,用户刷新仍默认页)。四个菜单路由 name 各异,RouterView 缓存键 name+params 不同 → 每次点击组件重挂载,深链可靠。图形分析无专属 tab,暂归"相关性"。pnpm type-check EXIT=0vitebase=/web,端口 5666HMR 生效。

十二、田间试验精度补强·砧木×接穗随机互作 G×R(2026-08-04

12.1 缺陷背景(用户核实两条精度缺口,拍板先做 G×R)

用户核实田间试验设计精度两条缺口:① 无 R 侧空间协方差(行-列 AR1×AR1,当前 np.eye(m)*Ve 纯对角)——该项需先补 tree.row_no/col_no 数据与设计图,留待后续;② 无 scion×rootstockG×R)随机互作——rootstock 当前仅作固定哑变量(v2.0 ⑤ 砧木建模铁律「BLUP 固定效应扣除」),无第三个随机效应槽。用户拍板先做 G×R 随机互作(探索到跑通真实数据档位成本可控)。

12.2 架构决策

  • 结构同构、求解器零改动G×E 分支 _solve_gxeblup.py)的 Z₂ 已按 (基因型,因子水平) 分组配 I·σ² 交互,因子无关pair-grouping 机制),G×R 只是把分组键换成 (基因型, 砧木水平)MME/REML/输出键全部复用。
  • Z₂ 单槽位 → G×E/G×R 必须互斥if gxe and gxr 显式 409(文案「共用同一随机效应槽(Z₂)」),前端再加双向互斥 watcher 兜底。
  • 克隆坍缩系谱共享gxe_pedigreeclone 树坍缩为 c{clone} 节点,父母本=组合/种质亲本)构建块从 if gxe:上移为 G×E/G×R 共享(纯构建、ABLUP 路径不执行)。
  • rootstock 移出固定效应gxr=True 时强制 fixed_effects 剥离 rootstock,p_est 不再计入砧木水平,防与 Z₂ 共线。

12.3 求解器(backend/scripts/breeding_stats/blup.py

_solve_gxe 加两个可选参数(默认值保现有 G×E 行为逐字节不变):

  • factor_label="G×E"——未收敛警告「{factor_label} 似然面可能极平/边界最优」;
  • factor_name="环境"——方差归零警告「{factor_label} 方差分量收敛到 0(数据不支持基因型×{factor_name}互作)」。
  • 公开 solve() 加参并透传 _solve_gxe服务端走的是 solve(),首次探针即暴露漏传)。
  • ENGINE_VERSION "1.1.0"→"1.2.0"。

12.4 服务端(statistics/schema.py + controller.py + service.py

  • RunStatsIn + run_ablupgxr: boolcontroller 透传。
  • 互斥门禁(job 创建前):gxe and gxr → 409。
  • job_type="GXR" if gxr else ("GXE" if gxe else "ABLUP")params_json 落 gxr
  • elif gxr: 分支镜像 G×E site 分支:
    • 遍历 phenotypes.items()int tid),rid = f"t{tid}"字符串键)查 rootstock_map[rid]rs{rootstock}),缺砧木 → skipped++ 跳过并 note 警示;无任何可分砧木记录 → 409。
    • rec_gxr[rid] = (grp, rs)grp 优先 c{clone_of[tid]}(克隆坍缩)、退 f{combo_of[tid]}rec_map[rid] 同理。
    • 门禁三件套镜像:n_cross_rootstock=同基因型跨砧木数==0、max cell_counts<2、residual_df = m - q - p_est<1p_est 含 intercept + trial_study 水平-1(若固定)+ covariaterootstock 不计入)→「G×R 不可辨识」409。
    • rec_fixed(仅 trial_study,经 fixed_map+ rec_covcov_map);rootstock 从 fixed_effects 剥离。
    • 求解:blup.solve(gxe_pedigree, rec_phenos, gxe=rec_gxr, record_map=rec_map, fixed=..., covariate=..., factor_label="G×R", factor_name="砧木")
    • method="GXRBLUP"model_name GXRBLUP_{trait} + _{stage}? + _{ts}
    • notestage/sigma_a/sigma_gxr(=sigma_gxe)/sigma_e/gxr_ratio(=gxe_ratio)/n_cross_rootstock(=n_cross_env)/n_genotypes/warning/skipped/stage_note
    • EBV 写入共用段 accuracy 个体集按 gxr 选 gxr_tree_ids
  • _DATA_VERSION "v2.9"→"v2.10"。

12.5 前端(statistics.ts + statistics/index.vue

  • RunStatsPayload.gxr
  • G×E tab gxeEnabled 后加 <el-checkbox v-model="gxrEnabled">启用砧木×接穗互作(G×R)随机效应</el-checkbox>;双向互斥 watcher;运行按钮文案「运行 MET / GxE / GxR」、辅助文案三分支。
  • 批次表互作方差列 v-if 扩为 GXEBLUP || GXRBLUPfmtGxeNoten.sigma_gxr != null 分支(σ²gxr/σ²gxe、gxr_ratio/gxe_ratio、跨砧木/跨环境基因型)。
  • runGxe payload 加 gxr: gxrEnabled.valuevue-tsc 通过(EXIT=0)。

12.6 验证(Temp/claude/e2e_gxr_20260804.py4 组全过)

  1. 正例:2 基因型(clone)× 2 砧木 × 2 株 = 8 株,强交叉互作观测(clone1×R1 高/R2 低、clone2 相反)→ GXRBLUP、job_type=GXR、σ²gxr=74.8>0、n_cross_rootstock=2、n_genotypes=2、8 EBV 行。
  2. 门禁负例:同基因型仅跨 1 砧木 → CustomException「G×R 不可辨识」。
  3. 互斥负例gxe=True, gxr=True → CustomException「Z₂」。
  4. rootstock 剥离gxr=True 同时 fixed_effects=["rootstock"] → 剥离后不共线、正常出 σ²gxr。
  • 后端重启(含孤儿 reloader worker 清理)后 openapi 确认 gxr: True 入参;vue-tsc EXIT=0。

十三、基因组选择(GS)实证严谨性·GBLUP/ssGBLUP 专用 k-fold 交叉验证(2026-08-04

13.1 缺陷背景(用户核实两条 GS 实证缺口,拍板先做 k-fold)

用户核实 GS 实证严谨性两条缺口: ① GS 缺自身交叉验证——run_cv/kfold_cv(blup.py)是 A 矩阵系谱预测(ABLUP/GXE),GBLUP 落库的 accuracy=√mean(reliability)理论准确度PEV 推导),对模型误设不敏感:G 算错/标记编码错/遗传力先验偏时 PEV 可靠性依然漂亮,真实预测能力却崩了,只有掩蔽留出「GEBV vs 表型 pearson」能测出实证预测能力。 ② SSR panel 难构 VanRaden G——_dosage_from_gt 只吃 0/1 两段整数且 max≤1SSR 片段编码(168/174)、多等位(0/1/2)、phasing0|1)全部被丢弃 → SSR calls 静默变缺失 → m_after_maf→0build_g_matrix 直接 ValueError「MAF≥0.05 的标记为 0」→ 409。这是"有引擎但数据接不进"的现实坑。

用户拍板先做 GS k-fold(①);SSR dummy 编码(②)留待后续。

13.2 架构决策

  • 核心洞察——掩蔽留出已原生支持_profile_solve(genomic.py)已实现「仅观测子集进模型、全部个体出 EBV」——非观测个体 Z 行全 0、经 G⁻¹/H⁻¹ 的 cross-relationship 预测(e2e_advanced_gblup 已验证非基因型株 tree4 出非零 EBV)。所以 GS CV 掩蔽留出 = 传训练子集 phenos → 全个体 GEBV → 取留出个体与观测表型相关。G/H/Hinv 只建一次,逐折只换 z_train 子阵(折划分不改变关系矩阵)。
  • 折划分差异(与 ABLUP 的本质区别)ABLUP 的 kfold_cvsire 家系分层留出(同一家系不跨训练/测试,防同家系信息泄漏)。GS 的候选是 genotyped∩phenos 的同世代样本、无系谱家系树,用固定种子随机分层round-robin 到 k 折)即标准做法——文档明示该差异,将来要防近亲泄漏可加「按 G 关系分层」。
  • 方法互通method="gblup" → 关系矩阵 Gindividuals=genotypedmethod="ssgblup"_build_h 合并关系阵 Hindividuals=order,含非基因型亲属)。两者共用一个输出 dict 形状(与 blup.kfold_cv 逐键对齐)。

13.3 求解器(backend/scripts/breeding_stats/genomic.py

  1. 抽取 _build_h(pedigree, genotyped, G, *, ridge, extra_base)solve_ssgblup 的 base/non_base→_order_pedigree→A/Ainv→Hinv→H 构建提成 helper,返回 (order, idx, H, Hinv)。solve_ssgblup 改调(行为不变)。
    • 缺失基因型个体按 base 补入系谱(原 if missing_gen: raise ValueErrorfor g in missing_gen: base.append(g))——无表型基因型树不再触发 ValueErrorCV/ssGBLUP 更稳(与 phenos 兜底一致)。
  2. 新增 kfold_cv_genomic(phenos, G, genotyped, *, k=5, seed=20260804, method="gblup", pedigree=None, ridge)
    • method="gblup"individuals = sorted(genotyped)G 行序);relmat_inv = np.linalg.inv(G)(奇异回退 pinv);zmat_full = G。
    • method="ssgblup"_build_h(pedigree, genotyped, G, extra_base=list(phenos)) → individuals = orderrelmat_inv = Hinvzmat_full = H。
    • cand = sorted(genotyped ∩ phenos)n_total = len(cand)<2 → 空 folds + warning(对齐 blup.kfold_cv)。
    • 折划分:rng = random.Random(seed)shuffle cand → bin_of = {c: i % k}
    • 逐折:test_set = {c: b == fold}train_phenos = phenos test_setz_train = 观测个体索引_profile_solve(zmat_full[ix_(z,z)], X, y, relmat_inv, n, z_train) → 全 EBV → 留出个体 GEBV vs 表型 blup._pearson + RMSE;单折失败(训练<2/测试空/求解异常/未收敛/测试有效<2)→ error 记 warning 不中断
    • 输出 dict 与 blup.kfold_cv 逐键对齐k/n_total/n_individuals/folds/mean_pearson/mean_rmse/pooled_pearson/pooled_rmse/cv_accuracy/h2/warning)。
  3. ENGINE_VERSION "1.0.0"→"1.1.0"。

13.4 服务端(statistics/schema.py + controller.py + service.py

  • _gather_gblup_inputs(dataset_id, maf_min) 提取run_gblup 的 dataset→samples→call_rows→markers→sample→tree 映射→dosage→build_g_matrix→genotyped 装配(约 60 行)提成 helper,返回 (dosage, marker_order, genotyped, G, g_meta, unmapped)。run_gblup 改调(行为逐字节不变),GS CV 复用。e2e_advanced_gblup.py 复跑兜底回归
  • run_cv 签名扩展:加 dataset_id: int | None = None, method: str | None = None, maf_min: float = 0.05params_json 落三键。
  • GS 分支(公共表型/系谱装配后、elif gxe: 前,与 G×E/ABLUP 互斥——双开时 GS 优先):
    • _gather_gblup_inputs(dataset_id, maf_min)gs_phenos = {f"t{tid}": v}(键对齐 run_gblup "t{tid}" 约定)→ kfold_cv_genomic(gs_phenos, G, genotyped, k=k, method=method, pedigree=pedigree)
    • method 名 "KFCV/GBLUP" / "KFCV/ssGBLUP"method varchar(16) 放得下)。
    • input_hash = sha256(_input_digest(pedigree, gs_phenos) + \n + geno_str)geno_str 镜像 run_gblupf"{s}|{mk}|{dosage[s].get(mk, '.')}" 全排序)。
    • engine_version 按分支:GS 用 genomic.ENGINE_VERSIONABLUP/GXE 用 blup.ENGINE_VERSIONcv_engine_version/method_name 先默认后覆盖)。
  • schema CvRunIn + controller run_cv 透传 dataset_id/method/maf_min
  • _DATA_VERSION "v2.10"→"v2.11"。

13.5 前端(statistics.ts + statistics/index.vue

  • CvRunPayloaddataset_id?/method?/maf_min?
  • CV tab 加 mode radioABLUP / GS:GS 模式显示基因型数据集下拉(复用已加载 gbDatasets+ method radioGBLUP/ssGBLUP+ MAF≥ 输入;隐藏 G×E 控件;辅助文案分支「掩蔽留出 GEBV vs 表型 pearson(实证预测能力,固定种子随机分层)」。
  • submitCv 按 mode 组装 payloadGS 传 dataset_id/method/maf_min);vue-tsc EXIT=0。

13.6 验证(Temp/claude/e2e_gblup_cv_20260804.py3 组全过 + 回归)

构造:5 家系 × 3 全同胞 = 15 株(每系独立组合+亲本种质),10 标记(MK0/MK1 为 QTL 效应 2.0,家系 QTL 剂量 [(2,2),(2,1),(1,2),(1,0),(0,0)]→遗传值 8/6/6/2/0,非 QTL 标记 (f*3+j)%3 家系特征化),表型 = 12 + 2·dose(MK0) + 2·dose(MK1) + 低噪(±0.3),家系内基因型一致 → 留出预测靠 G/H 同家系交叉关系,强信号。

  1. GBLUP 正例run_cv(trait, dataset_id, method="gblup", k=5) → job SUCCESSCvResultModel.method=="KFCV/GBLUP"cv_accuracy=0.794 > 0.3==mean_pearson、n_total/n_individuals=15/15、input_hash 64hex、engine_version=1.1.0、5 折 n_train/n_test≥1、CvFoldModel 5 行。
  2. ssGBLUP 正例method="ssgblup""KFCV/ssGBLUP"、cv_accuracy=0.794 > 0.3H 合并系谱+标记,家系内同基因型仍强预测)。
  3. 门禁负例:dataset 仅 1 个无映射样本(sample_name=NO_MATCH)→ CustomException「基因型样本均无法映射到单株」,FAILED job 落库。
  4. 回归e2e_advanced_gblup.py 复跑全过(_gather_gblup_inputs 提取后 run_gblup 行为不变:h²/5 条 EBV/非基因型株 EBV=0、note 未映射警示)。
  • 后端重启(含孤儿 reloader worker 清理)后 openapi 确认 CvRunIn 出现 dataset_id/method/maf_minvue-tsc EXIT=0。

十四、现代桃育种领域覆盖·S-等位基因交配兼容性 + 抗病/需冷量性状字典(2026-08-04

14.1 背景(用户核实四方向覆盖,拍板按建议次序做)

方向 核实结论 处置
① S-等位基因(自交不亲和)交配兼容性 完全未建模bre_pollen/bre_pollination 无 S-allele 字段、bre_cross_combination 无兼容性校验、"配了不结"硬需求空白 落地(本批)
② 需冷量/需热量 环境侧已建(bre_germplasm.chilling_requirement 属性 + bre_environment_condition.chilling_hours/GDD),选种性状侧 bre_trait 缺失66 行字典无一条) 落地(本批)
③ 抗病性状(细菌性穿孔病/褐腐病/白粉病) bre_germplasm.disease_resistance 仅自由文本,bre_trait 一条都没有 落地(本批)
④ MAS/QTL/GWAS 闭环 900214 仍 _coming_soon,发现层(GWAS/QTL 定位→MAS)完全缺失 留待单独立项

关键事实:统计引擎 _trait_meta_map 仅消费 data_type='numeric' 的性状(EBV/选择指数/决策候选),故抗病/需冷量必须建 numeric 而非 categorical 分级;桃属配子体自交不亲和(S-RNase),Sf 等位为自交亲和型(SI 功能缺失),多数商业化品种携带。

14.2 ②③ 性状字典种子(backend/sql/bre_disease_chilling_traits.sql

幂等 ON CONFLICT (trait_code) DO UPDATE,新增 5 条 numeric trait,全部 into_ebv='1'(选种目标)+ direction='asc'(低值优):

trait_code 名称 category unit 说明
disease_shot_hole 细菌性穿孔病 抗病性 0-5 级病情指数(0=免疫…5=高感),valid_min=0/valid_max=5h²=0.3
disease_brown_rot 褐腐病 抗病性 同上
disease_powdery_mildew 白粉病 抗病性 同上
chilling_requirement 需冷量 生态适应性 h 打破休眠 0~7.2℃ 低温累计小时(0-3000),h²=0.5
heat_requirement 需热量 生态适应性 GDD 发芽前 >7.2℃ 有效积温(0-10000),h²=0.4

stage='evaluation' + method 测定说明;前端 trait 页 category 自由文本自动显示、0 改动。

14.3 ① S-等位基因建模(germplasm + cross_combination

  • bre_germplasm.s_allelesString(32),如 S1/S3Sf=自交亲和型):model + schemaCreate/Update/Out+ ALTER TABLE + COMMENT
  • 兼容校验cross_combination/service.py):
    • _parse_s_alleles(raw):分隔符 / , ; → 归一化小写等位集合;空白返回 None。
    • _s_compat_check(female_s, male_s)任一亲本含 sf→full 放行Sf 不排斥);否则共享 2 个→none、1 个→half、0 个→full;缺 S 数据→unknown 跳过。
    • _check_s_compat(female_id, male_id):读亲本 s_alleles → noneCustomException 409「S-等位基因完全不相容(共享 …),该组合无法坐果」("配了不结"硬门禁);half 返回警示文案。
    • create/update 在亲本存在性断言后调用;CrossCombinationOutSchema.s_compat(可选派生字段)落半兼容警示;同亲本自交共享 2 等位自然被 409 拦截(除非含 Sf)。

14.4 前端

  • germplasm 表单加 S-等位基因 输入(type inputplaceholder「如 S1/S3Sf=自交亲和型」)+ 导出列;germplasm.ts GermplasmForm/GermplasmTables_alleles?
  • cross_combination 组合提交包装 createApi/updateApi:响应含 s_compatmsg.warning 展示(统一消息入口);409 由统一错误处理自动提示。

14.5 验证(Temp/claude/e2e_s_allele_20260804.py6 组全过)

  1. 纯函数 8 例S1/S3×S1/S3→none、×S2/S4→full、×S1/S2→half、S1/Sf×S1/S1→full、大小写/混合分隔→none、缺数据→unknown、_parse_s_alleles 归一化断言。
  2. service 层 create:共享 S1/S3→409「不相容」;共享 S1→s_compat 半兼容文案;0 共享→无警示;Sf 放行;缺 S 跳过。
  3. ②③ 落库核验bre_trait 5 条 numeric+asc+into_ebv=1 已落库。
  4. openapi 核验BreedingGermplasm{Create/Update/Out}.s_alleles + CrossCombinationOut.s_compat
  5. vue-tsc EXIT=0;后端重启后核验。

十五、GWAS/QTL/MAS 标记辅助选择闭环(2026-08-04)

v2.13 §十四 标记「④ GWAS/QTL/MAS 闭环留待后续单独立项」——本轮单独立项落地,补齐发现层:GWAS/QTL 定位 → 显著标记 → MAS 面板,900214 占位页翻真实页。桃在成熟期/果重等位点已有已知 QTL,MAS 让童期幼苗在无表型/无 EBV 时也能被标记辅助选择。

15.1 求解器 backend/scripts/breeding_stats/gwas.pyENGINE_VERSION=1.0.0,纯 numpy 零 scipy

  • 模型:逐标记单标记回归 y ~ μ + PC1..PCn_pc + marker;加性效应=标记回归系数。
  • 群体结构:标记剂量矩阵(缺失按列均值填)中心化 → np.linalg.svd 前 n_pc 个主成分得分(pc_scores = U[:,:n_pc]·s[:n_pc])作协变量。
  • p 值t = coef/SEp = fdist.f_pvalue(t², 1, df)df = n n_pc 2)——复用 DUS LSD 已验证的正则不完全 beta,零 scipy 新依赖
  • 多重检验threshold_bonf = sig_level/m_after_mafBH-FDR qnumpy argsort 自底向上保单调)。
  • QTL 定位sig_bonf 标记按 chromosome 排序,相邻间距 < qtl_window 合并簇,簇内最小 p 为峰标记(单显著标记也落 QTL 兜底)。
  • 共线兜底(本轮关键修复):非 QTL 标记与 PC 共线时 XtX 奇异,np.linalg.inv 返回病态(负对角元 → sqrt 域错)。改微小岭回归 reg=1e-8·max(diag(XtX)) 兜底——共线方向 SE 大而有限 → t 小 → p≈1(效应被 PC 吸收,正确非显著);与群轴正交的 QTL 标记不受影响(1e-8 相对岭可忽略)。
  • MLM 预留:method 参数(gwas/ssgwas),本轮仅实现 gwas。

15.2 数据装配与 5 张新表

  • _gather_gwas_inputs(dataset_id, maf_min)service.py 新 helper,仿 _gather_gblup_inputs 但 marker 查询补 chromosome/position)→ (dosage, marker_order, markers_meta, genotyped, unmapped)独立 helperrun_gblup/run_cv 零回归
  • bre_gwas_result(批次:n_individuals/n_markers/m_after_maf/maf_min/n_pc/sig_level/threshold_bonf/n_sig_bonf/n_sig_fdr/n_qtl/data_version/input_hash/engine_version/remark
  • bre_gwas_snp(逐标记:marker_id/marker_name/chromosome/position/maf/effect/se/t_value/p_value/neg_log10p/q_value/sig_bonf/sig_fdrFK CASCADE
  • bre_qtltrait_id/chromosome/start_bp/end_bp/peak_marker_id/peak_marker_name/peak_p/n_markers/effect/source=known|gwas/gwas_result_id
  • bre_mas_panel + bre_mas_panel_markerfavorable_dose/direction=high|low/effectUNIQUE(panel,marker)
  • ORM 于 statistics/model.pyModelMixin 全套),create_all 建表 + backend/sql/weld_gwas.sql 幂等 CREATE TABLE IF NOT EXISTS 双保险。

15.3 服务端端点与 MAS 决策 hook

  • POST /bre/statistics/gwas/runGwasRunIn: dataset_id/trait_id/trait_code/year/method/maf_min/n_pc/sig_level/qtl_window)→ job_type=GWAS_gather_gwas_inputs + asyncio.to_thread(gwas.run_gwas) + input_hash(系谱+表型+基因型确定性序列化)+ engine_version;成功落 bre_gwas_result + bre_gwas_snp 批量 + bre_qtlsource=gwas)。
  • GET /bre/statistics/gwas/list + GET /bre/statistics/gwas/{id}result + snps + qtls)。
  • bre_qtl CRUD(已知 QTL 录入 source=known+ bre_mas_panel CRUD + POST /bre/statistics/mas-panel/{id}/markers(全量替换)。
  • decision_preview MAS hook:条件循环 ("pheno","ebv")("pheno","ebv","marker")_mas_hit_map 按候选树批量查 call → _dosage_from_gt → 有利剂量命中计数(direction=high: dose≥favorable_dose / low: ≤),conds["marker"]={panel_id:{min_hits}} —— 童期幼苗无表型/无 EBV 也能被标记辅助选中
  • _DATA_VERSION v2.12;端点权限复用 module_bre:statistics:*900071 已授 ADMIN900214 翻转无需新增按钮)。

15.4 前端(gwas.ts + gwas/index.vue900214 翻转)

  • GWAS 结果 tab:批次表 + Manhattan 图(裸 echarts.init:x=染色体累加位置、逐染色体分组着色、显著点红色、Bonf 阈值 markLine、dataZoom+ QQ 图(期望 log10((i+.5)/m) vs 观测)+ SNP 表 + QTL 区间表。
  • QTL 定位 tab:已知 QTL 录入 CRUDtrait/chromosome/区间/peak/effect/remark)。
  • MAS 面板 tab:面板 CRUD + 标记选择对话框(marker/favorable_dose/direction/effect)。
  • 运行对话框参数:dataset_id/trait_id/year/maf_min=0.05/n_pc=3/sig_level=0.05/qtl_window=1000000。
  • sys_menu 900214component_path='module_bre/gwas/index'bre_menu.sql §6d);vue-tsc EXIT=0。

15.5 验证(Temp/claude/e2e_gwas_20260804.py7 段全过 + 回归)

  1. run_gwasjob GWAS/SUCCESSbre_gwas_result n=32/m=200→200/bonf=2/fdr=2/qtl=2/input_hash 64 位/engine_version=1.0.0/threshold_bonf=sig/m_after_maf。
  2. bre_gwas_snp:全字段(chromosome/position/neg_log10p/q_value);MK0/MK1 均 Bonf 显著且为所在染色体(chr1/chr3)最小 pMK0 p=2.3e-05、MK1 p=5.4e-05)。
  3. QTL 定位2 区间峰标记=MK0/MK1source=gwas 落库且挂批次。
  4. 已知 QTL CRUDcreate/update/listsource=known)全过。
  5. MAS:面板 2 标记(favorable_dose=2/high)→ decision_preview marker 条件(min_hits=1)命中 16 株 + 无表型童期幼苗 1 株,低剂量株不命中。
  6. 门禁dataset 无映射样本 → CustomException「无法映射」。
  7. 清理finally FK 逆序自动清理。
  • 回归e2e_advanced_gblup.py + e2e_gblup_cv_20260804.py 复跑零回归GBLUP/ssGBLUP CV accuracy 0.794);openapi 核验 10 条 gwas/qtl/mas-panel 路径。

15.6 数据设计要点(避免 PC 吞噬 QTL 的实证教训)

  • 标记数太少(如 20)且非 QTL 标记全为群轴共线时,标记矩阵秩塌缩,SVD 前 n_pc 个 PC 本身跨越因果标记 → 效应被 PC 吸收、SE 膨胀、无显著标记(实测 MK0 p=0.77)。
  • 正确设计:2 群体结构(各 16 株)+ 200 标记,非 QTL 标记携带「群轴 + 组内独立伪随机变异」(PC1=群轴、PC2/3 与 QTL 标记低相关),QTL 标记剂量在群体内多重集一致(与群轴正交)→ PC 校正后效应保留、双 QTL Bonf 显著。
  • 功效n=32、m=200、QTL 效应 2.0 时 p1e-5Bonf 阈值 2.5e-4 余量 10×);n=24 则功效不足(p2.5e-4 擦线)。

十六、九缺口补齐:经典侧计算端点 + 分子侧严谨性 + 求解器核心(2026-08-04

用户自 GWAS/QTL/MAS 闭环后重扫 12 项缺口,A1(S-等位)与 A4(G×R)已同日落地剔除,余 9 项拍板「全部补齐」,分三批独立 e2e + 回归。三批均 e2e 通过、回归零回归,后端重启 + openapi 核验 + HTTP smoke + 前端 vue-tsc EXIT=0。

16.1 批1 经典侧计算端点(纯计算不建表,statistics/controller.py + service.py + 前端 statistics/index.vue

缺口 落地
A5 数据质量 POST /statistics/data-quality——data_quality_report(trait_id, site_id?, tree_ids?)tree 级观测装配(同 run_ablup+ 缺失率 + CV + IQRMAD 稳健 z-score 双法异常标记,输出 {trait, n_trees, missing_rate, cv, outliers, summary};前端「数据质量」对话框
A3 遗传增益 POST /statistics/genetic-gain——ΔG=k·r_g·σ_Ak 由 top_p 经 Acklam 有理近似 Φ⁻¹(纯 numpy 零 scipy)、r_g=批次 PA(√mean reliability)、σ_A=√h²·σ_P,逐轮 {round, current_mean, ΔG_units, ΔG_pct_mean, next_mean, cumulative}
A6 主动选配 POST /statistics/mating-recommend——S-等位硬过滤(复用 cross_combination._s_compat_checknone 剔除/half flag+ 亲缘 A 惩罚 score=w_ebv·mid_parent_EBVw_kin·max(0,rthreshold){pairs:[{female, male, ebv_mean, r, s_compat, score, flags}]}计算端点不落库(用户拍板)

16.2 批2 分子侧严谨性(gwas.py / genomic.py / VCF 装配 / MAS 语义)

缺口 落地
B1 EMMAX gwas._emmax:零模型 y=Xβ+u+e(u~N(0,σ²g·K)),方差分量复用 genomic._profile_solveeigh 对角化 K=QΛQ' → V⁻¹=Q(σ²Λ+σ²eI)⁻¹Q';逐标记 GLS t²→fdist.f_pvalue;run_gwas 后处理抽共享函数,GLM 逐字节不变;method="emmax"gwas 1.1.0
B2 SSR 多等位 VCF 按 ALT 数定 marker_type_allelic_from_gt 每等位 0/1/23 处装配按 marker_type 分支 SSR 展开每等位一列;build_g_matrix 多等位 VanRaden 推广(genomic 1.2.0
B3 QTL×E POST /statistics/gwas-qtl-x-e:分环境 run_gwas 合并 QTL → stable(≥2 环境同号)/ env-specific / 异号 G×QTL 警示,计算端点不建表
B4 MAS 语义 weld_mas_semantics.sql 幂等 ADD COLUMNmode/favorable_allele/haplotype_group_mas_hit_map additive/dominance/recessive/allele/haplotype 五语义

16.3 批3 求解器核心(blup.pyENGINE_VERSION 1.3.0

  • A2 AR1×AR1 空间协方差 solve_spatiale~N(0,σ²e·R)、R=AR1(ρ)⊗AR1(ρ)、R⁻¹ 纯 numpy eigh、REML 对 (h²,ρ) 坐标上升黄金搜索;run_ablup(spatial=True) → method=AR1×AR1/model_name=SPATIAL_*,ρ/σ²a/σ²e/h² 落 note;与 G×E/G×R 互斥、缺 row/col 坐标 409spatial=False 逐字节不变。
  • A7 稀疏 A⁻¹+共轭梯度_build_ainv_sparseCOO+ _cg_solvemax_iter=800/tol=1e-9);use_sparse = n_with_parents>0 and n>N_SPARSE(1000) 阈值分派 → "solver":"sparse-cg" + cg_iterHutchinson k=100(固定种子 20260804)估 PEV 对角 → "reliability_approx":True;收敛失败回退稠密;稠密路径(n≤1000)逐字节不变。

16.4 版本与验证

  • _DATA_VERSION v2.13ENGINE_VERSIONblup 1.3.0 / genomic 1.2.0 / gwas 1.1.0。
  • 批1 Temp/claude/e2e_data_mating_gain_20260804.pydata-quality 命中离群株 / ΔG 自洽 / mating-recommend 剔除不相容对 + 亲缘惩罚生效 / 无观测 409 门禁。
  • 批2 Temp/claude/e2e_molrigor_20260804.py 五段:EMMAX 复现双 QTL + SSR 混合 GBLUP 全标记进入 + QTL×E stable/env-specific + dominance/haplotype 语义命中 + 门禁。
  • 批3 Temp/claude/e2e_spatial_sparse_20260804.py 三段:AR1×AR1 ρ=0.9796/h²=0.0013/method 标签 + 稀疏路径 EBV 3.49e-12 / h² 0.00 / CG 7 折 / Hutchinson mean-rel Δ0.054n=20 最坏,文档标注近似)+ 默认稠密路径引擎级 0 差(落库 4.92e-05 为 numeric(12,4)/numeric(6,4) Postgres 量化,非回归)。
  • 回归e2e_gwas7 段)/e2e_advanced_gblup/e2e_gblup_cv/e2e_gxr/e2e_refine/e2e_corr_spatial 全绿;openapi 核验 4 新端点 + RunStatsIn.spatial/gxe/gxr + GwasRunIn/GwasQtlXEIn.method=emmax + MasPanelMarkerIn 三字段;HTTP smokedata-quality trait 28、genetic-gain top_p=0.2 得 k=1.3998、409 门禁);vue-tsc EXIT=0。

十七、十二项真缺口补齐:引擎三件 + 模块四件 + 底座五件(2026-08-05

用户「全部补齐」后做全量现状盘点(2 个 Explore 代理 + 关键文件精读),发现总表大量「待建」标记过时——35 个 module_bre 后端模块 CRUD 全部齐全、数据字典四类已灌、描述统计/ANOVA 引擎已落地。真实缺口收敛为 12 件,用户拍板范围=只补这 12 件;移动端(V1.2)/品种登记 PVP(V3.0)/AI 三件套(V4.0)留波次不建。分三批独立 e2e + 回归,每批验收。三批均 e2e 通过、全量回归零回归,后端重启 + openapi 核验(631 路径)+ vue-tsc EXIT=0。完整台账见规格 §8.248.26。

17.1 批1 引擎三件(solver 扩展,独立新路径)

  • ssGWASscripts/breeding_stats/gwas.pyENGINE_VERSION 1.2.0):run_gwas method="ssgwas" 分支 → _ssgwas——genomic.build_g_matrixblend 岭保正定)构 G → genomic.solve_gblup 全样本 GEBV û;Wang et al. 单步 GWAS MEM 对角近似ê_j=(M_j'Z'G⁻¹û)/(2Σp_j(1p_j))Var(ê_j)=σ²u/(2Σp_j(1p_j))Wald t=ê/SE、df=n2 → fdist.f_pvalue;共享 _finalize/_bh_qvalues/_cluster(GLM/EMMAX 逐字节不变);门禁无基因型样本报错、G⁻¹ 岭兜底;服务端 method 透传 + 前端 gwas 运行对话框下拉加 ssgwas。
  • 全 MT-BLUP 多变量 REMLscripts/breeding_stats/mtblup.pyENGINE_VERSION 1.1.0):solve_multi——m 性状 y 堆叠、X/Z 块对角、Var(u)=G0⊗A、Var(e)=diag(ve_i·I)EM-REML 迭代(单性状 REML 初始、G0 非对角 0 → 迭代更新 G0/ve、特征值截断 + Higham 投影保正定、max_iter 兜底不收敛→converged=False+warning);输出 G0 全元素 + r_g 矩阵 + n_iter/converged/warningrun_genetic_corrfull_mtblup=True 一次 m 性状给完整 G0(逐对 bivariate 路径保活)。
  • AR1×AR1 双参 ρscripts/breeding_stats/blup.pyENGINE_VERSION 1.4.0):solve_spatial(aniso=False)——R_ij=ρ_row^|Δrow|·ρ_col^|Δcol|、内层 _f_rho 拆 ρ_row/ρ_col 交替坐标上升;run_ablup(spatial=True, spatial_aniso=True) → method=AR1×AR1(aniso)、note 落 rho_row/rho_colaniso=False 输出与 v1 逐字节一致(回归断言);门禁/互斥/缺坐标逻辑不变。

17.2 批2 模块四件(标准 CRUD 五件套 + 前端 + 菜单翻转)

  • field_operation 农事操作 900051bre_field_operationtree_id/plot_id/op_type/op_date/op_detail/operator_id);op_type 字典(施肥/喷药/修剪/灌溉/疏果/套袋/采收)bre_dict 灌入。
  • observation 通用观测 900050bre_observation EAV 通用录入(可挂 plot 级、不强制 trait);obs_type numeric/text/date。
  • breeding_report 育种报告 900075bre_report CRUD + POST /report/generate(按 report_type 聚合 bre_prediction/bre_stability_result/bre_cv_result 成结构化报告 + doc_path);前端列表 + 生成对话框。
  • analysis_dataset 分析数据集 900070:新表 bre_analysis_datasettrait_codes/sample_ids/config jsonb + statuscreate_all + 幂等 weld 兜底);CRUD +「查看性状值」跳 statistics trait-values 复用既有视图。
  • 菜单翻转 + 文案清理:幂等 UPDATE component_path→module_bre/<name>/index、E 段按钮 900xxx900014/900015/900021/900061/900063/900065 菜单 description 残留「待建」→ UPDATE 去除。

17.3 批3 底座五件

  • 审计切面bre_audit_log16 列已建零实现)→ module_bre/audit/base_crud.py 三写方法事务内 flush 后追加 CREATE 记录级 / UPDATE 字段级 diff(每变更字段一行)/ DELETE 记录级settings.AUDIT_BRE_ENABLED + 模型 __bre_audit__ opt-in;批量导入会话标志抑制逐行、仅汇总 IMPORT 一条;GET /bre/audit/list|detail
  • 统一编号服务app/utils/number_gen.py NumberGenService(前缀/日期/序列/回绕规则)+ pg_advisory_xact_lock 原子取号 + bre_sequence 表;迁移 4 处(cross_combination YY+3位 / tree 组合-序号 / selection_result clone_code 扩位 / seedling batch_no YP-…),行为格式保持。
  • 超期预警定时任务:每日 job 按 selection_rule 扫描——树 N 年未决策(selection_result 无记录且定植超 N 年)/ pollen 批次过期(采集日+有效期)/ seed_lot 超期 → 写 bre_alertalert_type/entity_type/entity_id/message/status/created_id+ GET /bre/alert/list + 前端「预警中心」页。
  • 备份容灾backend/scripts/pg_backup.shpg_dump 自定义格式到 Temp/backup/ 按日期 + N 天轮转)+ pg_restore.sh;系统 job 每日 02:00ap_scheduler 3 系统 joboperation 清理 Sun 03:00 / alert 扫描 08:37 / 备份 02:17)。
  • BrAPI + MIAPPEmodule_bre/brapi/controller.pyapp 根注册 prefix /brapi/v2,只读不建表):germplasm/observationvariables/studies/observations/miappe 五端点,BrAPI 2.x metadata{pagination,status,datafiles}+result{data} 包裹、0 基分页;bre_germplasm → germplasmDbId/germplasmName/PUI/accessionNumber/commonCropName=Peach/genus=Prunus/species=persica/subtaxabre_trait → observationVariableDbId/trait/method/scalescale.dataType 映射 + validValues);observations 合并 bre_trait_observation + bre_observationtree→germplasm join)。

17.4 版本与验证

  • _DATA_VERSION v2.14ENGINE_VERSIONgwas 1.2.0ssGWAS/ mtblup 1.1.0solve_multi/ blup 1.4.0aniso/ genomic 1.2.0。
  • 批1 Temp/claude/e2e_gaps_engines_20260804.py 3 组 PASSssgwas 复现已知 QTL(与 EMMAX 同数据集显著标记一致)+ solve_multi 3 性状 G0 半正定、r_g 与逐对 bivariate 同号量级 + aniso 双参 ρ 合理、aniso=False 与 v1 逐字节一致。
  • 批2 Temp/claude/e2e_gaps_modules_20260805.py 15 组断言 PASS:四模块 CRUD + report generate 聚合 + 菜单翻转 + 文案清理。
  • 批3 Temp/claude/e2e_gaps_base_20260804.py 19 ok / 0 fail:审计三操作(CREATE 记录级 / UPDATE 字段级 diff / DELETE 记录级)+ 导入抑制仅汇总 + 8-session 并发取号 seq 1-8 唯一 + 三类预警命中(树超期/花粉过期/种子超期)、无负例误报、幂等去重、resolve→不再重复 + 备份脚本执行成功 + pg_restore --list 含 bre_alert/bre_sequence/bre_audit_log/bre_analysis_dataset + BrAPI 分页数学/germplasm/variable/study/observation 映射。
  • 回归e2e_spatial_sparse3 段)/e2e_gwas7 段)/e2e_molrigor5 段)/e2e_advanced_gblup4 段)/e2e_gblup_cv3 段)/e2e_refine8 段)/e2e_gxr4 段)/e2e_corr_spatial3 段)全复跑零回归;其间修复 1 处回归——statistics.service._allelic_columns 的 B2 SSR 兜底对 SNP 标记误把多等位调用(如 "1/2")当有效剂量 → 树 4 被误判基因型、破坏「非基因型株 GBLUP EBV=0」语义;修复:仅 marker_type 为空时走 SSR 每等位展开,SNP 标记 "1/2" 视为缺失(显式 SSR 分支不受影响,e2e_molrigor 全绿兜底)。
  • openapi:重启后端后核验 631 路径5 brapi + /bre/breeding_report/report/generate + /bre/audit/list|detail|options + /bre/alert/list|detail|options|resolve 全在);HTTP smokegermplasm 37 / variables 71 / studies 3 / observations 107 / miappe 3 模板);前端 vue-tsc --noEmit EXIT=0。

十八、桃育种业务流全面完善:业务数据链 + 统计算法 + 前端体验(2026-08-05

用户要求「对现有功能,结合桃育种实际业务流程与需求,进行全面测试分析,并完善」。三路审计(双代理并行 + 数据层性状字典探测 + 独立 grep/read 验证)收敛真实缺口 10 项(业务数据链 1-6 / 统计算法 7 / 前端 8-10),拍板全部实施 + 两裁决:导入按钮维持隐藏(23+ 页显式隐藏,导入弹窗/处理器/后端端点完整保留)、采收入口走农事操作op_type=harvest 结构化产量表单 + 同步统计引擎,非独立模块)。批A 业务数据链(A1-A6)/ 批B 统计算法(B1-B4)/ 批C 前端(C1-C4),分三批独立 e2e + 全量回归零回归,后端重启 + openapi 核验 + vue-tsc EXIT=0。完整台账见规格 §8.27。

18.1 批A 业务数据链(A1-A6

  • A1 果实采收结构化入口field_operation/{model,service,schema}.py):bre_field_operationyield_kg/fruit_count/avg_fruit_weight/marketable_rate 4 可空列(backend/sql/weld_busflow.sql ADD COLUMN IF NOT EXISTS 幂等,create_all 不建已有表新列);service create/update 当 op_type=="harvest" 且 tree_id 非空且有产量数据 → 按 trait_codesingle_tree_yield/fruit_number/avg_fruit_weight/marketable_rate)查 trait_id 同步写 bre_trait_observationevaluate_year=op_date.year、trial_study_id 由 plot 继承),trait_code 缺失跳过不 409plot 级采收只留 field_operation,不进树级统计
  • A2 性状种子backend/sql/bre_yield_phenology_traits.sqlON CONFLICT(trait_code) DO UPDATE 幂等):产量构成 5(单株产量/果数/均果重/好果率/裂果率 low)+ 物候 3 date 型(盛花期/果实成熟期/落叶期)+ 品质 3(可溶性固形物/可滴定酸 low/固酸比)+ 生长量 3(主干周长/树高/冠幅)+ 描述性 categorical 5(果形/茸毛/离核/果皮底色/着色类型,into_ebv=0)。
  • A3 种质级观测bre_observation 加可空 germplasm_idFK→bre_germplasmweld ALTER + index);observation service assert_parents_exist 扩展种质校验;前端表单种质选择器 + 搜索栏 germplasm 过滤。
  • A4 授粉→收种→种子处理补链bre_seed_lot.pollination_idFK→bre_pollination+ bre_seed_treatment.seed_lot_idFK→bre_seed_lotweld ALTER);前端 seed_lot 授粉选择器(按 combination 过滤)、seed_treatment 种子批次选择器。
  • A5 EAV 观测校验observation + trait_observation create/update):obs_type=numeric→parse float、obs_type=date→parse 日期,否则 409trait 有 valid_min/valid_max 且 numeric → 越界 409重复校验 同 (tree_id|plot_id|germplasm_id, trait_id, obs_year, obs_date) 已存在 → 409(精确到日,同日不同 trait / 不同日多次观测放行)。
  • A6 阶段自动设置 + 成株门禁tree.service create 当 stage 为空 → 按 breeding_generation 推断(F 代杂种→juvenile、亲本/嫁接成株→evaluation);trait_observation create 门禁 trait.stage=evaluation 而 tree.stage=juvenile → 409「童期树不可录成株性状」;juvenile 性状录童期树仍允许;不影响 decision_preview 的 marker 辅助选入(非观测路径)。

18.2 批B 统计算法(B1-B4

  • B1 type-B 多环境遗传力statistics/service.py):_values_by_tree_env(按 trait_id + trial_study_id/evaluate_year 分环境聚合树→值)+ run_type_b_heredity 复用 mtblup.solve_bivariate 把环境当"性状"phenos={"E1":{tree:v},"E2":{tree:v}} 同一系谱)精确 REML 估 r_g;method="calo" 备选(分环境 EBV 相关/√rel);env_dim="site"|"year";共有树 <2 → 409;落 bre_type_b_resultstatistics/model.py 新表,镜像 GENCORR+ controller POST /statistics/type-b-heredity + GET /type-b + GET /type-b/{id};前端 type-B tab。
  • B2 correlation genetic 模式correlation_matrixmode="pheno"|"genetic"g_methodyearpheno 分支逐字节不动genetic 走新私有 _genetic_corr_matrix 逐对 mtblup.solve_bivariate 组装 G0(对角 1、非对角钳[-1,1]),不落库(对齐 data_quality 计算端点模式);schema CorrelationIn 加 mode/g_method/year。
  • B3 selection_index 自动权重auto_weights: bool=False → True 时权重=_trait_meta_map.default_h2(实测 h² 优先,兜底 0.1)、强制 use_h2=False(防双重相乘)、direction 由 _weighted_z_index asc 翻转处理;weights_json 记 "__auto":trueinto_ebv=0 剔除进 dropped。
  • B4 UPGMA 聚类run_clustertrait_ids/entity_type(tree|clone)/mode(pheno|genetic)/distance(1-|r| 或 euclidean 标准化)/k)输入矩阵复用 _genetic_corr_matrix/correlation_matrixUPGMA 纯 numpy(距离矩阵迭代合并,无 scipy);输出 {clusters, merges, order}controller POST /statistics/cluster(不落库);前端 cluster 树状图 tab。

18.3 批C 前端(C1-C4,按用户裁决:不恢复导入按钮)

  • C1 观测录入增强observation 页搜索栏加 plot/trial_study(站点)/germplasm 过滤(ObservationQueryParam 加 tree_id/plot_id/germplasm_id/trial_study_id+ germplasm 表单(A3);field_operation 页 op_type=harvest 动态显示产量结构化表单 + 表格 4 列。
  • C2 统计可视化 EChartsecharts.ts 注册 HeatmapChart + VisualMapComponentstatistics/index.vue correlation 热图(mode 切换)+ gblup 可靠性热图/EBV 趋势折线(per-batch 聚合)+ type-B tab(热图+明细)+ cluster 树状图;图表生命周期(activeTab→resize、window resize、onBeforeUnmount dispose)。
  • C3 combination-funnel 前端入口statistics 工具栏「组合得失漏斗」按钮 + 1080px 对话框调 GET /statistics/combination-funnel(后端已有、前端此前缺失)。
  • C4 stage_phenotype 容器同步_shared/StageView.vue compMap 注册 Observation/FieldOperationstage_phenotype/index.vue tabs 通用观测/农事操作翻真实页。

18.4 版本与验证

  • _DATA_VERSION v2.15service.py:94);引擎版本不变mtblup/blup/gwas/genomic 本轮未改)。
  • 批A Temp/claude/e2e_busflow_20260805.py 11 组断言 PASS(A1 采收同步 4 行观测/plot 级不写 + A2 性状种子齐全 + A3 种质观测回查 + A4 授粉→收种→处理全链路 + A5 非法/越界/重复 409 + A6 F1 自动 juvenile、童期录成株 409)。
  • 批B Temp/claude/e2e_statsflow_20260805.py 15 组断言 PASStype-B 矩阵对角 1/对称/r_g 范围/site·year 环境集不同/n_common 共有树/GET 回查 + correlation pheno 逐字节回归/genetic 对称对角 1/calo 回退 + index auto==手工 default_h2 权重/asc 翻转/into_ebv=0 剔除 + cluster 3 已知类还原/k 边界/clone 聚合)。
  • 批C HTTP smoke Temp/claude/smoke_busflow_c_20260805.py 10 检查全过observation 3 过滤对真实数据 n=1 全命中 + funnel n=21 + correlation pheno/genetic + type-b list + cluster POST + auto_weights);vue-tsc --noEmit EXIT=0。
  • 回归11 套件全复跑零回归——e2e_spatial_sparse / e2e_gwas / e2e_molrigor / e2e_advanced_gblup / e2e_gblup_cv / e2e_refine / e2e_gxr / e2e_corr_spatial / e2e_gaps_engines / e2e_gaps_modules / e2e_gaps_base(其间同步 e2e_spatial_sparse 两处 data_version 断言 v2.14→v2.15,版本语义更新非回归)。
  • openapi:后端重启核验 /statistics/type-b-heredity/type-b/type-b/{id}/statistics/clustercorrelation?mode/genetic/selection-index auto_weights 全在;observation list 四过滤(tree/plot/germplasm/trial_study)经真实 HTTP 命中。

18.5 世代闭环修复:单株晋级同步落系谱(2026-08-05 跟进)

用户报告闭环断裂selection_result/service._promote_tree_to_clone 晋升单株到品系(line/regional_trial/released)时仅 BreedingGermplasmCRUD.create(cultivar_name=clone_code) 建种质,未同步写 bre_pedigree → 新种质在统计引擎 _build_pedigreestatistics/service.py:299,按 bre_pedigree.child_codegermplasm.cultivar_name 匹配祖先)里查不到亲本,被当 founder,跨世代系谱链断裂:A-BLUP / 亲缘矩阵 / 选配近交规避跨代失效、遗传增益滚雪球效应归零。

修复selection_result/service.py):晋级到 _GERMPLASM_STAGES 且树未关联种质时,建 bre_germplasm 携带 generation/stage,并自动落一条 bre_pedigreechild_code=clone_code(品种名)dam_id/sire_id=tree.dam_id/sire_id(为空回退组合 female_parent_id/male_parent_id)、combination_idgeneration=tree.generation、remark「单株晋级自动落系谱(世代闭环)」;child_code 幂等查重(已存在不重复落)。附 combo=None 顶部初始化,消除"树已有 clone(ap/sp 晋级过)再晋级品系"路径的 UnboundLocalError 隐患。

引擎级验证Temp/claude/e2e_pedigree_closure_20260805.py,11 组断言全过):① 晋升 line → 建种质携带 generation/stage + 自动落谱(dam/sire/combination/generation 齐);② _build_pedigree 对下一代树输出 g{晋升种质} 带 dam/sire(非 founder);③ A 矩阵跨代恢复——两棵仅经晋升种质共享祖先的下一代树,亲缘 A[T2,T3]=0(修复前,gT1 当 founder)→ 0.125(修复后,血缘推导 2·¼·f(gT1,gA)=2·¼·¼);A[gT1,gA]=0.5(亲子)佐证链条接通;④ tree.dam/sire 为空 → 组合亲本回退落谱;⑤ child_code 预置行不重复;⑥ 已有 clone(sp 晋级过)再晋级品系 → else 分支回退组合亲本落谱(combo=None 初始化防 UnboundLocalError 的回归用例)。

回归e2e_batch_selection(晋级主线,含新建谱行被 combo CASCADE 清理无残留)/ e2e_gaps_base19 ok/ e2e_spatial_sparse / e2e_advanced_gblup / e2e_gaps_modules15 组)全过零回归。

18.6 近交惩罚「静默关闭」修复:亲缘矩阵多源解析 + 显式告警(2026-08-05 跟进)

用户报告最隐蔽的坑mating_recommend 的亲缘矩阵靠 _germplasm_pedigreestatistics/service.py)用 bre_pedigree.child_code 与种质 cultivar_name/accession_no 精确字符串匹配来建。一旦名称不完全一致(大小写/空格/代号),pedigree 返回空 → rmat={} → 所有配对 r=0kin_pen=max(0,0thr)=0近交规避整体失效,且无任何告警——用户以为系统在避近交,实际没避。用户提出三点修复方向:① 匹配失败显式告警;② 优先用种质实体自带 dam/sire 或 clone/tree 聚合,而非名称反查;③ 绝不静默 no-op。核实确认,并额外发现:候选既是 child 又是祖先时 g{id} 被重复追加 → blup.relationship_matrix 抛『系谱个体重复』→ 端点崩溃。

修复statistics/service.py)——重写 _germplasm_pedigree多源级联(返回 (pedigree, coverage)coverage={total,resolved,resolved_ids,founder,matched_rows,orphan_rows,fk_sources}):

  1. ① 显式系谱(权威)bre_pedigree.child_code 规范化(strip+casefold)命中 cultivar_name/accession_no 索引——保留手录系谱语义,并直接修复大小写/空格错配;
  2. ② FK 兜底tree.germplasm_id == 该种质 的树 → 其 dam_id/sire_id 全集去重后唯一一致才采纳(升种质=升谱树自带种质级亲本,消除名称反查对代号错配的脆弱性);多对歧义(trial 树挂冲突亲本)→ 视为无回退 founder,不武断选取;
  3. ③ founder。祖先以同级联 BFS 展开 + 去重(修复重复抛错崩溃 + 打通跨代系谱链)。

mating_recommend 新增显式告警:kinship_status=ok|partial|none + kinship_warning(none→「候选亲本均未解析到系谱…近交惩罚已禁用:所有配对 r 按 0 计」;partial→列未解析亲本名单;ok 但有孤儿行→「bre_pedigree 有 N 条 child_code 未匹配任何种质名称(孤儿记录),跨代亲缘可能低估」)+ 逐对 flags 加「亲缘未解析(r 按 0 计)」;返回体新增 kinshipresolved/founder/matched_rows/orphan_rows/fk_sources)。设计红线:FK 只做兜底、绝不覆盖显式系谱(A6 回归保真:trial 树 FK 挂 FM/MM 与显式系谱 dam=G0 冲突 → r(G0,G4)=0.5 保持)。

验证Temp/claude/e2e_mating_kinship_20260805.py14 组断言全过):① FK 兜底恢复(无 ped 行升种质树直连 → r(GX,GA)=0.5,修复前为 0);② 孤儿行告警(全解析 status=ok + orphan 警告);③ 规范化匹配(child_code 大小写变体仍命中显式系谱);④ 三代链不崩 + r(GX,GW)=0.5 / r(GA,GW)=0.25;⑤ 全 founder → status=none + 显式告警 + 逐对旗标;⑥ partial → 未解析亲本名单。回归e2e_data_mating_gainA6r=0.5 保真)/ e2e_batch_selection / e2e_gaps_base 全过零回归。HTTP 核验:后端重启后 /bre/statistics/mating-recommend 真实数据 32/33 → kinship_status=none + kinship_warning 含「近交惩罚已禁用」+ kinship={resolved:0,founder:2,orphan_rows:2} + 逐对旗标(顺带暴露 2 条真实孤儿系谱行——数据质量信号)。

18.7 选配「亲本 EBV」回退逻辑方法学修复:direct 优先 + 子代测验降权 + 双侧去重(2026-08-05 跟进)

用户报告方法学错误mating_recommend 旧实现对无直接 EBV 行(ABLUP/GBLUP 按树写、germplasm_id 为空)的候选种质,用**「其子代树 EBV 均值」回退代表该亲本育种值**。三条质疑核实成立:① 这是 progeny-test 值(子代世代预测值 ≈½亲本BV+共亲本渗入+孟德尔抽样),不是亲本自身育种值;② 同一子代树若双亲都缺直接 EBV,被等权计入 dam 与 sire 两侧,稀释严重;③ 跨组合混合无区分。会误导选配排序。用户提出修复方向:优先用亲本自身预测值;回退值必须显式标注「基于子代测验的近似」并降权参与打分

修复statistics/service.py mating_recommend):

  1. direct 优先:种质级 EBV 行(germplasm_id 直连)=亲本自身预测值,无条件最优先;有 direct 的候选绝不被其子代树值污染(回退仅对 missing 集生效,杜绝树级 99.0 泄漏进亲本)。
  2. 回退显式标注 + 降权:新增 _EBV_SOURCE_FACTOR = {direct:1.0, progeny:0.5, missing:0.0};打分改 mid=(f_a·ebv_a+f_b·ebv_b)/2score=w_ebv·midw_kin·pen——progeny 近似按半权参与,绝不冒充亲本自身值、不掩盖 direct;missing 按 0 计(与旧行为一致,全缺失时排序不变)。
  3. 双侧等权稀释修复:子代树双亲均在 missing 集(如 FM×MM 双亲均无 direct)→ 剔除(该树均值无法归属,防止同值计入两侧);仅单侧可归属的树才计入对应亲本。
  4. 跨组合辨别:回退亲本记 n_progeny(子代数)/n_combos(跨组合数),供调用方判断子代测验近似的稳健性。
  5. 显式可查,绝不静默降级:返回体新增 candidate_ebv(每候选 germplasm_id/name/value/source/n_progeny/n_combosmissing 的 value=None+ ebv_source.coveragedirect/progeny/missing 计数)+ 逐对 flags 加「亲本EBV为子代测验近似(降权0.5)」/「亲本无EBV(按0计)」。

验证Temp/claude/e2e_mating_ebv_20260805.py5 组断言全过):① candidate_ebv 来源可查——P0=direct/10.0(子代树值 99.0 未泄漏)、P1=progeny/8.0n_progeny=3、n_combos=2)、P2/P3/P4=missing/None;② ebv_source.coverage={direct:1,progeny:1,missing:3};③ 降权打分——P0×P1 ebv_mid=7.0=(1.0·10+0.5·8)/2(≠9.0 原始均值)+「子代测验近似」旗标、P0×P2 ebv_mid=5.0+「无EBV」旗标;④ 双侧去重——P3×P4 双亲均缺 → 子代树剔除 → source=missing、ebv_mid=0.0(旧代码会 progeny=7.0);⑤ score 降序、榜首 P0×P1(加权 EBV 互补最高)。回归e2e_data_mating_gainA6 无 Prediction 行 → 全 missing → 排序不变)/ e2e_mating_kinshipok=14/ e2e_batch_selection / e2e_gaps_base19 ok)全过零回归。HTTP 核验:后端重启后 /bre/statistics/mating-recommend 真实数据返回 candidate_ebv12 候选全 source=missing/value=None+ ebv_source.coverage={direct:0,progeny:0,missing:12} + 逐对旗标。

18.8 数据质量「离群值」方向语义错位修复:同向=极值候选(精英)/ 反向=疑似录入错误(2026-08-05 跟进)

用户报告语义错位data_quality_report(§8.17①/§8.23① 的 A5 数据质量端点)旧实现用 IQR(Q11.5IQR/Q3+1.5IQR) 超界 + MAD 稳健 z-score(>3.5) 双通道把任何偏离分布的值都标为「离群株(疑似异常)」。但桃育种按选育目标选极端表型——果重/固酸比/可溶性固形物要高的、裂果率/病指要低的——正向偏离恰恰是育种家要选的精英单株(与高 EBV 高度相关),把精英候选标成「疑似录入错误」会诱导弃选、误导决策。用户提出修复方向:仅当偏离方向与选育目标相反才提示疑似录入错误;同向偏离标为「极值候选(精英)」

修复statistics/service.py data_quality_report):

  1. 方向感知trait_row = await self._numeric_trait(trait_id) 后取 direction = (trait_row.direction or "desc").lower()desirable_high = direction != "asc"desc/None → 高值优;asc → 低值优)。判定标准与 v2.3 性状方向标注链路一致,低优性状(裂果率/病指)反向侧为高值。
  2. 双通道分流:IQR/MAD 命中的株再按偏离侧分类——is_high = v > medis_elite = is_high == desirable_high同向偏离 → extreme_candidatesclass="extreme_candidate"side=high/low,极值候选·精英);反向偏离 → outliersclass="outlier",疑似录入错误)。两表互斥,精英绝不进错误表。
  3. 返回体:新增 directionextreme_candidatestree_id/value/z/side/class/reasons)、summary.n_extreme_candidatessummary.has_warning/n_outliers/outlier_rate 语义收紧为疑似录入错误计数(不再把精英株计入告警)。is_high = v > med 而非 >0,中位对称稳健。
  4. 前端statistics/index.vue 数据质量 tab):选育方向指示条(高值优 desc / 低值优 asc)+ 双表——「极值候选(精英)」success 标签表 + 「疑似录入错误」danger 标签表;hint 说明同向=精英/反向=错误;无错误时绿色 info alert「未发现疑似录入错误」而非黄色警告。

验证Temp/claude/e2e_data_mating_gain_20260804.py [1] 17 株断言全过):15 正常树 + 精英树({PREFIX}-HI,值 16.0G3+ 错误树({PREFIX}-LO,值 2.0G3),direction=desc——精英树进 extreme_candidatesclass=extreme_candidate/side=high)且不在 outliers;错误树进 outliersclass=outlier/side=low);n_trees=17n_extreme_candidates=1n_outliers=1missing_rate=0回归e2e_mating_kinshipok=14/ e2e_batch_selection / e2e_gaps_base19 ok)全过零回归。HTTP 核验:后端重启后 POST /bre/statistics/data-quality 对 asc 裂果率(bB_DIR5668)与 desc 果重(dA_DIR5668)两真实性状返回 direction/extreme_candidates/outliers/summary.n_extreme_candidates 全部正确——真实数据无极端偏离 → 双表空(无误报)。

18.9 ΔG 投影假设声明 + 工程健壮性打磨:note 假设 + spatial 缺坐标降级 + numpy 收敛(2026-08-05 跟进)

用户报告两点,均非功能 bug(核实确认后拍板落地):① genetic_gain(§8.23① A3 遗传增益端点)的 next_pheno_mean = pheno_mean ± dg 隐含「环境均值恒定」假设——若年际气候漂移,投影会偏;属投影演示性质,应显式标注假设。② 工程健壮性细节——spatial 模型要求所有观测树都有 row/col,否则整批 ValueError(门禁合理但无「剔除缺坐标者继续」的优雅降级);data_quality_report/genetic_gain 函数体内重复 import numpy;多处 numpy 计算未利用托管 venv 向量化优势。

修复statistics/service.py + statistics/index.vue):

  1. ① ΔG 投影假设显式声明genetic_gain 返回体新增 note 静态常量——投影假设环境均值恒定(未计入年际气候漂移与栽培措施变化);ΔG=k·r_g·σ_A 仅含遗传增益分量,next_pheno_mean 为投影演示值而非实测预测。(同性状/同数据重跑不变,探针断言稳定)。前端 gain tab 在描述区后、轮次表前展示 el-alert type="info" 提示假设边界。
  2. ② spatial 缺坐标优雅降级run_ablup(spatial=True) 坐标收集循环把 row_no/col_no 为空的观测树记入 missing_coord_ids剔除其表型但保留系谱——blup.solve_spatial 本就对所有个体(含无表型)输出 EBV,故缺坐标株 EBV 仍由系谱预测;剔除数显式写入批次 note「缺坐标剔除N株表型(EBV由系谱预测)」;仅当全部观测树都缺坐标(coords 空)才整批 409(提示先在单株录入填行号/列号)。input_hash 随剔除后的表型子集计算(同数据可复现)。设计红线:缺坐标仅剔除该株表型、绝不剔除系谱——系谱是空间 EBV 的预测基础。
  3. ③ numpy 工程清理data_quality_report/genetic_gain 及另 5 处(genetic_corr/selection_index/bivariate/genetic/type-B/UPGMA)函数体内重复 import numpy 全部收敛为模块级单次 import numpy as npservice.py:24);data_quality_report 逐株 flag 循环改 numpy 布尔掩码向量化——z_robust_all = np.where(mad>1e-9, 0.6745·(amed)/mad, 0)iqr_flag_all = (a<q11.5iqr)|(a>q3+1.5iqr)z_flag_all = |z_robust|>3.5flagged_idx = np.nonzero(iqr|z)[0] 一次性定位命中株,输出逐字节不变(精英/错误分流逻辑不变)。

验证Temp/claude/e2e_spatial_sparse_20260804.py 降级场景断言全过):5 株(前 4 株 2×2 网格带 row/col + 第 5 株 row_no=None)观测 [10.0,10.5,11.0,11.5,9.0] → method=AR1×AR1train_n=4、note 含「缺坐标剔除1株」、5 株全部有 EBV 行(缺坐标株由系谱预测);全缺坐标场景仍整批 409 且报错含 row_no/col_no 数据需求。A6 探针 [2] 新增 note 断言:note 含「环境均值恒定」且两性状稳定一致。回归e2e_spatial_sparse / e2e_data_mating_gain / e2e_mating_kinshipok=14/ e2e_batch_selection / e2e_gaps_base19 ok)五套零回归。vue-tsc EXIT=0。HTTP 核验:后端重启后 POST /bre/statistics/genetic-gain(真实性状 dA_DIR5668)返回 note(含「环境均值恒定」);POST /bre/statistics/data-quality 返回 direction: asc、双表空无误报。

18.10 A–F 六项功能级缺口·批1 父本验证 + 近交衰退:一致性校验 + F→表型回归(2026-08-05 跟进)

用户全模块 grep 实证 A–F 六项功能级缺口(「有无/深度」问题,非正确性 bug),逐项复核确认 + 拍板「全部六项分批落地」。批1 = A 父本验证(pollination 花粉来源一致性 / tree 显式亲本警示 / cross_combination 自交门禁)+ C 近交衰退(_DATA_VERSION v2.22)。

A 父本验证consistency,不落库):

  1. A1 pollination 花粉来源父本一致性pollination/service.py 新增 _validate_pollen_parent):批次 pollen_lot.male_tree_id 声明采集父本树时,授粉声明 male_tree_id 须一致,否则 409「花粉批次 {lot_code} 采集自父本树 {X},与授粉声明父本树 {Y} 不一致,请确认花粉来源」;批次无采集父本(混合/外地采集)或授粉未声明父本 → 放行。create/update 统一在 _validate_pollen_window 后调用(update 取 existing 回退)。
  2. A2 tree 显式亲本 vs 组合父母本警示tree/service.py _resolve_parents 改返回 (dam, sire, warning)):显式 dam/sire 与组合 female/male_parent 不一致时聚合「显式母本与组合母本不一致;显式父本与组合父本不一致(以显式为准)」;warning 不阻断(tree 可独立建,武断 409 会误伤);tree/schema.py 加只读 warning 字段(仅返回体,不落库)。
  3. A3 cross_combination 同质自交门禁cross_combination/service.py _check_parent_roles 角色解析后追加):female_parent_id == male_parent_id → 409「母本与父本同为「{名}」,自交组合请确认」;create/update 生效亲本统一触发(与既有 S-等位 409 语义一致不冲突)。

C 近交衰退分析statistics/ 三件套 + 前端,计算端点不建表):

  • POST /statistics/inbreeding-depressionInbreedingDepressionIntrait_id/trait_code + year/trial_study_id 可选 + min_n=10)——inbreeding_depressiontree 系谱(t{tree_id} 个体 + g{germplasm_id} founder)→ blup.relationship_matrix 取 F=A_ii1关键洞见:inbreeding dict 仅含 F>0,非近交树须从 individuals 默认 F=0 兜底,否则非近交株被排除出回归;trait 树级表型 select(obs.tree_id, func.avg(value_numeric)).group_by(tree_id) 聚合(按 year/trial_study_id 可选过滤)→ 交集树 → 纯 numpy np.linalg.lstsq 线性回归 phenotype ~ F。返回 {sufficient, reason, n_obs, mean_F, max_F, direction, regression:{intercept, slope, r2, t_slope, depression_rate, has_depression, interpretation}, high_inbreeding:[{tree_id, tree_no, F, value}]}has_depression = slope<0 且 t_slope≤−1.645(单侧 95% 大样本近似);high_inbreeding 按 F 降序取前 10n<min_n 优雅降级 sufficient=False + reason(不 409)。
  • 前端「亲缘/近交」tab 加「近交衰退(F → 表型)」区:trait select + year input + 运行;el-alertinsufficient=warning / has_depression=error / 无衰退=success+ el-descriptions + high_inbreeding 表。修 vue-tsc TS2322el-alert :type 无 danger 合法值,改 'error'

验证Temp/claude/e2e_parent_validation_20260805.py 10 断言全过——A1 不一致 409(含「不一致」)/一致放行/混合批次放行/update 同门禁;A2 双侧警示(含「以显式为准」、dam/sire=显式)/单侧仅父本/一致无警示/update 警示;A3 create/update 同质 409(含「自交」)。Temp/claude/e2e_inbreeding_depression_20260805.py 4 断言全过——12 树(6×F=0 + 6×F=0.5 自交)衰退性状 y=10060F+ε → slope≈−60/t 显著负/r²>0.9/has_depression=true/depression_rate<0/max_F≈0.5/mean_F≈0.25/high_inbreeding 前 6 全为 S-自交 F=0.5、后 4 F=0;无衰退 y≈100 → slope≈0/「未检出」;min_n=20 → insufficient 含「12 棵」「≥20」;trait_id=99999999 → 409。回归e2e_spatial_sparsev2.22 断言同步)/ e2e_statsflow / e2e_data_mating_gain / e2e_mating_kinship / e2e_batch_selection / e2e_gaps_base 六套零回归。vue-tsc EXIT=0。HTTP 核验:后端重启后 POST /bre/statistics/inbreeding-depression(真实稀疏数据)返回 code=0、sufficient=false、n_obs=2、reason「同时具备系谱近交系数 F 与表型的树仅 2 棵(需 ≥10)」、mean_F/max_F/regression=null、high_inbreeding=[]。

18.11 A–F 六项功能级缺口·批2 GS 家系 CV + 试验设计深度:家系阻塞折 + RCBD 生成/区组 ANOVA2026-08-05 跟进)

AF 六项缺口批2 = B GS 家系 CV(深度:随机分层 → 家系阻塞折)+ F 试验设计深度RCBD 生成 + 设计基 ANOVA)。批1 已落地 §18.10v2.22);本批 _DATA_VERSION v2.23。

B GS 家系 CVgenomic.py + statistics/service.py + 前端):

  1. 引擎 genomic.kfold_cv_genomicsplit: str = "random" + family_of: dict[str, str] | None = Nonesplit="random" → 现有 round-robin bin_of = {c: i % k} 逐字节不变(回归零变化);split="family" → 照 blup.kfold_cv 的 sire 家系留出模式——fam_of = {ind: (family_of or {}).get(ind, ("self", ind))}(无家系个体自成一族)→ fams 去重 → rng.shuffle(fams)fam_bin = {f: i % k}bin_of = {c: fam_bin[fam_of[c]]}同家系个体同折(防亲缘泄漏高估准确度);家系数 < 折数 k → 折叠为 n_families 折 + warning「家系数 {n} < 请求折数,折叠为 {k} 折(family-blocked)」;单家系(n_families<2)→ folds=[] + warning「可验证个体仅构成 1 个家系,无法家系阻塞交叉验证(请改用随机分层)」。输出加 n_families(逐键对齐 blup.kfold_cv)。
  2. 服务 run_cvsplit="random"|"family" 透传(controller/schemajob params_json 记 split):GS 分支 split=="family" 时用既有 ped_rowsselect 顺序 id/dam_id/sire_id/trial_study_id/rootstock_id/female_parent_id/male_parent_id/combination_id/clone_id/germplasm_id)构建 family_of = {f"t{tid}": f"s{s}"}s = sire if sire is not None else cmsire 缺失回退组合 male_parent);落库 CvResultModel.notesplit=family · n_families={N}+ 引擎 warning 拼接)。
  3. 前端「交叉验证」tab runCv 参数区加 split 下拉(random=随机分层/family=家系阻塞)+ 结果表 n_families 列。

F 试验设计深度trial_study_entry/model.py + weld_trial_study_entry.sql + statistics/ 三件 + anova.py + 前端):

  1. F1 RCBD 生成器bre_trial_study_entry 加可空 block_no integermodel 列 block_no: Mapped[int | None] + sql/weld_trial_study_entry.sql ALTER TABLE ... ADD COLUMN IF NOT EXISTScreate_all 只建新表故 weld 幂等兜底);新端点 POST /statistics/trial-designTrialDesignIntrial_study_id + design_type="rcbd" + seed 可选)——trial_designdb.get(TrialStudyModel) 409、design_type≠rcbd 409、block_count=study.block_count or 1、按 entry_number 取参试条目(空 409「无参试条目」)→ random.Random(seed) 洗牌 + round-robin 分进区组(均分 + 组内随机 = 田间布局)→ update(...).values(block_no=case(block_of, value=TrialStudyEntryModel.id, else_=None)) 批量落库 + flush;返回 {trial_study_id, design_type, block_count, seed, n_entries, blocks:{str(b): [entry_number…]}}
  2. F2 设计基 ANOVAanova.solve_rcbd(rows)rows={"group","block","value"}RCBD 双因素 Type I 顺序X1→Xg→Xgb dummy 矩阵:SS_group=rss(X1)rss(Xg)、SS_block=rss(Xg)rss(Xgb)、SS_error=rss(Xgb),纯 numpy + fdist.f_pvalue),输出含 f_block/p_block/groups/blocks/warning<2 组合或 <2 区组 ValueErrordf_error≤0 → warning「区组设计过饱和」);anova.solve 单因素逐字节不变run_anovablock: bool=Falseblock=False → 原单因素路径不变;block=True → 查 bre_tree.block_no 组 rows、过滤空 block、<2 区组 → 409「区组数据不足:需 ≥2 个区组(请先运行 /statistics/trial-design 生成设计并落库 block_no)」,method=ANOVA/H2/RCBD。
  3. 前端 statistics ANOVA tab 重构:顶部「生成 RCBD 设计」工具条(trial_study select + seed input + warning button+ 设计区组表 + trait select + year + el-checkbox anovaBlock「RCBD 区组校正」+ 提交;结果加 n_blocks/f_block/p_block 条件 v-if + 区组均值表。statistics.tstrialDesign() + TrialDesignResult

验证

  • Temp/claude/e2e_trial_design_20260805.py 5 组断言全过——[1] RCBD 生成(block_count=3/n_entries=9/3 区组×3 均分/9 条目齐全/seed·design_type 回显);[2] block_no 落库核验(紧随首次生成避免复现覆盖;落库区组集合==返回设计集合);[1b] seed=42 复现同一设计 / seed=43 异动;[3] block=False → method=ANOVA/H2、无 f_block/n_blocks/blocks 键(单因素逐字节不变);[4] block=True → method=ANOVA/H2/RCBD、n_blocks=3、ss_block>0、f_block>1、p_block 存在、区组均值随 +3/0/−3 递减;[5] 空研究点 409「无参试条目」。
  • Temp/claude/e2e_gs_family_cv_20260805.py 5 组断言全过——[1] 5 家系×3 全同胞 k=3 → method=KFCV/GBLUP、note「split=family · n_families=5」、家系阻塞折 n_test=[3,6,6][2] k=5 → 每折恰 1 家系 n_test 全 3[3] random k=3 → note 无 split=family、n_test=[5,5,5](随机分层回归零变化);[4] 引擎级 6 家系<请求 8 → 折叠 6 折 + warning[5] 单家系 → folds=[] + warning。注:探针树创建曾漏 db.add_all([fm, mm]) 致 germplasm.id=None → 组合父母本全空 → sire 全空 → n_families=15,补 add 后修正为 5(服务侧代码位置核实无误)。
  • 回归e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_busflow / e2e_mating_kinship / e2e_gaps_base / e2e_molrigor 七套零回归。vue-tsc EXIT=0。HTTP 核验:后端重启后 POST /bre/statistics/trial-design + POST /bre/statistics/anova/run(block=true)经真实端点返回。

18.12 A–F 六项功能级缺口·批3 OCS 最优贡献选择 + MABC 标记辅助回交:投影梯度求解器 + 前景/背景选择工作流(2026-08-05 跟进)

AF 六项缺口批3(收官)= D OCS 最优贡献选择 + E MABC 标记辅助回交。批1 §18.10v2.22)、批2 §18.11v2.23);本批 _DATA_VERSION v2.24。两端点纯计算不落库(对齐 data_quality 惯例);前端同批交付(选配推荐 tab OCS 运行区 + 独立回交 MABC tabvue-tsc EXIT=0)。

共享 helper 抽取 _candidate_ebv_mapstatistics/service.py:3429-3531):

  1. mating_recommend 内联 EBV 解析块原样抽取_candidate_ebv_map(prediction, tree_ids){germplasm_id → ebv}prediction batch ABLUP/GXEBLUP/GXRBLUP/GBLUP/ssGBLUP 全支持;direct germplasm_id 先取,缺失走 progeny 子代均值并 _EBV_SOURCE_FACTOR={direct:1.0, progeny:0.5, missing:0.0} 降权;返回 ebv_map/source/status/warning/cover/n_progeny/n_combos/ebv_mid
  2. 「双亲均缺直接 EBV → 子代树剔除(双侧去重)」规则随抽取原样保留——经 transcript 抽取前内联块 old_string 实证该规则已存在于抽取前代码(v2.19 方法论),非抽取回归;e2e_mating_ebv [4] P3×P4=0.0 权威验证、e2e_audit_fix_20260804 ④ 已同步语义。
  3. OCS 端点复用 _candidate_ebv_mapcandidate germplasm 直接取)+ mating_recommend 保留原内联调用(行为不变)——mating 回归 14/14 零变化证明抽取无副作用。

D OCS 最优贡献选择POST /statistics/ocs):

  1. _proj_simplex:欧氏投影到单纯形(numpy sort/arange 解析投影,无 scipy),_solve_ocs 投影梯度 + 回溯线搜索max Σc_i·ebv_i λ·c'Acs.t. Σc=n_select、c≥0A 由 _germplasm_pedigree + blup.relationship_matrix rmat 组装(对角=1、非对角候选对 r,覆盖<100% → kinship_status="partial" + warning)。
  2. 输出contributionsc 降序 + ebv/source/可选 n_progeny/n_combos)、mean_ebvavg_kinshipc'Ac)、kinship_quadvs_top_n(同 n 贪心 top-n 对照:mean_ebv 相当 + kinship_reduction,量化 OCS 亲缘控制价值)、ebv_source/kinship_status/kinship_warning
  3. 门禁:空候选 / n_select>候选数 / λ<0 → 409。

E MABC 标记辅助回交POST /statistics/mabc-progress):

  1. 前景选择:复用 _mas_hit_map/_mas_marker_hitadditive/dominance/recessive/allele/haplotype 五语义),foreground_pass = 命中 ≥ foreground_min_hitsstage 无关、童期幼苗即可)。
  2. 背景基因组恢复率background 面板逐标记候选 vs 轮回亲本「纯合剂量一致」比例(_pure_homologous:候选纯合且等位∈轮回亲本等位集;杂合不计),标记均值 = 恢复率 %(round 2)。
  3. 回交代建议_BC_LADDER=["F1","BC1","BC2","BC3","BC4","BC5"] + _MABC_GENERATIONS={"F1","BC1","BC2","BC3"};晋级 / 再回交 / 补测后判定 / 前景未通过 四分支 reason;recommended 前景通过按恢复率降序(None 排尾)。
  4. 门禁:空候选 / 空前景或背景面板 / generation∉_MABC_GENERATIONS / background_target∉(0,100] / 轮回亲本不存在 → 409。

验证

  • Temp/claude/e2e_ocs_20260805.py 17 断言全过——[1] Σc=3、c≥0、coverage=direct 5/5、c 降序、最高=A[2] mean_ebv 与 vs_top_n 相当 + kinship_reduction=0.0398 + kinship_quad≈4.641[3] λ↑(0→0.5→1→10)→ avg_kinship 单调非增(1.0→0.5157→0.3211→0.2685);[4] λ=0 退化=贪心 top-n(满额投最高 EBV 单亲);[5] A 缺失 → kinship_status=partial + warning[6] 三 409。清理干净。
  • Temp/claude/e2e_mabc_20260805.py 23 断言全过——[1] 前景 5 pass/1 fail[2] 恢复复算 100/75/75/0[3] reason 晋级 BC2/再回交/前景未通过;[4] recommended 恢复率降序 [100,100,100,75,0][5] 童期 C6 前景通过+晋级;[6] 轮回亲本缺背景基因型 → None + warning[7] 六 409。清理干净。
  • 回归e2e_molrigor / e2e_gwas / e2e_mating_kinship14/14/ e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_busflow / e2e_gaps_base / e2e_b8_seed_lot / e2e_prediction_rigor / e2e_audit_fix 全套零回归(_candidate_ebv_map 抽取 + mating 语义双核对)。vue-tsc EXIT=0。HTTP 核验:后端重启后 POST /bre/statistics/ocs(最小正例)+ POST /bre/statistics/mabc-progress(成功 + 空面板 409 + 非法 generation 409)经真实端点返回。环境性 b34(G1 门禁)为探针脆弱非本批回归。

18.13 近交衰退两处正确性修复:方向感知检测 + 深层系谱近交系数(2026-08-05 跟进)

用户实证复查 inbreeding_depression(v2.22,§18.10)两处缺陷,本会话核实成立后修复:① 方向盲目判据——无条件 slope<0 且 t≤−1.645 判衰退,对「越低越好」的 asc 性状(如病指)F↑→指标↑=恶化却误报「未检出」;② 浅层近交系数——系谱只取树级 dam/sire 把每个引用种质当 founder,未走深层系谱,多世代项目(半同胞共享祖亲)低估 F(OCS/mating 已用 _germplasm_pedigree 深层解析,故仅近交衰退受影响)。版本仍 v2.24(正确性修复不升版,避免批3 版本断言连锁)。

① 方向感知检测statistics/service.py inbreeding_depression):

  1. direction(此前读取未用)得 desirable_high = direction != "asc"
  2. 高优性状(desc/None)衰退 = slope<0 且 t≤−1.645;低优性状(asc)衰退 = slope>0 且 t≥+1.645
  3. interpretation 方向化——asc 衰退「F 每升 0.1,{trait} 表型平均上升(恶化) …%」/ 未达显著「斜率偏正…」/ 未检出「F 对表型无**上升(恶化)**影响」。对齐 data_quality_report 既有 desirable_high 方向语义。

② 深层系谱近交系数

  1. 系谱构建改复用 _germplasm_pedigreebre_pedigree 名称反查 + tree FK 兜底 + BFS 祖先展开,与 OCS/mating 同源)展开全部被引用种质祖先 + 树节点 + 未解析种质 founder 兜底(软删引用不悬空);_germplasm_pedigree 本体零改动。
  2. 多世代半同胞共享祖亲 → F 正确 >0(旧浅层把 G7/G8 当 founder → F=0 低估)。

验证

  • Temp/claude/e2e_inbreeding_depression_20260805.py 6 组断言全过——原 [1] 衰退 / [2] 无衰退 / [3] 样本不足保持,新增 [4] asc 病指12 树同 F 结构 y=10+40F → slope=+40、t 显著正、has_depression=true、文案含「上升(恶化)」、高近交前 6 仍 F=0.5 自交株;旧判据误报未检出)+ [5] 深层系谱 FP→G7/G8 tree FK 升谱、6 候选树 dam=G7 sire=G8 半同胞近交 + 6 对照 F=0y=10060F → max_F=0.125/mean_F=0.0625、slope≈−61、has_depression=true、高近交前 6 全为 H 半同胞株;旧浅层 F=0+ [x] trait 不存在 409 保持。清理干净(26 树 48 观测 + 4 性状全删)。
  • 回归e2e_ocs / e2e_mabc / e2e_mating_ebv / e2e_mating_kinship / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_trial_design / e2e_parent_validation / e2e_batch_selection / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules 全套零回归。vue-tsc EXIT=0(前端仅提示文案方向化一行)。HTTP 核验沿用批3(后端未重启)。

18.14 分子亲本验证(孟德尔一致性)+ 试验设计深度(增广 + α-格子)(2026-08-05v2.25

用户实证复查指出两处遗留缺口,本会话核实全部成立:① genotype_call 对 mendelian/parentage 零命中(仅有 fingerprint_check 无性系混杂/标签互换检测);② trial_design 仅 RCBD。α-格子范围用户拍板:平方格子(v=k²,闭式构造,平衡可证)+ 一般 v 贪心回退(balance_warning 诚实标注)_DATA_VERSION v2.25,同步 3 处探针版本断言(e2e_prediction_rigor / e2e_spatial_sparse / e2e_statsflow)。

批4-A 孟德尔/亲本一致性检验genotype_call/service.py mendelian_check(dataset_id, compat_threshold=0.98) + controller.py GET /bre/genotype_call/mendelian/check,镜像 fingerprint/check 模式,纯计算不落库):

  1. 数据解析(跨数据集):子代样本 = GenotypeSampleModel.source_type=="tree" 且 source_id∈dataset → tree 集合;声明亲本 = tree.dam_id/sire_id→germplasm(两亲皆空 → no_declared_parents + reason「未声明亲本」);亲本基因型 = source_type=="germplasm" 样本跨数据集解析(同数据集优先,否则其他数据集最低 id 兜底)——探针验证子代样本 D1、亲本样本 D2 跨数据集解析成功;亲本声明但无 germplasm 基因型 → missing_parent_genotype不 409,reason 标注「母本/父本」缺哪个)。
  2. 孟德尔规则:逐标记 _allele_set"/" 分割去空白/缺失)得子代/母本/父本等位集;子代等位集 ⊆ dam∪sire 并集即兼容(union 规则);任亲本空白/缺失 → 非信息位点不计分母。单株兼容率 = 兼容/信息位点,flag = rate < compat_threshold0.98 对齐 fingerprint)。
  3. 输出{dataset_id, compat_threshold, trees_checked, trees_flagged, trees_no_parents, trees_missing_parent_genotype, summary{informative_markers/incompatible_markers}, trees:[{tree_id, tree_no, dam, sire, status, informative_markers, compatible, incompatible, compatibility_rate, flag, incompatible_markers:[{marker_id, allele, dam, sire}], reason?}]};数据集无样本 → 零值返回 summary=None(不 409)。

批4-B 试验设计深度statistics/service.py trial_design 分派 rcbd/augmented/alpharcbd 路径逐字节不变schema.py TrialDesignIncheck_germplasm_ids: list[int]=[] / block_size: int|None / reps: int|Noneextra="ignore"):

  1. augmented(增广):对照 check_germplasm_ids 须为参试条目种质 id 子集(否则 409「对照种质不在参试条目中」)、至少 1 对照 + 1 新品系(否则 409「增广设计需至少 1 个对照种质」);对照每区组重复(anchors,check_reps=block_count)、新品系 rng.shuffle + round-robin 均分区组(不重复);对照条目 block_no 不落库None)、新品系落 1..block_count。输出加 checks:[{entry_number,germplasm_id}]/n_new_entries/n_checks/check_reps
  2. alpha(α-格子)block_size=kv%k==0 否则 409「α-格子条目数 {v} 须能被 block_size {k} 整除」;k 缺省 v 完全平方自动 k=√v,否则 409「α-格子需指定 block_size(当前 {v} 条目非完全平方)」);reps=r(缺省平方 k+1/一般 s;r<2 → 409「α-格子重复数需 ≥2」;平方 r>k+1 → 409「完全平方格子(v={v}=k²)重复数最多 {r_full}」)。平方 v=k² → 闭式格子rng.shuffle 打标 (x,y)rep m∈{0..k} 直线 y≡m·x+(b1) mod km=k=竖列),完全格子 r=k+1 任一对至多同块一次 λ≤1;k 素数(_is_prime)完全平衡 balance_warning=False,非素数 → balance_warning=True(保守告警,可分解不保证平衡)。非平方 v → 贪心可分解构造:逐 rep 贪心填 s 块×kused_pairs 集避免同块对重复,卡死则余下允许复用 + balance_warning=Truerng(seed) 确定性。block_no 复合编码 rep*100+blockrep 1..r、block 1..k)落库。
  3. 探针抓出的真 bug:平方分支初版 block_no 编码 m*100+b0-based m)致 rep1 落库 b1..3)与贪心分支/文档的 rep*100+block 不一致 → 修正 (m+1)*100+b401/402…)。探针 [2] 落库断言由 301/302 → 401/402 验证。

验证

  • Temp/claude/e2e_mendelian_check_20260805.py 8 断言全过——跨数据集解析(子代 D1/亲本 D2):T1 全 0/1 唯 M5=2/2(亲本均无该等位)→ informative=5/compatible=4/incompatible=1/rate=0.8/flag + incompatible_markers[0]={M5,2/2,dam=0/0,sire=1/1}T2 全兼容 rate=1.0/flag=falseT3 双亲空 → no_declared_parents + reasonT4 dam=G3 无基因型 → missing_parent_genotype + reason「母本」不 409summary informative=10/incompatible=1D3 空数据集零值 summary=None 不 409。清理干净(call→sample→marker→dataset→tree→germ→combo→target 全删)。
  • Temp/claude/e2e_trial_design_ext_20260805.py 19 断言全过——[1] augmented 12 条目 3 对照×3 区组:n_new=9/n_checks=3/check_reps=3、新品系 block_no∈{1,2,3} 不重复、对照 block_no=None、checks 结构;[2] v=9=k² k=3 素数 r=4 完全格子:4 rep×3 块×3 条、每 rep 覆盖 9、任一对至多同块一次(maxλ≤1 恰 36 对)、balance_warning=False、block_no 复合编码落库;[3] 部分 r=3 仍平衡;[4] v=16 k=4 非素数 r=5 + balance_warning=True[5] v=12 一般贪心 s=4/r 缺省=s + block_no 落库;[6] 四 409(对照非条目子集/增广无对照/v 不被 k 整除/非平方缺 block_size)。清理干净(entry→study→trial→germ→combo→target 全删)。
  • 回归rcbd 由 e2e_trial_design_20260805.py 回归零变化兜底;全量套件 e2e_molrigor / e2e_gwas / e2e_mating_kinship / e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_batch_selection / e2e_ocs / e2e_mabc / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules / e2e_prediction_rigor / e2e_inbreeding_depression / e2e_parent_validation 全套零回归。vue-tsc EXIT=0。HTTP 核验:后端重启(PID 更换)后 GET /bre/genotype_call/mendelian/check?dataset_id=999999 → 200 零值结构;POST /bre/statistics/trial-design augmented/alpha → 409「该研究点无参试条目」(分派+参数链路通)、design_type=latin → 409「暂不支持设计类型 latin(可用: rcbd=随机完全区组、augmented=增广、alpha=α-格子)」。
  • 方法学保留mendelian_check 与 fingerprint_check 互补(样本一致性 vs 子代-亲本孟德尔规则);augmented 对照 anchoring + alpha 平衡性显式告警与 RCBD 随机化并存;亲本基因型缺失/双亲空归状态不 409(数据现状透明化)。

18.15 批5 区组随机效应 ABLUP(N3)+ 孟德尔检验落库/隔离/进报告(N1)+ 统计引擎全量数值校验(N2)(2026-08-05v2.26

用户实证复查提出三项,本会话逐项核实全部成立,用户拍板范围:① N3(中-高,真实断点)——trial_design 已给增广/α-格子落库 block_no 不完全区组结构,但 run_ablup 只把 block_no 当空间竞争协变量网格 key,未作随机效应(service.py:651)→ 用户选「显式 block 开关」;② N1(中)——mendelian_check 只读不落库、不进数据质量报告、不自动隔离可疑树,错配亲本仍污染系谱 → 用户选「断开错误亲本链」;③ N2(中)——run_gblup/ssGBLUP、genetic_corr、type_b、run_cluster、stability 等大体量新模块只有结构性断言,缺逐文件数值真值校验 → 用户选「全量统计引擎」。_DATA_VERSION v2.25→v2.26(同步 3 处探针版本断言:e2e_prediction_rigor / e2e_spatial_sparse×2 / e2e_statsflow);blup.ENGINE_VERSION 1.4.0→1.5.0

批5-A(N3):ABLUP 区组随机效应

  1. 引擎 blup.pysolveblock: dict|None 分派 _solve_block(pedigree, phenotypes, *, fixed, covariate, block_of, record_map, tol)(镜像 _solve_gxeblup.py:1006-1205)——Z₂ 按 block_of: {记录id: 区组水平} 分组(G×E 的 (g,e) 复合键退化为单区块水平),剖面 REML 坐标上升估 (σ²a/σ²e, σ²block/σ²e)、MME、PEV 可靠性;输出键 sigma_block/block_ratio/block_effects/n_blocks、factor_label=「区组」;区组方差收敛到 0 / 无系谱 / 未收敛三警告。ENGINE_VERSION → 1.5.0。
  2. 服务 run_ablup:新参 block: bool=False。互斥并入 L491-494blockgxe/gxr(共用 Z₂ 槽)409、blockspatial(残差结构与第二随机效应槽)409。新分支:读 select(TreeModel.id, TreeModel.block_no)block_of={f"t{tid}": int(blk)};无 block_no 的树降级剔除表型保留系谱(镜像 spatial 缺坐标降级,note 记剔除数);len(set(block_of))<2 → 409「区组数据不足:需 ≥2 个区组(请先运行 /statistics/trial-design 生成设计并落库 block_no)」;method="ABLUP-BLOCK"、model_name 前缀 ABLUP_BLOCK_、note_payload 含 sigma_block/block_ratio/n_blocks/warningaccuracy 按 block 树均值可靠性。
  3. Schema/控制器/前端RunAblupInblock: bool=Falsecontroller /ablup/run 透传;前端 statistics「多环境 GxE」tab 加 blockEnabled 复选框 + 互斥 watchblock↔gxe/gxr/spatial+ payload.block + 成功文案/说明三元。
  4. 探针 Temp/claude/e2e_ablup_block_20260805.py 3 批次落库全过——[1] 3 区组×5 株已知 σ²block>0 → method/n_blocks/σ²block/block_ratio + EBV 独立矩阵解一致;[2] 单区组 409[3] 无 block_no 409[4] block+gxe/block+spatial 409 互斥;[5] 部分缺 block_no 降级剔除 + note 含剔除数;[6] 全收敛数据无区组归零警告。

批5-B(N1):孟德尔检验落库 + 自动隔离 + 进数据质量报告

  1. 新表create_all 自动建):MendelianCheckModelbre_mendelian_checkdataset_id/compat_threshold/计数/summary_json/data_version/input_hash/engine_version/note+ 子表 MendelianCheckTreeModelbre_mendelian_check_treeFK check_id CASCADEtree_id/dam_id/sire_id/status/信息位点/兼容/不兼容/rate/flag/reason/incompatible_markers_json);TreePedigreeExclusionModelbre_pedigree_exclusiontree_id 唯一、reason/source_type="mendelian"/source_check_id/created_id)。
  2. 服务mendelian_check 纯计算核心抽共享 _compute_mendelian(dataset_id, compat_threshold)(GET 预览与 POST 逐字节同源);新 run_mendelian_check 计算→落库主表+每树子行→自动隔离flag=true 树 upsert bre_pedigree_exclusion,本次未 flag 但此前隔离(同 dataset 范围)删除隔离行(注册表=最新检验结论、可逆)。
  3. 控制器:新 POST /bre/genotype_call/mendelian/check/runAuth module_bre:genotype_call:edit,写操作),GET 只读预览保留。
  4. 进数据质量报告data_quality_report 加可选 dataset_id,提供时追加 mendelian 段(最新 bre_mendelian_check 计数 + flagged 树列表 + 当前隔离状态);flagged>0 → summary.has_warning=True;无检验记录 → mendelian: NoneDataQualityIndataset_id 透传。
  5. 系谱消费方断开亲本链(共享 _excluded_tree_ids() 读注册表,树级 dam/sire 置 None + note):_build_pedigreegenetic_corr/index/type_b/gblup/ssgblup/gwas)、run_ablup 内联系谱循环、inbreeding_depressionkinship_matrixrun_cv_germplasm_pedigree(树→种质亲本链)。GBLUP/ssGBLUP 基因型样本不过滤(错配是亲本声明非基因型)。
  6. 前端genotype_call 孟德尔对话框主按钮改 POST mendelianCheckRun(展示 check_id + 隔离树数 + 新类型);statistics「数据质量」tab 加 dataset 选择器 + mendelian 段(flag 计数 alert + 隔离树表)。
  7. 探针 Temp/claude/e2e_mendelian_persist_20260805.py ok=19 fail=0——[1] 落库(主表行/计数/子表行/check_id);[2] 隔离生效 + EBV 断开(隔离树与声明亲本亲缘=0);[3] 再跑未 flag → 隔离行清除(可逆);[4] data_quality_report(dataset_id) mendelian 段 + has_warning=True、无检验 None[5] run_ablup note 含隔离剔除数、genetic_corr 亲缘=0[6] GET 只读预览 8 断言零回归。

批5-C(N2):统计引擎全量数值真值校验Temp/claude/e2e_stats_numerics_20260805.pyok=101 fail=0):

  • 14 个引擎段 + 4 服务端点段全过blup.solve 普通(独立 V⁻¹ BLUP≡MME + 网格 REML 表面一致)、_solve_gxeMME 恒等 + 方差分解)、_solve_blockMME 恒等 + 区组效应恢复)、solve_spatial(_aniso)R 重构 + MME 恒等 + ρ_row/ρ_col 恢复)、build_g_matrix(手算 VanRaden method2)、solve_gblupMME 恒等 + 可靠性公式)、_build_h(教科书 H⁻¹ 含 Christensen 缩放 + 岭)、ssGBLUP MME 恒等 + 非基因型株 EBV≠0、solve_bivariate(完全正相关 r_g→1 / 独立 r_g≈0)、solve_multi(已知 G0 恢复 + PSD)、finlay_wilkinson(独立 OLS)、ammi(解析 2×2 SVD)、solve_rcbd(手算 SS/MS/F)、_solve_diallel(手算 GCA/SCA)、_proj_simplex/_solve_ocs/_selection_intensity、服务端 run_clusterUPGMA 首次合并=最小距离对)、genetic_gain(ΔG=k·r_g·σ_A 复算)、data_quality_reportIQR/MAD 手算边界)、kinship_matrix3 节点 A 手算)。
  • 探针自身两处 fixture 缺陷修复(引擎本体零缺陷):① A8.4 独立性状 r_g 假收敛 -0.99 / A9 G0 恢复不可靠——根因是 4 创始人+10 子代低 h²(h²≈0.43)小样本 REML 面平坦/近边界(单性状 ve 塌缩、EM 起点被毒化),换高遗传力(va=[4,3,2.5]、ve=[0.5,0.4,0.35]h²≈0.87-0.9+ 高真相关(0.95/0.90/0.85+ 10 全同胞家系×3 株(n=54,24 创始人)良态设计 → r_g 恢复误差 ≤0.0611.1s 收敛);② B4.2 硬编码 tree_id==4fixture 树真实自增 id 5664 非 4)→ 改 trees[3](值 9.0 精英株)。逐项核实 EM-REML/M-step/固定点/MME/剖面均教科书正确,非引擎 bug 不误报。
  • runtime 约束记录solve_multi 3 性状 n≥100 时每次迭代 MME solve+inv 0.7sn=100)超 2 分钟,数值探针 fixture 保持 n≤54。

验证

  • 三新探针(e2e_ablup_block / e2e_mendelian_persist / e2e_stats_numerics)全过;27 套件全量回归零回归(含 e2e_mendelian_check / e2e_trial_design / e2e_trial_design_ext / e2e_gxe / e2e_gxr / e2e_molrigor / e2e_gwas / e2e_mating_kinship / e2e_mating_ebv / e2e_gblup_cv / e2e_statsflow / e2e_spatial_sparse / e2e_gs_family_cv / e2e_batch_selection / e2e_ocs / e2e_mabc / e2e_gaps_base / e2e_gaps_engines / e2e_gaps_modules / e2e_prediction_rigor / e2e_inbreeding_depression / e2e_parent_validation / e2e_advanced_gblup / e2e_corr_spatial)。
  • vue-tsc EXIT=0(前端 statistics/statistics.ts/genotype_call/index.vue 类型检查通过)。
  • HTTP 核验(后端重启):POST /bre/genotype_call/mendelian/check/runPOST /bre/statistics/data-qualitydataset_idmendelian 段、POST /bre/statistics/ablup/runblock=True / block+gxe 409)、POST /bre/statistics/ocs
  • 备份镜像 Temp/claude/backup_block_mendelian_numerics_20260805/(18 文件按相对路径,收尾补 2 文件 → 20:更新版 e2e_gaps_engines_20260804.py + http_v226.py)。
  • 方法学保留block 与 gxe/gxr 共用 Z₂ 槽故互斥(同一数据既跨环境又跨区组时用户二选一);孟德尔隔离可逆(数据修正/阈值提高再 run 自动解除);N2 探针与既有结构性探针互补(真值段独立 numpy 实现对照,fixture 良态设计避开小样本 REML 退化区)。

批5 跟进(2026-08-05,收尾)

  • 回归首轮抓 1 处探针陈旧断言(非引擎回归)e2e_gaps_engines_20260804.py:141 断言 blup.ENGINE_VERSION == "1.4.0",批5 已升 1.5.0 → 改断言 1.5.0 复跑通过(与批5 三处 _DATA_VERSION 同步同类机械性版本断言更新)。27 套件全量回归最终全部 exit=0
  • HTTP 核验完成Temp/claude/http_v226.py,后端重启后真实端点,ok=14 fail=0):POST /bre/genotype_call/mendelian/check/run 200check_id + isolated=1);GET /bre/genotype_call/mendelian/check 只读预览零回归;POST /bre/statistics/data-qualitytrait+dataset_idmendelian 段 flagged=1 + summary.has_warning=TruePOST /bre/statistics/ablup/runblock=True200 → prediction method=ABLUP-BLOCK、model_name 前缀 ABLUP_BLOCK_、note 含 sigma_block/n_blocks=2block+gxe / block+spatial 均 409Z₂/残差互斥文案);POST /bre/statistics/ocs 200contributions 4 条和=2)。fixture 运行后自动清理(bre_mendelian_check/tree/pedigree_exclusion 0 残留)。
  • 核验前需换新 tokendpb_token.txt 旧 token 过期(401「认证已失效」)→ 经 POST /system/auth/loginsuper/123456)刷新(登录在 /system 前缀,不在 /bre)。

18.16 批6 规划↔目标↔试验 可追溯性闭环:plan/target/trial 三 FK + trace 端点 + 双删除守卫(2026-08-05v2.27

用户全代码库 grep 实证可追溯性缺口成立:bre_plan彻底孤立的根表(零传入外键,bre_trialplan_id/target_id,无 project/program 表)。用户拍板「加试验挂目标」最小双链:bre_target.plan_id + bre_trial.plan_id(双链),另加 bre_trial.target_id(试验挂目标)。_DATA_VERSION v2.26→v2.27statistics/service.py:97 + genotype_call/service.py:45;5 处探针版本断言同步:e2e_prediction_rigor:102 / e2e_spatial_sparse:175+229 / e2e_statsflow:174 / e2e_mendelian_persist:207)。

  1. DB:新 backend/sql/weld_plan_trace.sql(幂等 ALTER 三列 + FK,已应用验证):bre_target.plan_id FK→bre_planbre_trial.plan_id FK→bre_planbre_trial.target_id FK→bre_target,均可空(历史孤目标/独立试验不受影响,可追溯性渐进式)。
  2. target 三件套TargetModel.plan_id + relationshipschema plan_id 透传;get_list outerjoin 解析 plan_namecreate 父校验(plan_id 不存在 → 409None 跳过);delete assert_no_children(有 combo 子 → 409)。
  3. trial 三件套TrialModel.plan_id/target_id + 双 relationshipschema 双字段透传;get_list 解析 plan_name+target_name;create 双父校验(不存在 → 409None 跳过);delete assert_no_children(有 trial_study 子 → 409)。
  4. plan trace 端点:新 trace(plan_id) 服务方法 + GET /bre/plan/trace/{id}——{plan, targets:[{…,n_combinations,n_trees,combinations:[{…,trees}]}], trials:[{…,target_name,n_trial_studies,n_trees,trial_studies:[{…,trees}]}], totals};组合/试验点软删过滤;孤目标不入链;不存在计划 409;plan.delete assert_no_children(有 target/trial 子 → 409)。
  5. 前端target/trial 表单「所属计划/目标」select(res.data.data ?? [])+ 表格/详情列;plan 页「追溯」行操作弹窗(ElCollapse 目标链/试验链 + ElTags)。
  6. 探针 Temp/claude/e2e_plan_trace_20260805.py 17 断言全过(目标链/试验链/totals/软删过滤/孤目标不入链/三父校验 409/双删除守卫 409/标签解析),自清理(含 bre_target 审计行)。
  7. 审计探针根治(本批排查修复)e2e_audit_20260805.py 残留检查原 entity_id.in_(CREATED_TARGET_IDS) 未限定 entity_type,而 entity_id 按实体表各自序列非全局唯一breeding_target_id_seq 推进到 691 后,target id 与既有 bre_cross_combination(669/685)/bre_germplasm(675) 审计行撞 id → 间歇误报「仍有残留 id=…」)→ 残留检查限定 entity_type=='bre_target'(与 clean() 删除范围一致),连续 5 轮 13/13 稳定。

验证:新探针 17/17 + 全量回归零回归(60 套件,含批5 三探针零变化)+ vue-tsc EXIT=0。HTTP 核验(后端重启,Temp/claude/http_v227.py):GET /bre/plan/trace/{id}、target/trial create 带 plan_id/target_id、三父校验 409、双删除守卫 409。备份镜像 Temp/claude/backup_plan_trace_20260805/(按相对路径)。

18.17 批7 统计引擎全量十模块 golden 复查·系谱键空间错位修复(2026-08-05v2.28

用户质疑「GBLUP/ssGBLUP、genetic_corr、type_b、cluster、stability、OCS、MABC、inbreeding_depression、trial_design、mendelian 这批新建模块还没逐一数值校验(golden-test 缺失)。历史上 G–L 的静默失效都是靠校验才暴露的」。拍板「全量十项逐一复查」。复查确认 8/10 已 goldenGBLUP/ssGBLUP、cluster、stability、OCS、MABC、inbreeding_depression、trial_design、mendelian 既有探针已具严格数值断言),type_b 与 genetic_corr 补齐 golden 缺口——审计深处抓到真 bug 就地修 + 探针加回归_DATA_VERSION v2.27→v2.28statistics/service.py:97 + genotype_call/service.py:45 同步;4 处探针版本断言同步:e2e_spatial_sparse:175+229 / e2e_statsflow:174 / e2e_prediction_rigor:102 / e2e_mendelian_persist:207)。

根因(THE BUG:服务层把 int tree_id 表型键 传给 mtblup.solve_bivariate,而 _build_pedigree 系谱用 str "t{tree_id}"blup.solve 的鲁棒逻辑(L382-385)把系谱外个体自动并入 base(视作无关 founder)→ 系谱被静默丢弃。平衡数据(同株跨环境提供协方差)掩盖;分裂家系数据(无同株跨环境、全同胞链跨站点桥接)暴露——int 键 → r_B/r_g 锁死 ±0.99(平剖面端点假收敛、假阴性负相关)。run_ablup 正确(L1020 phenos_keyed={f"t{tid}": v}),四个 mtblup 消费路径受影响。

修复:新增共享 helper _tree_individual_keys(d)service.py:163{tree_id:值}→{"t{tree_id}":值})收口四个调用点——_genetic_corr_matrixL2214/ _smith_hazel_index mtblup 分支(L2754/ run_genetic_corrL5122,喂 solve_multisolve_bivariate,类型注解同步改 dict[str, dict[str, float]]/ run_type_b_heredityL5294)。

探针 Temp/claude/e2e_rg_golden_20260805.py ok=21 fail=0——20 founder10 母×10 父)、10 全同胞家系×3 同胞=30 株、3 站点、高遗传力良态设计(VA=4.0/VE=0.5h²≈0.89,与批5-N2 良态设计经验一致);tY 分裂家系(站1=同胞0,1/站2=同胞2/站3=全株,真 r_B=0.8+ tA/tB/tC 平衡(真 r_g AB=0.95、AC=BC=0+ tS1/tS2 分裂家系(真 r_g=0.8):

  • [P0 诊断] solve_bivariate 直接调用:str 键恢复 r_B=0.7+、int 键锁死 0.99RED 实证);
  • [P1 type_b golden] 服务端点 r_B(1,2)>0.5 + n_common=0(三站无共有树、靠全同胞系谱桥接——系谱生效的直接证据)+ 全正 min>0.3
  • [P2 correlation golden] r_g(A,B)>0.65、|r_g(AC/BC)|<0.4、判别间隙>0.3、h²∈(0,1)
  • [P2b discriminator] r_g(S1,S2)>0.5(分裂家系无共有树,RED 下锁死 −0.99)。

探针自身缺陷修复:_simulate 初版 int 键 vs 观测循环 str 键 KeyError(统一 str 键)、种子扫描键错位(E0/E1/E2 vs E1/E2/E3 查键致 p2 空)、P2 间隙阈值过紧(r_g(B,C)=0.374 高抽样波动,阈值 0.4→0.3 重校准)、死 _build_ainv 占位行删除、exit-code 通道 bugreturn ok==0 and fail==0 恒假,改 fail==0,断言 21/21 本就全过)。

验证:新探针 21/21 + e2e_statsflowB1/B2,单家系 fixture 对键 bug 不敏感,15 断言零变化)+ e2e_advanced_mtblupr_g=0.99/n_common=4/smith-hazel mtblup)回归通过 + 全量回归零回归batches 13 + final60 套件,含版本断言同步)+ vue-tsc EXIT=0。HTTP 核验(后端重启,Temp/claude/http_v228.py):POST /statistics/type-b-heredity(分裂家系 r_B(1,2)>0.5 + n_common=0 + data_version=v2.28)、POST /statistics/genetic-corr/runtS1,tS2 分裂家系 r_g>0.5 + 平衡 tA,tB r_g>0.65)。备份镜像 Temp/claude/backup_keyspace_20260805/(按相对路径)。方法学保留:四个 mtblup 消费路径统一 str 键对齐系谱;探针 fixture 高遗传力 + 分裂家系结构保证判别力;run_ablup 正确路径不受影响。

18.18 回归基建:run_regression.py 统一回归 + 高风险模块正式 tc 套件(ssGBLUP/OCS/MABC/孟德尔)(2026-08-05,测试基建,不 bump 版本)

用户对批7 提出三点质疑,逐项核实全部成立,拍板「两者都要」——先建统一回归脚本把所有探针纳入(立即止血),再抽正式 tc 套件。纯测试基建,无后端代码改动_DATA_VERSION 保持 v2.28

  1. 全库 test_bre_*_tc.py(08-03)只覆盖「数据建链/导入导出/多波次」,对 GBLUP/ssGBLUP、OCS、MABC、近交衰退、试验设计、孟德尔检验这些新建分析模块零命中full_tc 的 correlation 只是 GET 200 冒烟);
  2. 19:55 改动(批7)未补 golden 测试——批7 探针建在 Temp/claude 一次性目录、无统一回归脚本;
  3. 风险:新模块若算偏(ssGBLUP 的 H⁻¹ 拼接、OCS 投影梯度收敛)会当「正常结果」输出——正是当年 G/I 静默失效的同款隐患(int-key bug 即活证据)。

统一回归脚本 run_regression.py(仓库根):glob Temp/claude/e2e_*.py(排除 e2e_probe* 探查工具)+ backend/scripts/test_bre_analysis_*_tc.py = 63 测试顺序串跑不并发(历史 RC=124 机器争用超时前科);每测试独立子进程(cwd=os.path.dirname(p)、timeout=1800s)完整输出写 Temp/claude/regression_logs/<name>.log,控制台回显尾部 + EXITEXIT 汇总任一失败整体 exit≠0(供交付流程判断);DPB_PYTHON 环境变量覆盖解释器(须 dpb env python,基础 miniconda 缺 PEP 695 generics SyntaxError);sys.stdout.reconfigure(encoding="utf-8") 防 GBK 崩溃;过滤器 python run_regression.py gwas ocs--keep-logs 保留日志。验证:全量 58/59 通过,唯一失败 gaps_engines 批量卡死(10 分钟无输出)单跑 RC=0 确认通过——机器争用非探针问题。

4 个正式 tc 套件backend/scripts/TestClient 走真实 API + lifespanURL 带 /api/v1/bre/... 前缀,登录 super/123456 form)——高风险模块必测,fixture 自带清理:

  • test_bre_analysis_ssgblup_tc.py ok=14 fail=0GBLUP vs ssGBLUP 同 fixture5 株表型 + 基因型数据集:树0/1/3 直连、树2 名称兜底、树4 全多等位无有效剂量)。H⁻¹ 拼接判别核心——非基因型株(树4GBLUP EBV=0 / ssGBLUP EBV≠0(若 H⁻¹=A⁻¹+[0;G⁻¹−A22⁻¹] 拼接错,非基因型亲属 EBV 为 0 或爆炸);h²∈(0,1)、5 条 EBV、全部有限。
  • test_bre_analysis_ocs_tc.py ok=23 fail=08 种质(F1/F2/F3/D/E + A/B 全同胞 + C 半同胞)EBV 全 direct。Σc=3/c≥0/coverage direct 5/最高贡献 A≈1.419、vs_top_n mean_ebv 9.7667/avg_kinship 0.5556/c'Ac≈4.641、λ↑→avg_kinship 单调非增 [1.0,0.5157,0.3211,0.2685]、λ=0 满额投 A、kinship_status=partial+告警 D/E、n_select>候选/空候选→409、λ<0→422schema 层 Pydantic ge=0 拦截)。
  • test_bre_analysis_mabc_tc.py ok=24 fail=0:轮回亲本 + 6 候选(C6 童期)、前景 F1/F2 + 背景 M1-M4。前景命中/背景恢复率 100/75/0 复算、回交建议(晋级 BC2/再回交/维持)降序、童期 C6 晋级、轮回亲本无基因型 warning、target 越界→422le=100 schema 校验)、其余 409。
  • test_bre_analysis_mendelian_tc.py ok=9 fail=0P1/P2 全 0/1→T1、P3/P4 全 0/0→T25 标记)。POST /bre/genotype_call/mendelian/check/run下划线 genotype_call,非连字符)落库 + T2 flag 进隔离注册表 bre_pedigree_exclusionsource=mendelian/source_check_id+ 阈值 0.0 重跑可逆(隔离行清除)+ GET 只读预览零回归;data_version=v2.28 落库。

tc 套件关键教训(写进探针防再犯):

  • HTTP 语义差异schema 层 Pydantic 校验(ge/le 约束)拦截 → 422;服务层 CustomException → 409e2e 直调只见 409tc 走 HTTP 见 422)——断言错误码须按路径定;
  • Mapper 注册PlantingModel 等 relationship 引用 UserModeltc 套件必须显式 from app.api.v1.module_system.user.model import UserModel 注册,否则 SQLAlchemy InvalidRequestError: expression 'UserModel' failed to locate a name
  • 时序验证:孟德尔 tc 的隔离注册表断言必须在 run1 落库后、run2(阈值 0.0 清除)之前验证,否则必然 n=0 假失败;
  • 启动残留预清理_wipe() 按前缀清残留(防上次进程被杀/建 fixture 中途失败留下 uq_bre_trait_code 等唯一键脏数据),套件可重复跑。

验证4 个 tc 套件 EXIT=014/23/24/9+ 全量回归 58/59gaps_engines 单跑确认)。备份镜像 Temp/claude/backup_test_rigor_20260805/root/run_regression.py + backend/scripts 4 tc 套件)。交付流程:凡改动统计引擎/业务链后端代码,跑 python run_regression.py(dpb env 解释器)全量回归 EXIT=0 后方可交付;新 tc 套件命名 test_bre_analysis_<模块>_tc.py 由驱动自动纳入。

18.19 回归基建 2:分析模块 tc 补齐(5 套)+ pytest 接入 + 本机 CI stage2026-08-05,测试基建,不 bump 版本)

用户对 §18.18 的 4 套 tc 认可后,继续补齐 5 个静默失效风险较低但属相关性/回归/生成器类的分析模块(genetic_corr / type_b_heredity / inbreeding_depression / trial_design / run_stability),并把 v8 验收标准定为「CI 跑通 pytest 全绿」。两条硬约束:① 基于真实 PostgreSQL 16 + Redis(工程无 SQLitetc 全部在真实 PG+Redis 实跑);② 不做 GitHub Actions / 不登录 GitHub(全工程无 git 仓库,GitHub Actions 云端本机用不上)——CI stage 落地为本机驱动脚本 run_ci.py。纯测试基建,无后端代码改动,_DATA_VERSION 保持 v2.28。

补齐 5 套 tcbackend/scripts/TestClient 真实 API + -X utf8 + _wipe() 残留预清理 + 自带清理):

  • test_bre_analysis_genetic_corr_tc.py ok=19:平衡 3 性状(VA=4/VE=0.5,真 r_g AB=0.95/AC=BC=0h²≈0.89)——matrix_json 对角 1/对称/r_g(AB)>0.65/|r_g(AC,BC)|<0.4/判别间隙>0.3/h²∈(0,1)分裂家系判别 tS1(测同胞 0/1+tS2(测同胞 2):r_g(S1,S2)>0.5 且 n_common=0(无共有树,全同胞系谱桥接生效;rng 消耗序敏感性——S1/S2 用独立种子 SEED_S=3(扫描 0-39 验证 r≈0.99)解耦自探针 tY-first 顺序);409×3。
  • test_bre_analysis_type_b_tc.py ok=18:3 站点分裂家系(站1=同胞0/1×20 株/站2=同胞2×10/站3=全株×30):3 环境 envs_json 20/10/30、r_B(1,2)/r_B(1,3)/r_B(2,3)>0.5、min>0.3、n_common=0复刻探针 tY-first rng 消耗序 → r=0.990409×3(坏 trait/env_dim/method)。
  • test_bre_analysis_inbreeding_tc.py ok=4412 树(6×F=0 + 6 自交 dam==sire F=0.5),y=10060F+ε → slope<40/t<3/r²>0.9/has_depression=true/高 F 前 6 自交株;无衰退 slope≈0 未检出;方向感知 asc 病指 y=10+40F slope>30(上升=指数型);deep 系谱 GP→G7/G8→H 树 F=0.125mean_F≈0.0625);min_n=20 insufficient"12 棵"/"≥20")不 409409+422。
  • test_bre_analysis_trial_design_tc.py ok=25:增广 12 条目(9 新品系+3 对照)——新品系 3 区组×3 条不重复、对照 block_no=None 不落库check_reps=3);α-格子平方 v=9 k=3 r=4(λ≤1、每 rep 可分解、warn=False/ 部分 r=3 仍平衡 / v=16 k=4 非素数 warn=True / 一般 v=12 贪心(r 缺省=s=4);block_no=rep*100+block 复合编码 DB 读回TestClient 退出后单一 asyncio.run 防嵌套 loop);409×4教训:α-格子 r=4 会 case() 整表覆写 block_no——部分 r=3 重跑须在 r=4 之前,否则 DB 读回是部分态。
  • test_bre_analysis_stability_tc.py ok=163 组合×3 站点 cell means C0=[0,6,12]/C1=[2,5,8]/C2=[4,4,4] → FW b≈2.0/1.0/0.0、flag_stable C1=True 其余 False|b1|≤2se)、r²≈1(常量响应基因型 r²=None 合法);AMMI n=9、rank 按 ASV 升序、IPC1 占比 1.0≥IPC2、ss_interaction=36>0engine_version 落库断言;year 维度 + 409×2(坏 methods/gxe_env)。

pytest 包装层 backend/tests/test_stat_analysis_tc.py9 套 tc 各一个 pytest 测试(@pytest.mark.pg + parametrize),subprocess 顺序串跑真实脚本(镜像 run_regression 契约:DPB_PYTHON 覆盖、-X utf8、timeout=1800)。环境控制关键——包装层不 import 任何 app 模块(防 conftest sqlite 污染);subprocess env 显式构建:剥掉 conftest 注入的 DATABASE_TYPE/DATABASE_NAME/POOL_SIZE/MAX_OVERFLOW/CAPTCHA_ENABLE,置 ENVIRONMENT=dev/DATABASE_TYPE=postgres/PYTHONPATH=backend/PYTHONUTF8=1,再并入从 backend/env/.env.dev 解析的真实连接值(TC_CI_* 可覆盖验证 skipif 路径)。skipif 探测asyncpg 连 PG + redis.asyncio pingprotocol=2 必须显式——redis-py 7.x 默认 RESP3,本机 WSL redis-server 版本较老 helloResponseError,与 app.core.database.redis_connectRedis.from_url(...protocol=2))对齐即通;任一失败 pytest.skippyproject.toml 注册 pg marker(消 PytestUnknownMarkWarning);conftest.pycollect_ignore_glob=["../scripts/test_*.py"] 防收集 import 独立脚本污染 sqlite 环境。

本机 CI stage run_ci.py(仓库根):step 0 探测真实 PG16+Redisasyncpg + redis.asyncio protocol=2,失败给明确指引并 exit≠0);step 1 pytest -m pgdpb python + -X utf8cwd=backend)跑 9 套;step 2 汇总 EXIT=0 →「 CI 全绿」;日志写 Temp/claude/ci_logs/。与 run_regression 并存(run_regression=手动全量回归 / run_ci=验收门)。

验证5 套逐个 EXIT=019+18+44+25+16=122 断言);pytest -m pg 9 passed(真实 PG+Redis146s,含既有 4 套零回归);skipif 路径(TC_CI_DB_PORT=1 指错端口)9 skipped 不红、无 unknown-marker 警告、scripts 未被收集(88 collected/79 deselected/9 pg);run_ci.py EXIT=0「CI 全绿」run_regression.py test_bre_analysis glob 自动纳入 9 套。备份镜像 Temp/claude/backup_analysis_tc2_20260805/交付流程v8 验收 = python run_ci.py EXIT=0(或 cd backend && pytest -m pg 全绿);改动统计引擎/业务链后端仍跑 python run_regression.py 全量。

18.20 O2–O4 统计方法学广度:幼年–成年遗传相关 + 非线性基因组预测 + 约束选择指数(2026-08-05v2.29

用户系统核对统计引擎能力后确认三项 P2 方法学缺口(均零命中、不影响当前业务正确性,属统计方法库广度),拍板「O2–O4 先落地」+ 两项决策:① O4 用经典 KempthorneNordskog =0 闭式解(纯 numpy 不迭代);② 前后端同步扩展。方法学扩展 → _DATA_VERSION v2.28 → v2.29genomic.ENGINE_VERSION 1.3.0 → 1.4.0无新表O2 复用 bre_type_b_result(env_dim 自由字段)、O3 复用 bre_prediction/bre_prediction_value(method 标签扩展)、O4 复用 bre_selection_indexresult_json 已含 extra)。

O2 幼年–成年遗传相关(env_dim="stage"_values_by_tree_envservice.py:324)加 stage 分支——coalesce(obs.stage, TraitModel.stage) 分组(观测缺省继承 bre_trait.stage)、group_by 含 coalesce 表达式、同树同阶段多次观测取均值;run_type_b_heredity env_dim 校验扩 ("site","year","stage")。发育阶段当"环境"→ 逐对 mtblup.solve_bivariate REML 精确估幼-成遗传相关 r_g(>0.5 表示童期可借力成株、早期间接选择有效)。前端 Type-B 页签 env_dim 下拉加「stage=发育阶段(幼/成)」。

O3 非线性基因组预测(genomic 1.4.0

  • solve_rrblupservice 5774 分派):岭回归逐标记 y=μ+Xu+eu=(Xc'Xc+λI)⁻¹Xc'yc,λ 由剖面 REML σa²/σe² 定(σu²=σa²/c、c=2Σp(1-p)),EBV=Xc·u+μ —— 与 GBLUP 数学对偶G=XcXc'/c 时闭式解 ĝ=G(G+λa·I)⁻¹yc+μ 逐位吻合,探针 1.42e-13);输出 marker effectsGBLUP 无的解释能力)+ PEV 可靠性近似。
  • solve_bayesbBayesB Gibbs 可变选择——δ_jBernoulli(1−π)+方差尺度混合、σ²jinv-χ²(df_s+1,(df_s·scale0+u_j²)/(df_s+1))、σe²~inv-χ²(df_e+m,...)numpy.random.default_rng(seed) 确定性MLOps 铁律:同 seed 两次 EBV 逐位一致);π 默认 0.95、稀疏 QTL 场景取 0.7 更贴合 30% QTL 真值。
  • kfold_cv_genomic 加 dosage/markers 分派:rrblup/bayesb 折内走对应求解器(实证 CV);run_cv GS 分支透传 seed + genotypes + markersmethod_name=KFCV/RRBLUP·KFCV/BayesB。
  • run_gblup method 扩 ("gblup","ssgblup","rrblup","bayesb") + seed 透传,rrblup/bayesb 从 _gather_gblup_inputs dosage 构 X → asyncio.to_thread 引擎,落 PredictionModel(method=RRBLUP/BayesB) + PredictionValueModelEBV/rel/pa/rank)、engine_version=1.4.0。前端 GBLUP/CV 页签 method radio 加 RRBLUP/BayesB + seed 输入。

O4 约束选择指数(restricted 闭式解 + economic weights

  • _smith_hazel_indexrestricted_traits/economic_weights。受限时 Kempthorne-Nordskog Lagrange 闭式投影:C(第 j 行=第 j 个受限性状单位向量)、M = C'(C·G·P⁻¹·G·C')⁻¹·C·G·P⁻¹·G、b = P⁻¹·G·(IM)·a → 约束 C·G·b=0 ⇔ 受限性状 ΔG=0(纯 numpy pinv,不迭代)。对照旧公式 M=C'(C·P⁻¹·C')⁻¹·C·P⁻¹ 实测 ΔG=4.46 不满足 → 修正必要e2e O4-1c 断言锁定)。
  • economic_weights 直接作 a(绝对尺度、不归一化统计权重、未列性状按 0 不进聚合基因型),可与 restricted 叠加;direction=asc 仍翻转 a[i](b=P⁻¹Ga 线性于 a → 保证该性状 b 相对下降,(P⁻¹G)₀₀>0 保号,非必 sign flip——tc 断言用严格下降)。
  • extra 落 restricted/constraint_mode=ΔG=0/economic + warningsmethod 校验扩 ("zsum","smith_hazel","restricted")、缺 restricted_traits 409、restricted_traits ⊆ cols(越界 409)、economic_weights 性状 ⊆ tmap。落库 method=SI_RES。前端指数页 method radio 加 restricted + restricted_traits 多选 + 每性状经济权重输入。

顺手修复(tc 暴露的既有缺口)cv_detail 折明细 dict 缺 cv_result_id(CvFoldOut 必填字段)→ 任意 GET /cv/{id} 400(既有 tc 均未触达该端点,静默失效风险同款);补 "cv_result_id": cv_id 后 rrblup/bayesb CV 详情可查。

验证e2e_o234_20260805.py 探针 19 断言(O3 对偶逐位 1.42e-13 + marker effects + BayesB 可复现 + kfold 5 折;O4 受限 ΔG=0 机器精度 + 旧公式失败 + economic asc 翻转;O2 真实 PG 16 树 r_g=0.6145);正式 tc test_bre_analysis_o234_tc.py ok=41 fail=0TestClient 真实 API + goldenO2 env_dim=stage r_g=0.8995/n_common=12/双阶段 12 株/data_version=v2.29O3 落库 method+engine_version 1.4.0/bayesb 同 seed 两次逐位一致/rrblup·GBLUP EBV 相关 1.000/CV 折数=5/非法 method 409O4 restricted b_受限=0.0/economic desc>0·asc<0/缺 restricted_traits 409+ TC_SCRIPTS 注册第 10 套 + 全量回归零回归61 e2e + 10 tc+ run_ci.py EXIT=0「CI 全绿」。备份镜像 Temp/claude/backup_o234_20260805/

十、文件清单与备份

新增/修改文件(2026-08-03

文件 说明
backend/app/api/v1/module_bre/statistics/service.py G×E 引擎 + 异步任务 + 门禁(含 blup.solve 传参)
backend/app/api/v1/module_bre/statistics/model.py StatisticsJobModeljob_type/status/error_msg/result_ref
Temp/claude/e2e_gxe_20260803.py G×E e2e 探针(5 场景)

新增/修改文件(2026-08-04

文件 说明
backend/sql/weld_trait_direction.sql 幂等 ALTER 三列
backend/sql/bre_trait_seed.sql 种子数据含三新列(43 行)
backend/app/api/v1/module_bre/trait/model.py / schema.py / service.py 三字段透传 + 批量导入导出兼容
backend/app/api/v1/module_bre/statistics/service.py 方向翻转 + into_ebv 剔除 + default_h2 兜底 + 排行/对比方向修复
backend/app/api/v1/module_bre/statistics/controller.py selection_only query 参数
frontend/web/src/api/module_bre/statistics.ts listTraits 带 selection_only
frontend/web/src/views/module_bre/statistics/index.vue selTraits 解耦 + asc 角标
frontend/web/src/views/module_bre/trait/index.vue 三字段表单/表格/详情/搜索
frontend/web/src/views/module_bre/selection_rule/index.vue 规则 JSON 说明
Temp/claude/e2e_direction_20260804.py 方向标注 e2e 探针(7 组)

新增/修改文件(2026-08-04 无性系级指数)

文件 说明
backend/app/api/v1/module_bre/statistics/schema.py SelectionIndexIn.aggregateclone 默认 / tree+ 文件头补 UTF-8 编码声明
backend/app/api/v1/module_bre/statistics/controller.py selection_index 透传 data.aggregate
backend/app/api/v1/module_bre/statistics/service.py _clone_units 可靠加权聚合 + 自株退化;zsum/Smith-Hazel 改单元 key 排名;apply_selection 按遗传实体写(clone_id + 溯源株 + 系内N株)+ 幂等晋升建 clone
frontend/web/src/api/module_bre/statistics.ts selectionIndex data 加 aggregate
frontend/web/src/views/module_bre/statistics/index.vue 聚合粒度 radio + clone 结果列
Temp/claude/e2e_clone_index_20260804.py 无性系级指数 e2e 探针(6 组)

新增/修改文件(2026-08-04 配合力交配设计)

文件 说明
backend/sql/weld_combining_design.sql 幂等 ALTERbre_cross_combination / bre_combining_abilitydesign_type
backend/app/api/v1/module_bre/cross_combination/model.py / schema.py / service.py design_type 字段 + create/update 校验归一化 + 导出/导入/模板兼容
backend/scripts/breeding_stats/combining.py solve(rows, design_type) 按设计分支:双列 model A / line_tester+NCIII model B(双因素、顺序 ANOVA、角色重叠/NCIII 门禁、gca_se
backend/app/api/v1/module_bre/statistics/controller.py / schema.py / service.py run_combining 透传 design_type + 按设计过滤 + 落库 + anova.gca_se
frontend/web/src/api/module_bre/statistics.ts / cross_combination.ts design_type 类型透传
frontend/web/src/views/module_bre/statistics/index.vue / cross_combination/index.vue 运行对话框设计选择 + 结果分显示 + CRUD 四处支持
Temp/claude/e2e_combining_design_20260804.py 配合力交配设计 e2e 探针(5 组)

新增/修改文件(2026-08-04 统计严谨·预测完整性与 MLOps 复现性)

文件 说明
backend/sql/weld_prediction_rigor.sql 幂等 ALTERbre_prediction_value.pa + bre_prediction.data_version/input_hash/engine_version
backend/sql/weld_rootstock.sql 幂等 ALTERbre_rootstock.dwarf_class/compatibility
backend/app/api/v1/module_bre/statistics/model.py / schema.py pa/data_version/input_hash/engine_version 字段 + OutSchema 透出
backend/app/api/v1/module_bre/statistics/service.py _DATA_VERSION="v2.7";PA 落库 + 批次真 PA;输入哈希(确定性序列化);germplasm_id 回填;Calo 相关校正(rel_by_trait + g_corr/g_note);covariate="competition"Chebyshev 邻域 + G×E 泛化 + 无坐标报错)
backend/scripts/breeding_stats/blup.py ENGINE_VERSION="1.0.0"
backend/app/api/v1/module_bre/rootstock/model.py / schema.py / service.py dwarf_class/compatibility 字段 + 导入导出/模板下拉
frontend/web/src/api/module_bre/statistics.ts 指数批次表/EBV 行类型加 germplasm_id/pa
frontend/web/src/views/module_bre/statistics/index.vue 批次表新列 + 协变量 radio(无/crop_load/competition
frontend/web/src/api/module_bre/rootstock.ts Rootstock 类型加两字段
frontend/web/src/views/module_bre/rootstock/index.vue 两字段全量(常量/搜索/表格/详情/表单)
Temp/claude/e2e_prediction_rigor_20260804.py ②③④ e2e 探针(4 组)
Temp/claude/e2e_rootstock_20260804.py ⑤ e2e 探针
Temp/claude/e2e_corr_spatial_20260804.py ①⑥ e2e 探针(3 组)
backend/sql/weld_combination_funnel.sql 幂等建 v_combination_funnel(六级聚合普通 VIEW
backend/app/api/v1/module_bre/statistics/service.py / controller.py combination_funnel() 查视图 + GET /statistics/combination-funnel
Temp/claude/e2e_combination_funnel_20260804.py 组合得失漏斗 e2e 探针(3 组)

新增/修改文件(2026-08-04 分子育种建数据能力)

文件 说明
backend/sql/weld_molecular.sql 幂等补 bre_genotype_sample.sample_name + (dataset_id, sample_name) 索引
backend/sql/bre_menu.sql 900210-900213 切真实页面 + F 段按钮 900700-900799 + 角色关联
backend/app/api/v1/module_bre/marker/ 五件套(marker_name UNIQUE 校验、CRUD/导入导出/模板)
backend/app/api/v1/module_bre/genotype_dataset/ 五件套(v1.4 规划表首次建服务)
backend/app/api/v1/module_bre/genotype_sample/ 五件套(dataset FK 校验 + dataset_name 透出)
backend/app/api/v1/module_bre/genotype_call/ 五件套 + import_vcf + fingerprint_check 两个专属端点
backend/app/api/v1/module_bre/__init__.py 注册 4 组路由
frontend/web/src/api/module_bre/marker.ts MarkerAPI
frontend/web/src/api/module_bre/genotype_dataset.ts GenotypingDatasetAPI
frontend/web/src/api/module_bre/genotype_sample.ts GenotypeSampleAPI
frontend/web/src/api/module_bre/genotype_call.ts GenotypeCallAPI + VCF/指纹接口与结果类型
frontend/web/src/views/module_bre/marker/index.vue 标记 CRUD 页
frontend/web/src/views/module_bre/genotype_dataset/index.vue 数据集 CRUD 页
frontend/web/src/views/module_bre/genotype_sample/index.vue 样本 CRUD 页(dataset 下拉)
frontend/web/src/views/module_bre/genotype_call/index.vue 分型 CRUD 页 + 导入 VCF / 指纹检测对话框
Temp/claude/e2e_molecular_20260804.py 分子育种 e2e 探针(CRUD/唯一键/父级/指纹/VCF/幂等)

新增/修改文件(2026-08-04 精修项四连发:DUS 数据能力 + stage 感知 + k-fold CV + 公平性报告)

文件 说明
backend/sql/weld_refine.sql 幂等 ALTERbre_prediction.stage varchar(16) + COMMENT
backend/sql/bre_dus_seed.sql UPOV TG/53 桃描述符 15 条种子(trait_code LEFT JOIN 解析 trait_idON CONFLICT DO NOTHING
backend/sql/bre_menu_refine.sql 900230 切真实页 + G 段按钮 900800-900808 + 角色关联
backend/app/api/v1/module_bre/dus/ 五件套 ×3 资源(descriptor 9 端点含导入导出模板 / test 9 / observation 6),注册 /bre/dus_test/*
backend/app/api/v1/module_bre/statistics/model.py PredictionModel.stage + CvResultModel + CvFoldModelcreate_all 建表)
backend/app/api/v1/module_bre/statistics/schema.py PredictionOut.stage + CvRunIn/CvResultOut/CvFoldOut + SelectionIndexIn/DecisionPreviewIn.stage
backend/app/api/v1/module_bre/statistics/service.py _trait_meta_map 取 stagerun_ablup 落 stagerun_cv/list_cv/cv_detailfairness_reportselection_index/decision_preview stage 过滤 + stage_warning/skipped_stage
backend/app/api/v1/module_bre/statistics/controller.py /statistics/cv/run /statistics/cv /statistics/cv/{id} /statistics/fairness + 指数/决策 stage 透传
backend/scripts/breeding_stats/blup.py kfold_cv:sire 家系分层留出 + 逐折 try/except + 留出 EBV 系谱预测
frontend/web/src/api/module_bre/dus.ts 三组 API + 类型
frontend/web/src/api/module_bre/statistics.ts runCv/listCv/cvDetail/fairnessReport + listTraits 补 stage
frontend/web/src/views/module_bre/dus/index.vue 单页三 tab(描述符模板/DUS 测试/观测录入)
frontend/web/src/views/module_bre/statistics/index.vue 「交叉验证」「公平性报告」双 tab + 指数/决策 stage 三态 + stage_warning ElAlert
Temp/claude/e2e_refine_20260804.py 精修项四连发 e2e 探针(4 组,ABLUP/GXE CV + 2 site 公平性)

新增/修改文件(2026-08-04 六项能力完善:MT-BLUP + GBLUP/ssGBLUP + DUS 特异性 + AMMI/FW 稳定性 + MLOps 重训 + stage 拆分)

文件 说明
backend/sql/weld_advanced.sql 幂等 ALTERbre_prediction.is_active + bre_trait_observation.stage + bre_dus_test.analysis_jsonjsonb+ COMMENT
backend/app/api/v1/module_bre/statistics/model.py PredictionModel.is_active + GeneticCorrResultModel + StabilityResultModelcreate_all 建 2 新表)
backend/app/api/v1/module_bre/statistics/schema.py GeneticCorrIn/GeneticCorrResultOut/StabilityRunIn/StabilityResultOut/GblupRunIn + SelectionIndexIn.g_method + RunStatsIn.stage + PredictionOut.is_active/stage
backend/app/api/v1/module_bre/statistics/service.py run_genetic_corr/list/detailrun_stability/list/detailrun_gblup/list_genotyping_datasetsmodel_drift/retrain/activaterun_ablup(stage)_gather_digest_inputs_smith_hazel_index(g_method);修复未定义 tid、retrain 不激活新批次
backend/app/api/v1/module_bre/statistics/controller.py 6 组新端点(genetic-corr×3 / stability×3 / gblup×2 / model drift·retrain·activate×3+ 透传 g_method/stage
backend/app/api/v1/module_bre/dus/service.py distinctness 求解器 + test_distinctness/distinctness_report(落 analysis_json + conclusion 自动建议)
backend/app/api/v1/module_bre/dus/controller.py / schema.py POST/GET /bre/dus_test/distinctness/{test_id} + DusTestOutSchema.analysis_json
backend/app/api/v1/module_bre/trait_observation/model.py / schema.py / service.py stage 字段(model 列 + create/update/out schema 透传 + 导入/导出映射,schema 暴露为收尾补丁)
backend/scripts/breeding_stats/mtblup.py solve_bivariate(成对双性状 REMLENGINE_VERSION=1.0.0
backend/scripts/breeding_stats/genomic.py build_g_matrix/solve_gblup/solve_ssgblupENGINE_VERSION=1.0.0;修复 V 块用 H 协方差)
backend/scripts/breeding_stats/stability.py finlay_wilkinson/ammiENGINE_VERSION=1.0.0;修复完美拟合 flag_stable
backend/scripts/breeding_stats/fdist.py f_icdf(二分反解)+ t_crit
backend/scripts/breeding_stats/blup.py ENGINE_VERSION="1.1.0"
frontend/web/src/api/module_bre/statistics.ts 三 tab 组 API + modelDrift/Retrain/Activate + g_method/stage 类型
frontend/web/src/views/module_bre/statistics/index.vue 「遗传相关 MT-BLUP」「稳定性 AMMI/FW」「基因组选择 GBLUP」三 tab + stage 三态 + g 矩阵来源 radio + 当前版本标签/漂移/重训/回滚按钮
frontend/web/src/views/module_bre/dus/index.vue 测试行「特异性判定」对话框
frontend/web/src/api/module_bre/tree_evaluation.ts / views/module_bre/tree_evaluation/index.vue 观测表单「观测阶段」下拉(juvenile/evaluation,写入每条观测 stage
Temp/claude/e2e_advanced_stability.py / stage.py / mtblup.py / gblup.py / dus.py / mlops.py 6 组 e2e 探针(运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.10 版本行 + §8.18 台账
doc/桃育种系统模块扩展需求规格.v2.10.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十一 六项能力完善 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑨ + EBV/分子行更新

新增/修改文件(2026-08-04 田间试验精度补强:砧木×接穗随机互作 G×R)

文件 说明
backend/scripts/breeding_stats/blup.py _solve_gxefactor_label/factor_name 参数(仅喂警告文案,默认保 G×E 不变)+ 公开 solve() 透传 + ENGINE_VERSION 1.2.0
backend/app/api/v1/module_bre/statistics/schema.py RunStatsIn.gxr
backend/app/api/v1/module_bre/statistics/controller.py run_ablup 透传 gxr
backend/app/api/v1/module_bre/statistics/service.py run_ablup(gxr):互斥门禁 + job_type=GXR + elif gxr: 分支(rootstock 剥离/门禁三件套/GXRBLUP/note σ²gxr+ 克隆坍缩系谱上移共享 + _DATA_VERSION v2.10
frontend/web/src/api/module_bre/statistics.ts RunStatsPayload.gxr
frontend/web/src/views/module_bre/statistics/index.vue G×R 复选框 + 互斥 watcher + fmtGxeNote σ²gxr 分支 + 批次表 v-if
Temp/claude/e2e_gxr_20260804.py e2e 探针(4 组断言,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.11 版本行 + §8.19 台账
doc/桃育种系统模块扩展需求规格.v2.11.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十二 G×R 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑩ + EBV/田间试验精度行补 G×R

新增/修改文件(2026-08-04 基因组选择实证严谨性:GS 专用 k-fold CV

文件 说明
backend/scripts/breeding_stats/genomic.py 抽取 _build_h(缺失基因型补 base+ 新增 kfold_cv_genomic(掩蔽留出 pearson/RMSE,输出对齐 blup.kfold_cv+ ENGINE_VERSION 1.1.0
backend/app/api/v1/module_bre/statistics/service.py _gather_gblup_inputs 提取(run_gblup↔GS CV 复用);run_cvdataset_id/method/maf_min + GS 分支(与 gxe/ABLUP 互斥)+ engine_version 按分支 + _DATA_VERSION v2.11
backend/app/api/v1/module_bre/statistics/schema.py CvRunIn.dataset_id/method/maf_min
backend/app/api/v1/module_bre/statistics/controller.py run_cv 透传三参
frontend/web/src/api/module_bre/statistics.ts CvRunPayload.dataset_id/method/maf_min
frontend/web/src/views/module_bre/statistics/index.vue CV tab mode radioABLUP/GS+ dataset/method/MAF + 隐藏 G×E + submitCv 按 mode
Temp/claude/e2e_gblup_cv_20260804.py GS CV e2e 探针(3 组:GBLUP/ssGBLUP 正例 + 门禁,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.12 版本行 + §8.20 台账
doc/桃育种系统模块扩展需求规格.v2.12.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十三 GS k-fold 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑪ + EBV/GS 行补「GS k-fold 实证验证」

新增/修改文件(2026-08-04 现代桃育种领域覆盖:S-allele + 抗病/需冷量性状)

文件 说明
backend/sql/bre_disease_chilling_traits.sql 5 条 numeric trait 种子(3 抗病 0-5 级病情指数 + 需冷量 h + 需热量 GDDinto_ebv=1、direction=asc,幂等 ON CONFLICT
backend/app/api/v1/module_bre/germplasm/model.py s_alleles 列(String(32)Sf=自交亲和型)
backend/app/api/v1/module_bre/germplasm/schema.py Create/Update 加 s_allelesOut 继承 Create
backend/app/api/v1/module_bre/cross_combination/schema.py CrossCombinationOutSchema.s_compat(可选派生字段)
backend/app/api/v1/module_bre/cross_combination/service.py _parse_s_alleles/_s_compat_check/_check_s_compat + create/update 校验(Sf 放行、共享 2→409、共享 1→半兼容警示)
frontend/web/src/api/module_bre/germplasm.ts GermplasmForm/GermplasmTable.s_alleles?
frontend/web/src/views/module_bre/germplasm/index.vue 表单加 S-等位基因输入 + 导出列
frontend/web/src/views/module_bre/cross_combination/index.vue 包装 createApi/updateApi 展示 s_compat 警示
Temp/claude/e2e_s_allele_20260804.py S-allele 兼容校验探针(纯函数 8 例 + service 层 5 组,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.13 版本行 + §8.21 台账
doc/桃育种系统模块扩展需求规格.v2.13.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十四 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑫ + 相关行补「S-allele 兼容 + 抗病/需冷量性状字典」

新增/修改文件(2026-08-04 GWAS/QTL/MAS 标记辅助选择闭环)

文件 说明
backend/scripts/breeding_stats/gwas.py GWAS 求解器(GLM+PCSVD 群体结构 + fdist.f_pvalue p 值 + Bonferroni/BH-FDR + QTL 合并 + 岭回归共线兜底,ENGINE_VERSION=1.0.0,纯 numpy
backend/sql/weld_gwas.sql 幂等 CREATE TABLE IF NOT EXISTSbre_gwas_result/bre_gwas_snp/bre_qtl/bre_mas_panel/bre_mas_panel_marker5 新表兜底)
backend/sql/bre_menu.sql §6dsys_menu 900214 component_path 翻转为 module_bre/gwas/index
backend/app/api/v1/module_bre/statistics/model.py GwasResultModel/GwasSnpModel/QtlModel/MasPanelModel/MasPanelMarkerModel
backend/app/api/v1/module_bre/statistics/schema.py GwasRunIn/GwasResultOut/GwasSnpOut/QtlIn/QtlOut/MasPanelIn/MasPanelOut/MasPanelMarkerIn/MasPanelSetMarkersIn
backend/app/api/v1/module_bre/statistics/controller.py gwas×3 + qtl×5 + mas-panel×4 端点(复用 module_bre:statistics:* 权限)
backend/app/api/v1/module_bre/statistics/service.py _gather_gwas_inputs + run_gwas/list_gwas/gwas_detail + qtl/mas_panel CRUD + mas_panel_set_markers + _mas_hit_map + decision_preview marker 条件 + _DATA_VERSION v2.12
frontend/web/src/api/module_bre/gwas.ts runGwas/listGwas/gwasDetail + Qtl/MasPanel/MasPanelMarker API
frontend/web/src/views/module_bre/gwas/index.vue 三 tabGWAS 结果 Manhattan/QQ 裸 echarts + QTL 定位 + MAS 面板)+ 运行对话框
Temp/claude/e2e_gwas_20260804.py GWAS/QTL/MAS 闭环探针(7 段断言,运行后自动清理;含数据设计要点避免 PC 吞噬 QTL)
doc/桃育种系统模块扩展需求规格.md v2.14 版本行 + §8.22 台账
doc/桃育种系统模块扩展需求规格.v2.14.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十五 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑬ + 900214 行「GWAS/QTL 已落地」

新增/修改文件(2026-08-04 九缺口补齐:经典侧计算端点 + 分子侧严谨性 + 求解器核心)

文件 说明
backend/app/api/v1/module_bre/statistics/controller.py POST /data-quality + POST /genetic-gain + POST /mating-recommend + POST /gwas-qtl-x-e
backend/app/api/v1/module_bre/statistics/service.py data_quality_report/genetic_gain/mating_recommend/qtl_x_e + _allelic_from_gt/装配 marker_type 分支 + _DATA_VERSION v2.13
backend/app/api/v1/module_bre/statistics/schema.py 4 新端点入参出参 + RunStatsIn.spatial
backend/scripts/breeding_stats/blup.py solve_spatialAR1×AR1ENGINE_VERSION 1.3.0+ _build_ainv_sparse/_cg_solve/HutchinsonN_SPARSE=1000 阈值分派稀疏-CG 路径,稠密路径逐字节不变)
backend/scripts/breeding_stats/gwas.py _emmax + 后处理抽共享 _bh_qvalues/_finalize/_clusterGLM 逐字节不变,ENGINE_VERSION 1.1.0
backend/scripts/breeding_stats/genomic.py build_g_matrix 多等位 VanRaden 推广(ENGINE_VERSION 1.2.0
backend/app/api/v1/module_bre/genotype_call/service.py VCF 导入按 ALT 数定 marker_typessr/snp
backend/sql/weld_mas_semantics.sql 幂等 ADD COLUMNbre_mas_panel_marker.mode / favorable_allele / haplotype_group
frontend/web/src/views/module_bre/statistics/index.vue 数据质量/遗传增益/选配 3 入口 + spatial 复选框
frontend/web/src/api/module_bre/statistics.ts 3 新端点 + spatial 参数
frontend/web/src/views/module_bre/gwas/index.vue method 下拉(gwas/emmax+ QTL×E tab + 面板标记编辑器三控件(xeForm 类型断言修复 vue-tsc
frontend/web/src/api/module_bre/gwas.ts GwasQtlXEIn + method 枚举
Temp/claude/e2e_data_mating_gain_20260804.py 批1 探针(数据质量/遗传增益/选配,运行后自动清理)
Temp/claude/e2e_molrigor_20260804.py 批2 探针(EMMAX/SSR/QTL×E/MAS 语义,运行后自动清理)
Temp/claude/e2e_spatial_sparse_20260804.py 批3 探针(AR1×AR1/稀疏-CG/Hutchinson,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.15 版本行 + §8.23 台账(+ 补 v2.13 缺失版本行)
doc/桃育种系统模块扩展需求规格.v2.15.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十六 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑭ + EBV/ABLUP 行、GWAS/QTL/MAS 行补注

新增/修改文件(2026-08-05 十二项真缺口补齐:引擎三件 + 模块四件 + 底座五件)

文件 说明
backend/scripts/breeding_stats/blup.py solve_spatialaniso(ρ_row/ρ_col 双参,ENGINE_VERSION 1.4.0
backend/scripts/breeding_stats/mtblup.py solve_multi 全多变量 EM-REMLENGINE_VERSION 1.1.0
backend/scripts/breeding_stats/gwas.py _ssgwas 单步 GWAS MEM 对角近似(ENGINE_VERSION 1.2.0
backend/app/api/v1/module_bre/statistics/service.py full_mtblup=True 模式 + _DATA_VERSION v2.14 + _allelic_columns SSR 兜底限定空 marker_type(回归修复)
backend/app/api/v1/module_bre/field_operation/{model,crud,service,controller,schema}.py 农事操作 900051 五件套
backend/app/api/v1/module_bre/observation/{model,crud,service,controller,schema}.py 通用观测 900050 五件套
backend/app/api/v1/module_bre/breeding_report/{model,crud,service,controller,schema}.py 育种报告 900075 五件套 + POST /report/generate
backend/app/api/v1/module_bre/analysis_dataset/{model,crud,service,controller,schema}.py 分析数据集 900070 五件套 + 新表 bre_analysis_dataset
backend/app/api/v1/module_bre/audit/{model,crud,service,controller,schema}.py 审计切面 + `GET /bre/audit/list
backend/app/api/v1/module_bre/alert/{model,crud,service,controller,schema,job}.py 超期预警 + `GET /bre/alert/list
backend/app/api/v1/module_bre/brapi/controller.py BrAPI 2.x /brapi/v2 五只读端点 + MIAPPE
backend/app/utils/number_gen.py NumberGenService + pg_advisory_xact_lock 原子取号
backend/app/api/v1/module_bre/sequence/model.py bre_sequence 表
backend/app/api/v1/module_bre/{cross_combination,tree,selection_result,seedling}/service.py 4 处编号迁移(YY+3位/组合-序号/clone_code 扩位/batch_no YP-…)
backend/app/core/ap_scheduler.py 3 系统 jobcleanup Sun 03:00 / alert 08:37 / backup 02:17
backend/app/utils/backup_job.py 每日备份 job 包装 pg_backup.shGit Bash + MSYS 路径)
backend/scripts/pg_backup.sh / pg_restore.sh pg_dump 自定义格式 + N 天轮转 / 恢复脚本
backend/app/init_app.py brapi_router 根注册(/brapi/v2 非 /bre 前缀)
backend/sql/weld_*.sql(op_type 字典/菜单翻转/文案清理/bre_alert/bre_sequence/bre_analysis_dataset 幂等 weld 兜底
frontend/web/src/views/module_bre/{field_operation,observation,breeding_report,analysis_dataset,alert}/index.vue 4 新模块页 + 预警中心
frontend/web/src/api/module_bre/{field_operation,observation,breeding_report,analysis_dataset,alert}.ts 5 新 API
frontend/web/src/views/module_bre/statistics/index.vue spatial aniso 复选框 + gwas method=ssgwas 下拉
Temp/claude/e2e_gaps_engines_20260804.py 批1 探针(ssgwas/solve_multi/aniso,运行后自动清理)
Temp/claude/e2e_gaps_modules_20260805.py 批2 探针(四模块 CRUD + report generate + 菜单翻转,运行后自动清理)
Temp/claude/e2e_gaps_base_20260804.py 批3 探针(审计/编号并发/预警/备份/BrAPI,运行后自动清理)
Temp/claude/regress_logs/ 全量回归日志(8 旧探针 + 3 批探针)
doc/桃育种系统模块扩展需求规格.md v2.16 版本行 + §8.24/8.25/8.26 台账
doc/桃育种系统模块扩展需求规格.v2.16.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十七 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑮ + 相关行补注 + 过时「待建」标记修正

新增/修改文件(2026-08-05 桃育种业务流全面完善:批A 业务数据链 + 批B 统计算法 + 批C 前端)

文件 说明
backend/app/api/v1/module_bre/field_operation/model.py 4 采收列 yield_kg/fruit_count/avg_fruit_weight/marketable_rate
backend/app/api/v1/module_bre/field_operation/{service,schema}.py harvest 结构化产量同步 bre_trait_observationA1+ 表单 4 字段
backend/app/api/v1/module_bre/observation/model.py germplasm_id 可空 FKA3
backend/app/api/v1/module_bre/observation/{service,schema}.py 种质校验 + EAV 校验(A5+ 4 查询过滤 tree/plot/germplasm/trial_study + germplasm 表单字段
backend/app/api/v1/module_bre/seed_lot/{model,schema}.py pollination_id FKA4
backend/app/api/v1/module_bre/seed_treatment/{model,schema}.py seed_lot_id FKA4
backend/app/api/v1/module_bre/tree/service.py create 阶段自动设置(A6breeding_generation→juvenile/evaluation
backend/app/api/v1/module_bre/trait_observation/service.py EAV 校验(numeric/date parse + valid_min/max + 重复)+ 成株性状门禁(A5/A6)
backend/app/api/v1/module_bre/statistics/service.py _values_by_tree_env + run_type_b_heredityB1+ _genetic_corr_matrixB2+ auto_weightsB3+ run_clusterB4+ _DATA_VERSION v2.15
backend/app/api/v1/module_bre/statistics/controller.py POST /type-b-heredity + GET /type-b + GET /type-b/{id} + POST /cluster + correlation mode/g_method/year 透传
backend/app/api/v1/module_bre/statistics/schema.py TypeBIn/Out + CorrelationIn mode/g_method/year + SelectionIndexIn auto_weights + ClusterIn
backend/app/api/v1/module_bre/statistics/model.py bre_type_b_result 新表(TypeBResultModel
backend/sql/weld_busflow.sql A1/A3/A4 四处 ALTER ADD COLUMN IF NOT EXISTS + index(幂等)
backend/sql/bre_yield_phenology_traits.sql A2 产量/物候/品质/生长量/描述性状种子 19 条(ON CONFLICT 幂等)
frontend/web/src/plugins/echarts.ts 注册 HeatmapChart + VisualMapComponent
frontend/web/src/api/module_bre/statistics.ts type-b/cluster/correlation mode/funnel/auto_weights 类型
frontend/web/src/api/module_bre/observation.ts ObservationPageQuery 四过滤 + ObservationForm germplasm_id
frontend/web/src/api/module_bre/field_operation.ts FieldOperationTable/Form 四采收字段
frontend/web/src/views/module_bre/observation/index.vue plot/站点/germplasm 过滤 + germplasm 表单(C1
frontend/web/src/views/module_bre/field_operation/index.vue harvest 结构化表单/表格 4 列(C1)
frontend/web/src/views/module_bre/statistics/index.vue correlation/gblup 热图折线 + type-B tab + cluster 树状图 + funnel 对话框(C2/C3
frontend/web/src/views/module_bre/stage_phenotype/index.vue tabs 通用观测/农事操作翻真实页(C4)
frontend/web/src/views/module_bre/_shared/StageView.vue compMap 注册 Observation/FieldOperationC4
Temp/claude/e2e_busflow_20260805.py 批A 探针(A1-A6,11 组断言,运行后自动清理)
Temp/claude/e2e_statsflow_20260805.py 批B 探针(B1-B4,15 组断言,运行后自动清理)
Temp/claude/smoke_busflow_c_20260805.py 批C HTTP smoke10 检查,不建数据)
doc/桃育种系统模块扩展需求规格.md v2.17 版本行 + §8.27 台账
doc/桃育种系统模块扩展需求规格.v2.17.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §十八 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑯ + 相关行补注

新增/修改文件(2026-08-05 世代闭环:单株晋级落系谱)

文件 说明
backend/app/api/v1/module_bre/selection_result/service.py _promote_tree_to_clone 建种质时同步落 bre_pedigreechild_code=品种名、dam/sire=tree.dam/sire 回退组合 female/male_parent_id、combination_id、generationchild_code 幂等)+ 种质携带 generation/stage + combo=None 初始化防 UnboundLocalError
Temp/claude/e2e_pedigree_closure_20260805.py 世代闭环探针(11 组断言,运行后自动清理)
Temp/claude/cleanup_pedigree_test.py 前缀清理脚本(幂等,探针残留兜底)

新增/修改文件(2026-08-05 近交惩罚静默关闭修复:亲缘矩阵多源解析)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py 重写 _germplasm_pedigree 多源级联(① 规范化名称反查显式系谱 → ② tree FK 兜底唯一一致 → ③ founder;BFS 祖先展开去重;返回 (pedigree, coverage));mating_recommend 加 kinship_status/kinship_warning/kinship + 逐对「亲缘未解析(r 按 0 计)」旗标
Temp/claude/e2e_mating_kinship_20260805.py 近交惩罚静默关闭修复探针(14 组断言,运行后自动清理)

新增/修改文件(2026-08-05 EBV 回退方法学修复:direct 优先 + 子代测验降权)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py mating_recommend EBV 回退重写——direct 优先(有 direct 绝不被树级值污染);回退显式标注 progeny + _EBV_SOURCE_FACTOR 降权 0.5 参与打分(mid=(f_a·ebv_a+f_b·ebv_b)/2);双亲均缺直接值的子代树剔除(防双侧等权重复计);记 n_progeny/n_combos;返回体加 candidate_ebv + ebv_source.coverage + 逐对旗标
Temp/claude/e2e_mating_ebv_20260805.py EBV 回退方法学修复探针(5 组断言,运行后自动清理)

新增/修改文件(2026-08-05 数据质量离群值方向语义错位修复:同向=精英 / 反向=疑似错误)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py data_quality_report 方向感知分流——取 trait_row.directiondesc/None→desirable_high=True 高值优;asc→False);IQR/MAD 命中的株按偏离侧双通道分类(is_high=v>medis_elite=is_high==desirable_high):同向→extreme_candidatesclass=extreme_candidate/ 反向→outliersclass=outlier);返回体加 direction + extreme_candidates + summary.n_extreme_candidateshas_warning/n_outliers/outlier_rate 语义收紧为疑似录入错误计数
frontend/web/src/views/module_bre/statistics/index.vue 数据质量 tab 改双表——「极值候选(精英)」success 标签表 + 「疑似录入错误」danger 标签表 + 选育方向指示条 + 无错误绿色 info alert(提示文案改方向语义)
Temp/claude/e2e_data_mating_gain_20260804.py A6 探针 [1] 扩展——17 株(15 正常 + 精英高值 16.0 + 错误低值 2.0):精英进 extreme_candidates/class=extreme_candidate/side=high 且不在 outliers;错误进 outliers/class=outlier/side=lown_extreme_candidates=1

新增/修改文件(2026-08-05 ΔG 投影假设声明 + 工程健壮性打磨:note 假设 + spatial 缺坐标降级 + numpy 收敛)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py genetic_gain 返回体加 note 投影假设声明(环境均值恒定/演示值);② run_ablup(spatial=True) 缺坐标株记 missing_coord_ids → 剔除表型保留系谱(EBV 由系谱预测)、剔除数写批次 note「缺坐标剔除N株表型(EBV由系谱预测)」、全缺才整批 409、input_hash 用剔除后子集;③ 模块级 import numpy as np:24+ 移除 7 处局部 importdata_quality_report 逐株 flag 循环改 numpy 布尔掩码向量化(输出逐字节不变)
frontend/web/src/views/module_bre/statistics/index.vue gain tab 描述区后、轮次表前加 el-alert type="info" 展示 gainData.note(投影假设边界)
Temp/claude/e2e_spatial_sparse_20260804.py spatial 探针新增强健降级场景——5 株(4 株 2×2 网格 + 1 株无坐标):method=AR1×AR1/train_n=4/note 含剔除标注/5 株均有 EBV 行;全缺坐标仍整批 409trait 清理含 tD_{P}
Temp/claude/e2e_data_mating_gain_20260804.py A6 探针 [2] 加 note 断言——含「环境均值恒定」且两性状稳定一致

新增/修改文件(2026-08-05 A–F 六项功能级缺口·批1 父本验证 + 近交衰退)

文件 说明
backend/app/api/v1/module_bre/pollination/service.py A1 _validate_pollen_parentcreate/update 统一:批次采集父本≠授粉父本 409,混合/未声明放行)
backend/app/api/v1/module_bre/tree/service.py A2 _resolve_parents 改返回 (dam, sire, warning) + create/update 返回体 warning(以显式为准,不阻断)
backend/app/api/v1/module_bre/tree/schema.py `warning: str
backend/app/api/v1/module_bre/cross_combination/service.py A3 _check_parent_roles 同质自交 409create/update 生效亲本统一)
backend/app/api/v1/module_bre/statistics/schema.py InbreedingDepressionIntrait_id/trait_code + year/trial_study_id + min_n
backend/app/api/v1/module_bre/statistics/controller.py POST /bre/statistics/inbreeding-depression
backend/app/api/v1/module_bre/statistics/service.py inbreeding_depression(F=A_ii1 + 树级表型均值 → numpy lstsq 回归,F=0 兜底)+ _DATA_VERSION v2.22
frontend/web/src/api/module_bre/statistics.ts inbreedingDepression API
frontend/web/src/views/module_bre/statistics/index.vue 亲缘/近交 tab 近交衰退区(trait/year + el-alert + el-descriptions + 高 F 株表;el-alert 'error' 修复 TS2322
Temp/claude/e2e_parent_validation_20260805.py 批1-A 父本验证探针(10 断言,运行后自动清理)
Temp/claude/e2e_inbreeding_depression_20260805.py 批1-C 近交衰退探针(4 断言,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.22 版本行 + §8.32 台账
doc/桃育种系统模块扩展需求规格.v2.22.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §18.10 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ⑳ + 相关行补注

新增/修改文件(2026-08-05 A–F 六项功能级缺口·批2 GS 家系 CV + 试验设计深度)

文件 说明
backend/scripts/breeding_stats/genomic.py B kfold_cv_genomic 加 `split="random"
backend/app/api/v1/module_bre/statistics/schema.py AnovaIn.blockRCBD 区组校正开关)+ TrialDesignIntrial_study_id/design_type/seed
backend/app/api/v1/module_bre/statistics/controller.py POST /bre/statistics/trial-design + run_anova 透传 block
backend/app/api/v1/module_bre/statistics/service.py run_cv 加 split 透传 + GS family_of 构建 + note 记 n_familiestrial_design RCBD 生成器(random.Random(seed) 洗牌 + case() 批量落库);run_anova 加 block 分支(solve_rcbd);_DATA_VERSION v2.23
backend/scripts/breeding_stats/anova.py F2 solve_rcbdRCBD 双因素 Type I 顺序,SS_group/SS_block/SS_error + f_block/p_block + 区组均值;solve 单因素逐字节不变)
backend/app/api/v1/module_bre/trial_study_entry/model.py F1 block_no 列(可空 integer
backend/sql/weld_trial_study_entry.sql F1 ALTER TABLE bre_trial_study_entry ADD COLUMN IF NOT EXISTS block_no integer(幂等)
frontend/web/src/api/module_bre/statistics.ts runAnova 加 block + trialDesign() + TrialDesignResult
frontend/web/src/views/module_bre/statistics/index.vue ANOVA tab 重构(生成 RCBD 设计工具条 + 设计区组表 + anovaBlock checkbox + 区组均值/block 结果 v-if
Temp/claude/e2e_trial_design_20260805.py 批2-F 探针(5 组断言,运行后自动清理)
Temp/claude/e2e_gs_family_cv_20260805.py 批2-B 探针(5 组断言,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.23 版本行 + §8.33 台账
doc/桃育种系统模块扩展需求规格.v2.23.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §18.11 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ㉒ + 相关行补注

新增/修改文件(2026-08-05 A–F 六项功能级缺口·批3 OCS 最优贡献选择 + MABC 标记辅助回交)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py D _proj_simplex/_solve_ocs + ocs(投影梯度,A=pedigree+rmat 组装,vs_top_n 对比);共享 helper _candidate_ebv_map 抽取(mating_recommend 内联原样提取,direct/progeny 降权 0.5/双侧去重保留);E _pure_homologous + mabc_progress(前景 _mas_hit_map + 背景恢复率 + _BC_LADDER 晋级建议);_DATA_VERSION v2.24
backend/app/api/v1/module_bre/statistics/controller.py POST /bre/statistics/ocs + POST /bre/statistics/mabc-progress
backend/app/api/v1/module_bre/statistics/schema.py OcsIncandidate_germplasm_ids/n_select/lam/prediction_id+ MabcIncandidate_tree_ids/foreground_panel_ids/background_panel_ids/recurrent_parent_tree_id/foreground_min_hits/generation/background_target)均 extra="ignore"
frontend/web/src/api/module_bre/statistics.ts ocs() + mabcProgress() API
frontend/web/src/views/module_bre/statistics/index.vue 「选配推荐」tab OCS 运行区(n_select + λ 滑杆 + contribution 表 + vs_top_n 对比)+ 独立「回交 MABC」tab(面板/轮回亲本/候选树 + 参数 + 逐株结果 + recommended 降序表)
Temp/claude/e2e_ocs_20260805.py 批3-D OCS 探针(17 断言,运行后自动清理;λ 梯度/退化/partial 告警/三 409
Temp/claude/e2e_mabc_20260805.py 批3-E MABC 探针(23 断言,运行后自动清理;前景/背景复算/reason/童期/六 409
doc/桃育种系统模块扩展需求规格.md v2.24 版本行 + §8.34 台账
doc/桃育种系统模块扩展需求规格.v2.24.md 冻结快照
doc/桃育种系统统计引擎实施记录.md §18.12 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md header ㉓ + 相关行补注

新增/修改文件(2026-08-05 近交衰退两处正确性修复:方向感知 + 深层系谱)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py inbreeding_depression 方向感知检测(desirable_high=direction!="asc"asc 衰退=slope>0 且 t≥+1.645interpretation 方向化)+ 深层系谱 F(复用 _germplasm_pedigree BFS + 树节点 + 未解析 founder 兜底;_germplasm_pedigree 本体零改动)
frontend/web/src/views/module_bre/statistics/index.vue 近交衰退提示文案方向化(「高优性状显著负斜率 / 低优性状(如病指)显著正斜率 = 近交衰退」)
Temp/claude/e2e_inbreeding_depression_20260805.py 批1-C 近交衰退探针扩展 4→6 组断言(新增 [4] asc 病指方向感知 + [5] 深层系谱 F 多世代;原 [1][2][3][x] 保持)
doc/桃育种系统模块扩展需求规格.md §8.35 跟进台账
doc/桃育种系统统计引擎实施记录.md §18.13 跟进 + 文件清单/备份/复跑

新增/修改文件(2026-08-05 分子亲本验证 + 试验设计深度·批4)

文件 说明
backend/app/api/v1/module_bre/genotype_call/service.py mendelian_check(子代 vs 声明亲本 union 规则、跨数据集亲本基因型解析、no_declared_parents/missing_parent_genotype 状态、incompatible_markers 明细)+ _allele_set 复用 + import TreeModel
backend/app/api/v1/module_bre/genotype_call/controller.py GET /bre/genotype_call/mendelian/checkAuth module_bre:genotype_call:queryQuery dataset_id + compat_threshold=0.98,镜像 fingerprint/check
backend/app/api/v1/module_bre/statistics/service.py trial_design 分派 rcbd/augmented/alpharcbd 逐字节不变)+ _trial_design_augmented(对照 anchoring/新品系 round-robin/对照 block_no 不落库)+ _trial_design_alpha(平方闭式格子 + 一般贪心可分解 + _is_prime + balance_warning + block_no 复合编码)+ _DATA_VERSION v2.25
backend/app/api/v1/module_bre/statistics/schema.py TrialDesignIncheck_germplasm_ids: list[int]=[] / block_size: int|None / reps: int|Noneextra="ignore"+ design_type 描述改 rcbd/augmented/alpha
backend/app/api/v1/module_bre/statistics/controller.py trial_design 透传三新参 + summary 更新「RCBD/增广/α-格子(落库 block_no)」
frontend/web/src/api/module_bre/genotype_call.ts mendelianCheck() + GenotypeCallMendelianParams/Result/Tree/IncompatMarker 类型
frontend/web/src/views/module_bre/genotype_call/index.vue 工具栏「孟德尔/亲本一致性」按钮 + FaDialogdataset select + compat_threshold + summary 计数 + trees 表 tree_no/dam/sire/informative/rate/flag/incompatible_markers 展开)
frontend/web/src/api/module_bre/statistics.ts trialDesign design_type 枚举扩 augmented/alpha + check_germplasm_ids/block_size/reps + TrialDesignResult 加 checks/n_new_entries/n_checks/check_reps/block_size/reps/balance_warning + blocks 联合类型
frontend/web/src/views/module_bre/statistics/index.vue DESIGN_TYPE_LABELS 补 增广/α-格子 + 条件参数(augmented 对照多选 / alpha block_size+reps+ α-格子平衡性 el-alert + alpha 块渲染「重复{rep}·块{blk}」
Temp/claude/e2e_mendelian_check_20260805.py 批4-A 探针(8 断言:跨数据集解析/alien 等位/rate/状态/空数据集零值,运行后自动清理)
Temp/claude/e2e_trial_design_ext_20260805.py 批4-B 探针(19 断言:增广/平方格子/部分 r/非素数告警/一般贪心/四 409,运行后自动清理)
doc/桃育种系统模块扩展需求规格.md v2.25 版本行 + §8.36 台账
doc/桃育种系统统计引擎实施记录.md §18.14 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md 相关行补注(分子育种 mendelian + 试验设计行增广/α-格子)

新增/修改文件(2026-08-05 批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验)

文件 说明
backend/scripts/breeding_stats/blup.py solveblock 参数分派新 _solve_block(区组第二随机效应,镜像 _solve_gxe+ ENGINE_VERSION 1.5.0
backend/app/api/v1/module_bre/statistics/service.py run_ablup block 开关 + block 分支(block_no 读取/降级剔除/≥2 区组 409+ 互斥(block×gxe/gxr/spatial+ data_quality_report dataset_id 可选 + mendelian 段 + _excluded_tree_ids 系谱消费方断链(_build_pedigree/run_ablup/inbreeding/kinship/cv/_germplasm_pedigree+ _DATA_VERSION v2.26
backend/app/api/v1/module_bre/statistics/schema.py RunAblupIn.block + DataQualityIn.dataset_id
backend/app/api/v1/module_bre/statistics/controller.py run_ablup block 透传 + data-quality dataset_id 透传
backend/app/api/v1/module_bre/genotype_call/model.py MendelianCheckModelbre_mendelian_check + MendelianCheckTreeModelbre_mendelian_check_treeFK CASCADE
backend/app/api/v1/module_bre/genotype_call/service.py 纯计算核心抽共享 _compute_mendelian + 新 run_mendelian_check(落库 + flag upsert 隔离/未 flag 清除,可逆)
backend/app/api/v1/module_bre/genotype_call/controller.py POST /bre/genotype_call/mendelian/check/runAuth editGET 只读预览保留)
backend/app/api/v1/module_bre/tree/model.py TreePedigreeExclusionModelbre_pedigree_exclusiontree_id 唯一)
frontend/web/src/api/module_bre/statistics.ts RunAblupPayload.block + DataQualityPayload.dataset_id
frontend/web/src/api/module_bre/genotype_call.ts mendelianCheckRun + GenotypeCallMendelianRunResultcheck_id/isolated/cleared
frontend/web/src/views/module_bre/statistics/index.vue GxE tab block 开关 + 互斥 + 数据质量 tab dataset 选择器 + mendelian 段(flag alert + 隔离树表)
frontend/web/src/views/module_bre/genotype_call/index.vue 孟德尔对话框主按钮改 POST run + check_id/隔离树数展示
Temp/claude/e2e_ablup_block_20260805.py 批5-A 探针(6 场景:已知 σ²block 恢复/409 门禁/互斥/降级/无归零警告)
Temp/claude/e2e_mendelian_persist_20260805.py 批5-B 探针(ok=19 fail=0:落库/隔离断开 EBV/可逆清除/data-quality 段/只读零回归)
Temp/claude/e2e_stats_numerics_20260805.py 批5-C 探针(ok=101 fail=0:全量统计引擎逐段 ground-truth 真值)
doc/桃育种系统模块扩展需求规格.md v2.26 版本行 + §8.37 台账
doc/桃育种系统统计引擎实施记录.md §18.15 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md 相关行补注(孟德尔落库隔离 + block 随机效应 + 统计引擎数值校验)

新增/修改文件(2026-08-05 批6 规划↔目标↔试验 可追溯性闭环)

文件 说明
backend/sql/weld_plan_trace.sql 幂等 ALTER 三列 + FKbre_target.plan_id、bre_trial.plan_id、bre_trial.target_id(均可空)
backend/app/api/v1/module_bre/target/model.py TargetModel.plan_id + relationship
backend/app/api/v1/module_bre/target/schema.py TargetCreateSchema/TargetUpdateSchema.plan_id 透传
backend/app/api/v1/module_bre/target/service.py get_list outerjoin 解析 plan_name + create 父校验(坏 plan_id 409+ delete assert_no_children
backend/app/api/v1/module_bre/trial/model.py TrialModel.plan_id/target_id + 双 relationship
backend/app/api/v1/module_bre/trial/schema.py 双字段透传
backend/app/api/v1/module_bre/trial/service.py get_list 解析 plan_name+target_name + create 双父校验 + delete assert_no_children
backend/app/api/v1/module_bre/plan/service.py trace(plan_id)(目标链/试验链/软删过滤/totals+ delete assert_no_children
backend/app/api/v1/module_bre/plan/controller.py GET /bre/plan/trace/{id}
frontend/web/src/api/module_bre/plan.ts PlanTrace 类型 + getPlanTrace
frontend/web/src/api/module_bre/target.ts getTargetOptions
frontend/web/src/views/module_bre/target/index.vue 「所属计划」select + 表格/详情列
frontend/web/src/views/module_bre/trial/index.vue 「所属计划/目标」select + 表格/详情列
frontend/web/src/views/module_bre/plan/index.vue 「追溯」行操作弹窗(ElCollapse 目标链/试验链)
Temp/claude/e2e_plan_trace_20260805.py 批6 探针(17 断言:目标链/试验链/totals/软删/孤目标/父校验/删除守卫/标签解析)
Temp/claude/e2e_audit_20260805.py 残留检查限定 entity_type=='bre_target'(跨表撞 id 误报根治)
doc/桃育种系统模块扩展需求规格.md v2.27 版本行 + §8.38 台账
doc/桃育种系统统计引擎实施记录.md §18.16 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md ㉖ 批6 可追溯性闭环补注

新增/修改文件(2026-08-05 批7 统计引擎全量十模块 golden 复查·系谱键空间错位修复)

文件 说明
backend/app/api/v1/module_bre/statistics/service.py 新增共享 helper _tree_individual_keysint→"t{id}" 对齐系谱键空间)+ 四个调用点收口(_genetic_corr_matrix/_smith_hazel_index mtblup 分支/run_genetic_corr/run_type_b_heredity+ _DATA_VERSION v2.28
backend/app/api/v1/module_bre/genotype_call/service.py GENOTYPE_DATA_VERSION v2.28
Temp/claude/e2e_rg_golden_20260805.py 批7 探针(ok=21 fail=0type_b 分裂家系 golden + correlation 平衡 golden + 分裂家系 discriminator + str/int 键诊断;含 exit-code 通道修复 fail==0
Temp/claude/e2e_spatial_sparse_20260804.py 版本断言 v2.27→v2.28(×2
Temp/claude/e2e_statsflow_20260805.py 版本断言 v2.27→v2.28
Temp/claude/e2e_prediction_rigor_20260804.py 版本断言 v2.27→v2.28
Temp/claude/e2e_mendelian_persist_20260805.py 版本断言 v2.27→v2.28
Temp/claude/http_v228.py 批7 HTTP 核验(type-b-heredity 分裂家系 r_B>0.5/n_common=0 + genetic-corr/run 分裂家系 r_g>0.5 + 平衡 r_g>0.65
doc/桃育种系统模块扩展需求规格.md v2.28 版本行 + §8.39 台账
doc/桃育种系统统计引擎实施记录.md §18.17 落地 + 文件清单/备份/复跑
doc/桃育种系统规划对照总表.md ㉗ 批7 系谱键空间错位修复补注

新增/修改文件(2026-08-05 回归基建:统一回归 + 高风险模块 tc 套件,无后端代码改动)

文件 说明
run_regression.py 统一回归驱动:顺序串跑 Temp/claude/e2e_.py(排除 e2e_probe+ backend/scripts/test_bre_analysis_*_tc.py = 63 测试,每测试独立子进程 log 到 regression_logs/EXIT 汇总;DPB_PYTHON 覆盖解释器;utf-8 reconfigure 防 GBK;过滤器 + --keep-logs
backend/scripts/test_bre_analysis_ssgblup_tc.py 正式 tc 套件(ok=14):GBLUP/ssGBLUP H⁻¹ 拼接判别——非基因型株 GBLUP EBV=0 / ssGBLUP EBV≠0(算偏当正常输出的同款隐患判别)
backend/scripts/test_bre_analysis_ocs_tc.py 正式 tc 套件(ok=23):OCS 投影梯度 golden(Σc/c≥0/λ 单调/c'Ac/λ=0 退化/409+422
backend/scripts/test_bre_analysis_mabc_tc.py 正式 tc 套件(ok=24):MABC 前景/背景恢复率/晋级/童期 C6/422+409
backend/scripts/test_bre_analysis_mendelian_tc.py 正式 tc 套件(ok=9):孟德尔 POST run 落库/隔离注册表/阈值 0.0 可逆/GET 零回归(URL 下划线 genotype_call + 启动残留预清理 _wipe + 隔离验证时序)
Temp/claude/backup_test_rigor_20260805/ 备份镜像(root/run_regression.py + backend/scripts 4 tc 套件最新修复版)

新增/修改文件(2026-08-05 回归基建 2:分析模块 tc 补齐 + pytest 接入 + run_ci,无后端代码改动)

文件 说明
backend/scripts/test_bre_analysis_genetic_corr_tc.py 正式 tc 套件(ok=19):平衡 3 性状 r_g 判别 + 分裂家系 r_g(S1,S2)>0.5 且 n_common=0(独立种子 SEED_S=3
backend/scripts/test_bre_analysis_type_b_tc.py 正式 tc 套件(ok=18):Type-B 3 站点分裂家系 r_B>0.5 且 n_common=0(复刻 tY-first rng 序 → 0.990+ 三 409
backend/scripts/test_bre_analysis_inbreeding_tc.py 正式 tc 套件(ok=44):近交衰退方向感知(衰退/无/上升)+ deep 系谱 F=0.125 + min_n insufficient + 422/409
backend/scripts/test_bre_analysis_trial_design_tc.py 正式 tc 套件(ok=25):增广(对照 block_no=None 不落库)+ α-格子(平方 λ≤1/非素数告警/一般贪心)+ block_no=rep*100+block DB 读回 + 四 409
backend/scripts/test_bre_analysis_stability_tc.py 正式 tc 套件(ok=16):AMMI/FW b 斜坡 + flag_stable + ASV rank + engine_version 落库 + year 维度 + 二 409
backend/tests/test_stat_analysis_tc.py pytest 包装层:9 套 tc @pytest.mark.pg + subprocess 串跑 + skipif 探测真实 PG16+Redisprotocol=2+ env 显式构建(剥 conftest 污染、解析 .env.dev、TC_CI_* 覆盖)
backend/pyproject.toml [tool.pytest.ini_options] 注册 pg marker(消 PytestUnknownMarkWarning
backend/tests/conftest.py collect_ignore_glob=["../scripts/test_*.py"] 防 pytest 收集独立脚本污染 sqlite 环境
run_ci.py 本机 CI stagestep 0 探测 PG16+Redis(失败指引+exit≠0)→ step 1 pytest -m pg → step 2 EXIT=0「CI 全绿」,日志 Temp/claude/ci_logs/
Temp/claude/backup_analysis_tc2_20260805/ 备份镜像(root/run_ci.py + backend/scripts 9 tc 套件 + backend/tests/test_stat_analysis_tc.py + pyproject/conftest diff

新增/修改文件(2026-08-05 O2O4 统计方法学广度,v2.29)

文件 说明
backend/scripts/breeding_stats/genomic.py ENGINE_VERSION 1.4.0solve_rrblup(岭回归逐标记 + marker effects + 对偶)+ solve_bayesbBayesB Gibbs,确定性 seed 可复现)+ kfold_cv_genomic dosage/markers 分派 rrblup/bayesb
backend/app/api/v1/module_bre/statistics/service.py _values_by_tree_env env_dim=stage 分支(coalesce(obs.stage, TraitModel.stage) 分组)+ run_type_b_heredity env_dim 校验扩 stage + run_gblup method 扩 rrblup/bayesb + seed 透传 + run_cv GS 分支 dosage/seed 透传 + _smith_hazel_index restricted 投影(Kempthorne-Nordskog 闭式解)/economic_weights + selection_index 透传 + cv_detailcv_result_id(顺手修复)+ _DATA_VERSION v2.29
backend/app/api/v1/module_bre/statistics/schema.py TypeBIn.env_dim 描述扩 stage + GblupRunIn/CvRunIn method 描述扩 rrblup/bayesb + seed + SelectionIndexIn.method 描述扩 restricted + restricted_traits/economic_weights
backend/app/api/v1/module_bre/statistics/controller.py run_gblup 透传 seed + selection_index 透传 restricted_traits/economic_weights
backend/app/api/v1/module_bre/genotype_call/service.py GENOTYPE_DATA_VERSION v2.29
frontend/web/src/views/module_bre/statistics/index.vue Type-B env_dim 下拉加 stage + GBLUP/CV method radio 加 RRBLUP/BayesB + seed 输入 + 指数页 restricted 单选/restricted_traits 多选/每性状经济权重输入 + SI_RES 结果表与警示
frontend/web/src/api/module_bre/statistics.ts selectionIndex/runGblup/runCv method 类型扩 + restricted_traits/economic_weights/seed
backend/scripts/test_bre_analysis_o234_tc.py 正式 tc 套件第 10 套(ok=41):O2 stage 幼成相关 / O3 rrblup+bayesb 落库与对偶可复现 / O4 restricted+economic
backend/tests/test_stat_analysis_tc.py TC_SCRIPTS 注册 ("o234", "test_bre_analysis_o234_tc.py")9 → 10 套)
Temp/claude/e2e_o234_20260805.py O2–O4 e2e 探针(19 断言,纯计算 golden + 真实 PG
Temp/claude/backup_o234_20260805/ 备份镜像(后端 service/schema/controller/genomic + 前端 vue/ts + tc + e2e

备份(无 git,批量编辑前手动镜像)

  • 2026-08-03 引擎改动 → Temp/claude/backup_gxe_20260803/
  • 2026-08-04 方向改动(13 文件,按相对路径镜像)→ Temp/claude/backup_direction_20260804/
  • 2026-08-04 规范文档 → Temp/claude/backup_docs_20260804/ + doc/桃育种系统模块扩展需求规格.v2.2.md(旧版本快照)
  • 2026-08-04 无性系级指数改动(controller/schema/service/statistics.ts/index.vue/e2e)→ Temp/claude/backup_clone_index_20260804/
  • 2026-08-04 配合力交配设计改动(13 文件,按模块相对路径镜像)→ Temp/claude/backup_combining_design_20260804/
  • 2026-08-04 统计严谨·MLOps 复现性改动(weld SQL×2 + statistics 三件套 + blup.py + rootstock 三件套 + 前端四文件 + 三探针)→ Temp/claude/backup_rigor_20260804/
  • 2026-08-04 组合得失漏斗改动(weld_combination_funnel.sql + statistics service/controller + e2e)→ Temp/claude/backup_combination_funnel_20260804/
  • 2026-08-04 分子育种改动(weld SQL + bre_menu.sql + module_bre 四模块五件套 + __init__.py + 前端四 api 四页面 + e2e)→ Temp/claude/backup_molecular_20260804/
  • 2026-08-04 精修项四连发改动(DUS 模块六件套 + statistics 四件套 + blup.py + weld/种子/菜单 SQL×3 + 前端 dus/statistics 两页两 api + e2e_refine)→ Temp/claude/backup_refine_20260804/
  • 2026-08-04 六项能力完善改动(weld_advanced.sql + statistics 四件套 + dus 六件套 + trait_observation 三件套 + mtblup/genomic/stability/fdist/blup 求解器 + 前端 statistics/dus/tree_evaluation 三页四 api(含 trait_observation.ts+ 六探针 + 文档四件,37 文件)→ Temp/claude/backup_advanced_20260804/
  • 2026-08-04 砧木×接穗随机互作改动(blup.py + statistics 三件套 + 前端 statistics.ts/index.vue + e2e_gxr)→ Temp/claude/backup_gxr_20260804/
  • 2026-08-04 基因组选择实证严谨性改动(genomic.py + statistics 三件套 + 前端 statistics.ts/index.vue + e2e_gblup_cv + 文档三件)→ Temp/claude/backup_gblup_cv_20260804/
  • 2026-08-04 现代桃育种领域覆盖改动(germplasm 三件套 + cross_combination 二件套 + bre_disease_chilling_traits.sql + 前端 germplasm/cross_combination 两页 + germplasm.ts + e2e_s_allele + 文档三件 + 规格快照 v2.13)→ Temp/claude/backup_s_allele_traits_20260804/
  • 2026-08-04 GWAS/QTL/MAS 闭环改动(gwas.py + weld_gwas.sql + statistics 四件套 + bre_menu.sql + 前端 gwas.ts/index.vue + e2e_gwas + 文档三件 + 规格快照 v2.14)→ Temp/claude/backup_gwas_20260804/
  • 2026-08-04 九缺口补齐改动(blup/gwas/genomic + statistics 四件套 + genotype_call + weld_mas_semantics.sql + 前端 statistics/gwas 两页两 ts + e2e×3 + 文档三件 + 规格快照 v2.15)→ Temp/claude/backup_complete_20260804/
  • 2026-08-05 十二项真缺口补齐改动(批1 blup/mtblup/gwas 引擎 + statistics;批2 field_operation/observation/breeding_report/analysis_dataset 四模块五件套 + 前端四页四 ts;批3 audit/alert/brapi/sequence 模块 + number_gen + ap_scheduler + backup_job + pg_backup/pg_restore.sh + init_app + weld SQL 多枚 + 前端 alert 页/statisticse2e×3 + 文档三件 + 规格快照 v2.16)→ Temp/claude/backup_gaps3_20260804/
  • 2026-08-05 桃育种业务流全面完善改动(批A field_operation/observation/seed_lot/seed_treatment/tree/trait_observation + weld_busflow.sql + bre_yield_phenology_traits.sql;批B statistics service/controller/schema/model + bre_type_b_result;批C echarts.ts + statistics/observation/field_operation 三 ts + statistics/observation/field_operation/stage_phenotype/StageView 五 vuee2e×2 + smoke + 文档三件 + 规格快照 v2.17)→ Temp/claude/backup_busflow3_20260805/
  • 2026-08-05 世代闭环改动(selection_result/service.py 晋级落谱 + 探针)→ Temp/claude/backup_pedigree_closure_20260805/
  • 2026-08-05 近交惩罚静默关闭修复改动(statistics/service.py 亲缘多源解析 + 探针)→ Temp/claude/backup_kinship_20260805/
  • 2026-08-05 EBV 回退方法学修复改动(statistics/service.py 打分降权 + 探针)→ Temp/claude/backup_ebv_20260805/
  • 2026-08-05 数据质量离群值方向语义修复改动(statistics/service.py 方向分流 + 前端 statistics/index.vue 双表 + A6 探针 + 文档三件 + 规格快照 v2.20)→ Temp/claude/backup_dq_semantics_20260805/
  • 2026-08-05 ΔG 投影假设 + 工程健壮性打磨改动(statistics/service.py note 假设 + spatial 降级 + numpy 收敛向量化 + 前端 statistics/index.vue gain alert + spatial/A6 探针 + 文档三件 + 规格快照 v2.21)→ Temp/claude/backup_dq_robust_20260805/
  • 2026-08-05 回归基建改动(run_regression.py + backend/scripts 4 tc 套件,无后端代码改动)→ Temp/claude/backup_test_rigor_20260805/
  • 2026-08-05 AF 六项缺口·批1 父本验证 + 近交衰退改动(pollination/tree/cross_combination service + tree schema + statistics 三件套 + 前端 statistics.ts/index.vue + e2e×2 + 文档三件 + 规格快照 v2.22)→ Temp/claude/backup_parent_validation_20260805/
  • 2026-08-05 AF 六项缺口·批2 GS 家系 CV + 试验设计深度改动(genomic.py + anova.py + statistics 三件套 + trial_study_entry model + weld_trial_study_entry.sql + 前端 statistics.ts/index.vue + e2e×2 + 文档三件 + 规格快照 v2.23)→ Temp/claude/backup_gs_family_trial_design_20260805/
  • 2026-08-05 AF 六项缺口·批3 OCS + MABC 改动(statistics service/controller/schema 三件套 _candidate_ebv_map 抽取 + ocs + mabc_progress + 前端 statistics.ts/index.vue OCS 运行区 + MABC tab + e2e×2 + 文档三件 + 规格快照 v2.24)→ Temp/claude/backup_ocs_mabc_20260805/
  • 2026-08-05 近交衰退正确性修复改动(statistics/service.py 方向感知 + 深层系谱 + 前端 statistics/index.vue 提示文案 + e2e_inbreeding_depression 扩展 + 文档二件 规格/实施记录)→ Temp/claude/backup_inbreeding_fix_20260805/
  • 2026-08-05 分子亲本验证 + 试验设计深度·批4 改动(genotype_call 二件套 mendelian_check + statistics 三件套 trial_design augmented/alpha 分派 + 前端 genotype_call/statistics 两页两 ts + e2e×2 + 文档三件 规格/实施记录/对照总表,14 文件按相对路径镜像)→ Temp/claude/backup_mendelian_design_20260805/
  • 2026-08-05 批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验改动(blup.py + statistics 四件套 + genotype_call 三件套 + tree/model.py + 前端 statistics/genotype_call 两页两 ts + 三探针 + 文档三件,18 文件按相对路径镜像)→ Temp/claude/backup_block_mendelian_numerics_20260805/
  • 2026-08-05 批6 规划↔目标↔试验 可追溯性闭环改动(weld_plan_trace.sql + target 三件套 + trial 三件套 + plan 二件套 + 前端 plan/target/trial 三页三 ts + 新探针 e2e_plan_trace + 文档三件,按相对路径镜像)→ Temp/claude/backup_plan_trace_20260805/
  • 2026-08-05 批7 系谱键空间错位修复改动(statistics/service.py _tree_individual_keys + 四调用点 + genotype_call/service.py 版本 + 新探针 e2e_rg_golden + http_v228 + 版本断言探针×4 + 文档三件,按相对路径镜像)→ Temp/claude/backup_keyspace_20260805/

复跑验证

# 后端(GBK 控制台需 UTF-8worship() ASCII 画报会崩)
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python main.py run --env=dev

# 探针(真引擎 + spy 捕获 kwargs / 真引擎直跑)
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxe_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_direction_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_clone_index_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_combining_design_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_rootstock_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_combination_funnel_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py

# 砧木×接穗随机互作(G×R)探针(真引擎直跑,运行后自动清理):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py

# 基因组选择(GS)专用 k-fold CV 探针(真引擎直跑,运行后自动清理)+ GBLUP 回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py

# GWAS/QTL/MAS 闭环探针(真引擎直跑 7 段断言,运行后自动清理)+ GBLUP/ssGBLUP 回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py

# 九缺口补齐三探针(真引擎直跑,运行后自动清理):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py

# 九缺口补齐:MAS 面板语义三列(幂等,可重跑):
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_mas_semantics.sql

# 组合得失漏斗视图(幂等,可重跑):
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_combination_funnel.sql
# 精修项三 SQL(幂等,可重跑;bre_dus_seed 依赖 bre_dus_descriptor 已由 create_all 建出):
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_refine.sql
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_dus_seed.sql
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_menu_refine.sql
# 六项能力完善:weld_advanced(幂等,2 表 + 2 列 + 1 jsonb;新表 bre_genetic_corr_result/bre_stability_result 由 create_all 建出):
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_advanced.sql
# GWAS/QTL/MASweld_gwas(幂等,5 新表 bre_gwas_result/bre_gwas_snp/bre_qtl/bre_mas_panel/bre_mas_panel_marker 兜底;正常已由 create_all 建出)+ 900214 菜单翻转:
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_gwas.sql
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/bre_menu.sql
# 六探针(真引擎直跑,运行后自动清理):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_stability.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_stage.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mtblup.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_dus.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mlops.py
# 十二项真缺口:批1/批2/批3 探针(真引擎直跑,运行后自动清理)+ 全量回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
# 桃育种业务流全面完善:批A/批B 探针(真引擎直跑,运行后自动清理)+ 批C HTTP smoke + 全量回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/smoke_busflow_c_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_refine_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py
# 世代闭环:晋级落谱探针(真引擎直跑 11 组断言,运行后自动清理)+ 晋级主线回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_pedigree_closure_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py

# 近交惩罚静默关闭修复:亲缘多源解析探针(真引擎直跑 14 组断言,运行后自动清理)+ A6 亲缘回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py

# EBV 回退方法学修复:direct 优先/子代测验降权/双侧去重探针(真引擎直跑 5 组断言,运行后自动清理)+ 亲缘/批次回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py

# 数据质量离群值方向语义修复:A6 探针(真引擎直跑,运行后自动清理)+ 回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py

# ΔG 投影假设 + 工程健壮性打磨:spatial 降级场景探针(真引擎直跑,运行后自动清理)+ A6 note 断言 + 回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py

# A–F 六项缺口·批1 父本验证 + 近交衰退:双探针(真引擎直跑,运行后自动清理)+ 全量回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_data_mating_gain_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py

# A–F 六项缺口·批2 GS 家系 CV + 试验设计深度:双探针(真引擎直跑,运行后自动清理)+ 全量回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py

# AF 六项缺口·批3 OCS + MABC:双探针(真引擎直跑,运行后自动清理)+ 全量回归(含 _candidate_ebv_map 抽取后 mating/audit 双核对):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_busflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_b8_seed_lot.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_audit_fix_20260805.py

# 近交衰退正确性修复(6 组断言:方向感知 asc 病指 + 深层系谱多世代 F)+ 全量回归(13 套):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py

# A–F 六项缺口·批4 分子亲本验证 + 试验设计深度:双探针(真引擎直跑,运行后自动清理)+ 全量回归(rcbd 路径零变化 + 13 套):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_check_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_ext_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py

批5 区组随机效应 + 孟德尔落库隔离 + 统计引擎数值校验:三探针(真引擎直跑,运行后自动清理)+ 27 套全量回归(含 gxe/gxr/mendelian_check/trial_design 零变化):

PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ablup_block_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_stats_numerics_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_check_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_trial_design_ext_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxe_20260803.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gxr_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_molrigor_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gwas_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_kinship_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mating_ebv_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gblup_cv_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gs_family_cv_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_batch_selection_20260803.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_ocs_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mabc_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_base_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_engines_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_gaps_modules_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_inbreeding_depression_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_parent_validation_20260805.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_gblup.py PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_corr_spatial_20260804.py


# 批6 规划↔目标↔试验 可追溯性闭环:新探针(真引擎直跑 17 断言,运行后自动清理)+ weld SQL(幂等,可重跑)+ 全量回归:
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_plan_trace_20260805.py
PGPASSWORD=dpb psql -h localhost -p 5432 -U dpb -d dpb -w -f backend/sql/weld_plan_trace.sql
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_plan_trace_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_audit_20260805.py

# 批7 统计引擎十模块 golden 复查·系谱键空间错位修复:新探针(真引擎直跑 21 断言,运行后自动清理)+ 回归(版本断言已同步 v2.28):
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_rg_golden_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_advanced_mtblup.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_statsflow_20260805.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_spatial_sparse_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_prediction_rigor_20260804.py
PYTHONIOENCODING=utf-8 ENVIRONMENT=dev PYTHONPATH=backend python Temp/claude/e2e_mendelian_persist_20260805.py

科学正确性收口:方向标注后,低优性状(裂果率/病害级别/酸度等 asc)在指数、EBV 排行、决策预览、轮次对比中一律按"越小越优"参与,与育种目标语义一致;Smith-Hazel 的 b 符号、加权 Z 的贡献方向均按 direction 归一,不再存在"高 EBV=优"的隐含假设。可追溯性收口bre_plan 不再孤立——plan→target→cross_combination→tree(目标链)与 plan→trial→trial_study→tree(试验链)双链闭合,GET /bre/plan/trace/{id} 一查到底;三 FK 均可空,存量孤目标/独立试验不受影响,新数据挂链即可查(渐进式,不强制回填)。

18.21 前端 TAB 陈旧数据修复:KeepAlive 切回自动重拉真实数据(2026-08-05,前端框架级,无版本变更)

用户反馈:授粉管理、花粉档案等「第2、3个 TAB」页面,切换过来后列表仍是旧数据,点刷新才变真实数据。根因:fa-page-content 默认 KeepAlive 缓存页面,切换 workbar 标签时组件不重新 mounted → onMounted 不重跑 → 列表停留旧快照。框架级修复(覆盖全部 useTable 页面,而非逐页打补丁)。

根因链(两层):① hooks/core/useTable.tsonActivated 只置 tableViewActive=truefetch 内 guard 防失活期拉数据),从不主动重拉;onDeactivatedcancelRequest()。KeepAlive 切回 → data.value 仍是旧快照。约 30 个 module_bre CRUD 页共用 useTable,仅 3 页有手动 onActivatedtree 的 refreshData()、pollination/pollen 的下拉重载),故框架层修一处全覆盖。② 跨实例去重键不含 API 身份globalListNetworkInflight 的 dedupeKey 仅由 stableDedupeKeyFromParams(requestParams) 生成(跳过 undefined 字段),而所有 module_bre 列表页默认参数形状相同({page_no:1, page_size:10})→ 硬刷新后多个 tab 并发挂载,各页 onMounted 并发发请求,页面 A 复用页面 B 的 in-flight 响应(字段与 prop 不匹配 → 列表只剩序号列有值,其它列空;这正是用户硬刷新后看到的"只有序号列")。点刷新(refreshData)时该 key 已无 in-flight,走自己的 HTTP → 正常。此 bug 既存,但激活重拉后并发概率骤增而被暴露。

改动

  1. frontend/web/src/hooks/core/useTable.ts:新增 tableActivatedOnce 标志;onActivated 首次(与 mounted 重合)跳过,之后每次恢复激活 → debouncedGetDataByPage.cancel() + clearCache(CLEAR_CURRENT, "恢复激活刷新") + getData()(强制 HTTP 重拉,in-flight 去重仍生效)。守卫 (immediate || data.value.length > 0) 保持 immediate:false 页面(cronjob 定时页)"不自动加载"语义不变。另修去重键:新增 apiIdentity = apiFn.toString()dedupeKey = \${apiIdentity}::${stableDedupeKeyFromParams(requestParams)}`——跨实例去重仅在**同一接口**间合并,不同页面的同形参数不再错配(globalListNetworkInflight` Map 全局共享,两处 in-flight key 均带上接口身份)。
  2. frontend/web/src/views/module_bre/statistics/index.vue:抽取 refreshPageLists()onMounted 全部 15 个 load 调用),onActivatedpageActivatedOnce 守卫后续激活重载(统计页多数据区整体刷新)。
  3. frontend/web/src/views/module_bre/pollination/index.vueonActivated 重载 5 个下拉(cross_combination/plot/personnel/tree/pollen 选项),表格由框架处理。
  4. frontend/web/src/views/module_bre/pollen/index.vueonActivated 重载采集父本树下拉。
  5. frontend/web/src/views/module_bre/tree/index.vue:移除冗余手动 onActivated(() => refreshData())(由 useTable 框架覆盖,避免双重重拉)。

验证vue-tsc EXIT=0(无类型回归);vite dev:5666base /web)热更新模块均 200 + 关键字符串存在;后端 /bre/pollination/list 实测返回字段完整(combination_name/pollination_date 等有值,确认非后端问题);浏览器行为需硬刷新(Ctrl+Shift+R,重建 KeepAlive 缓存与 HMR 旧实例)后实跑确认。备份镜像 Temp/claude/backup_tab_stale_20260805/

18.22 O1 花期数据消费补强:结构化花期区间 + 配对花期软警示 + 授粉窗口规划(2026-08-06v2.30

用户反馈 O1 花期字段(flowering_period 5 档字典)零消费属真实数据盲点,但定性为 P1 数据消费补强 + 辅助信息(非与 S-等位同量级的正确性硬防呆)。拍板三个落地档位:① 花期数据建模升级(结构化区间,前置);② mating_recommend 返回体加花期重叠软警示(重叠/错开/需采粉贮藏,不硬阻断);③ 授粉窗口规划消费 bre_pollen(新端点 GET /bre/pollen/window-plan)。花期建模新增列 → _DATA_VERSION v2.29 → v2.30

① 花期建模升级(germplasm 双 Date 列)bre_germplasm 新增 bloom_start_date/bloom_end_date(Date 可空,年际重复物候——比较/投影时取月日、忽略年份;flowering_period 5 档字典保留作粗粒度 fallback)。weld 幂等 SQLbackend/sql/weld_flowering.sql)+ 双处版本 bump。连锁全链:model.py / schemaCreate+Update/ serviceexport mapping_dict + import header_dict + fields 解析 + 模板 header_list/ 前端 germplasm 表单两个 date-picker、表格列、详情项。前端设计取舍useCrudForm 无提交前 transform hook → 弃 daterange(需 bloomStartRange↔两字段双向映射),改用两个独立 date 字段直绑 bloom_start_date/bloom_end_date(与 acquisition_date 同模式,零转换)。

② mating_recommend 花期软警示:新模块级 helper _bloom_overlap(female, male)statistics/service.py_md() 月日→年序日 1..366)——优先结构化区间(月日年际比较),缺区间 fallback 到 _BLOOM_TIER_ORDER 5 档字典序号(相邻/同档视为重叠)。四态返回 (status, msg)overlap「花期重叠,可同期授粉」/ store「父本先开花,需采粉贮藏至母本花期授粉」(me_d < fs_d/ offset「母本先开花,父本花期在后,注意母本柱头可授期」(fe_d < ms_d/ unknown「花期未知(缺结构化区间与档位)」。pairs 循环(female=gs[i], male=gs[j] 语义)在 s_compat 旁加 bloom_status/bloom_msg;非重叠三态追加进 flags[](前端红色 tag 自动渲染),overlap 不进 flags——软警示不硬阻断。前端 pairs 表加「花期」列(重叠=success tag / 需采粉贮藏·错开=warning tag / 未知=info tag)。

③ 授粉窗口规划(window-plan:新端点 GET /bre/pollen/window-plan?window_start=&window_end=controller + service.window_plan,纯计算不落库)。_project_bloom(g, ref_year) 把花期投影到窗口起始年:结构化区间按年际月日(桃花期 3-4 月单年窗口假设),缺区间 fallback _BLOOM_TIER_SPAN(5 档 → 代表区间,粗粒度标注)。花期种质给花粉覆盖三态 covered(整段有批次 collect<=bs and expiry>=be/partial/none(无覆盖 → n_need_pollen + 提示需采粉贮藏或同期授粉);库存侧给批次窗口状态 full(全程覆盖)/expiring(窗口内到期)/entering(窗口内采集、有效期出窗)/expired(窗口前失效)/not_started(窗口后采集)。窗口反向 409。前端 pollen 页顶部「授粉窗口规划」卡片:daterange 默认本年度/次年花期(3-4 月在当年、否则次年 03-01~04-30+ 生成按钮 + 缺粉 alert + 花期覆盖表 + 库存状态表;pollen.ts 加 getWindowPlan + PollenWindowPlan/PollenBloomItem/PollenInventoryItem/PollenLotRef 类型。

验证e2e_o1_bloom_20260805.py 探针全过——① CreateSchema→CRUD 双 Date 列落库;② 6 种质 15 对(重叠/错开/需采粉贮藏三类 + 档位 fallback mid×very_early→store + 区间×档位混合对→unknown,flags 仅非重叠进警示);③ 窗口 A(03-0504-08)花期覆盖三态 covered/partial/none + 档位投影种质、窗口 B03-1003-30)库存五态 full/expiring/entering/expired/not_started + 窗口反向 409。vue-tsc EXIT=0。全量回归 + run_ci.py EXIT=0 零回归。版本连锁:4 e2e 探针(statsflow/spatial_sparse×2/prediction_rigor/mendelian_persist+ o234 tc 断言 v2.29→v2.30。备份镜像 Temp/claude/backup_o1_bloom_20260805/