fix(plan): K00 按诊断词细分类目 + 低龄种植降位 + 「二期」正畸误吞 + 早矫措辞

分支主题(K00 focus category + 正畸映射)的一批年龄/诊断适配。核心是把召回「目标·X」
标签和话术的类目排序,从"只看 K 码 + 年龄"细到"看诊断原文词",纠三类线上误标。

── ① K00 大口袋按诊断词定方向(refineCategoriesForDiagnosis)──
K00「牙发育和萌出障碍」混着语义完全不同的病:乳牙滞留(要拔)/ 乳牙早失(管间隙)/
先天缺失(修复)/ 釉质发育不全(冠贴面)/ 萌出障碍(导萌),却共用固定序 [surgical,...]
→ focusCategory 恒为 surgical,给「乳牙早失」也打「目标·外科」(没牙可拔)。线上约 2800 条。
诊断码不动(还是 K00),只在同码内把最贴切类目提到首位。scenario 投影 name_zh、
signals 存 dxNameZh 快照,前端 ReasonLine 用同一函数复算,保证「目标·X」与本行首项一致。

── ② 低龄种植降位,边界与全仓另三处种植年龄闸统一为 ≤18 ──
recommendedCategoriesForAge 新增:age ≤ IMPLANT_LAST_AGE(18)时 implant 挪末位(只挪不删)。
 边界取 ≤18 而非 <18 —— 差一岁会自相矛盾:contraindication.feature.ts 是 age<=18 打
「种植禁忌」、potential-treatment 是 age>18 才产「潜在种植」。2026-07-27 生产实测:
恰好 18 岁有 1,299 条 plan、140 条 focusCategory=implant,若按 <18 判会在同一屏出现
「目标·种植」+ 画像「种植禁忌」。话术侧(fact-block / stable prompt)同步 ≤18。

── ③ planned 规则裸「二期」不再误吞正畸 ──
「正畸二期矫治」被 implant 规则的裸「二期」吞成种植(线上 陈芃霖 BJ0A094257)。
actual 侧的修法是收紧成「种植二期」,但 planned 侧种植二期普遍不带"种植"
(二期取模/二期手术/二期修复,prod 900+ 条),收紧会让它们掉进 _default 被丢。
改用位次:裸「二期」从 implant 主规则拆出、降到全表最末兜底 —— 带正畸词的先被
orthodontic 收走,其余纯「二期」仍落 implant,与修复前逐条一致。

── ④ 替牙期正畸措辞说「早期矫治」──
treatmentCategoryNameZhFor:age ≤ EARLY_ORTHO_MAX_AGE(12)时 orthodontic 显示「早期矫治」
(替牙期做的是一期干预,不是排齐恒牙列)。只改措辞不改类目,排除闸不受影响。

reason-signals schema 补 dxNameZh(nullable,旧 plan 无 → 回落原顺序,无回归)。
删 tests/tmp-jieya.spec.ts(纯 console.log 探针,无断言,不进仓库)。
测试 546 passed,两个 app tsc 干净。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Found errors in your .gitlab-ci.yml:

  • jobs:openapi-drift config contains unknown keys: rules
You can also test your .gitlab-ci.yml in the Lint
Status Job ID Name Coverage