FE↔后端联调实测暴露并修复: 1. 问卷键名三处错位(FE height_cm/weight_kg/psych_style vs 文档 height/weight/psyche_style)——vision._bmi 多键取值、diagnosis 维度 装配与规则上下文双键或运算,两侧谁改键名都不再炸 2. celery worker asyncio.run 每投递起新 loop + 模块级引擎缓存 → asyncpg 连接跨 loop(同进程第 3 个报告任务必现 RuntimeError: attached to a different loop;集成测试单循环掩盖)。新增 apps/worker/loop.py 持久 loop,report/ping 两任务接入 E2E 终态: psyche_style/height_weight 恢复、BMI 体型确定值、ok 26/32、 真实 LLM 文案通过校验 degraded=False。
dimensions.py 逐行编码需求文档 §4(32 项四要素、缺失显式 skipped)+ VisionProvider 接口位与确定性实现 + 规则引擎联动 rule_hits(T-P3-01/06)。 实现: - dimensions.py:DimensionSpec 恰 32 项(number 1~32 连续,33/34 永不复用), basic_coverage 口径机器可读:full 10 / label 3 / partial 8 / none 11, 初级覆盖 21/32(BASIC_FULL_KEYS + BASIC_COVERED_KEYS)。 - vision.py:VisionProvider Protocol(派生特征形状写进 docstring,真实 RTMPose/BiRefNet 实现后续按此替换)+ DeterministicVisionProvider(问卷 BMI/自评驱动体型与肤色,sha256(object_key+canonical问卷) 驱动其余枚举, 同输入同输出)+ build_vision_provider(未知名 CONFIG_ERROR)。 - vision_stage.py:derived_features 已存在 → skipped/reused(T-P3-09); 否则分析 → 写中间态并 flush;photo_meta.quality_flags 透传进产物(T-P3-01)。 - diagnosis_stage.py:32 维恒全键,缺输入显式 skipped+原因(T-P3-06 红线); 每维四要素 value/confidence/source/evidence/rule_hits + status;构造 RuleContext → RuleService 载入 published 规则 → evaluate,body_shape/color 类命中回落 #5/#19/#21,全量命中聚合进 #28/#30 的 rule_hits 与 evidence; 色板 #19/#20/#21 从 kb_color 按季型读取,库空 → skipped「色板未录入」。 测试:单测 29 项(32 项完整性/编号连续/确定性/工厂拒绝未知名;四要素齐全 性——故意缺问卷+缺视觉断言 32 键全在且全部 skipped 带原因;规则命中进 rule_hits 用内置最小规则集不连库);集成 1 项(种 2 条 published 规则 → VisionStage → DiagnosisStage:中间态落库与复用 skipped/reused、32 维全键、 rule_hits 出现、kb_color 空时色板 skipped、coverage basic_full=10/32)。 全绿:ruff check/format、mypy packages/report、lint-imports;单测 536 通过 (3 处既有 skip)、集成 46 通过。 偏差说明: 1. 任务文档写 RulesService,实际类名为 RuleService(packages/rules/service.py),按实际代码调用。 2. kb_color 联表键采用四季代码 spring/summer/autumn/winter(仓库无既定口径),已在 vision.py 注释声明。 3. 任务文档只给 basic_coverage 四枚举,需求表格中的「粗判/8色/3色」归入 partial、「Top1」归入 label。