# WB INS Font Fix + Bold-Stripping Disaster (2026-06-10) ## Problem Doro rejected 【修】青浦精神卫生-委托检验协议(修).docx: WB insertions displayed in wrong font. Terminal review passed 10 checks but missed basic font inconsistency. ## Root Cause `contract_docx_lib.py`'s `_ensure_rfonts_complete()` only filled hAnsi/cs, missing: 1. `w:eastAsia` — CJK falls back to docDefaults (Times New Roman vs 宋体) 2. `w:hint="eastAsia"` — required for CJK rendering priority 3. `w:sz` — not inherited inside `w:ins`; must be explicit ## Fix Applied (contract_docx_lib.py, 4 locations) ### 1. `_ensure_rfonts_complete()` — fill all 4 + hint ### 2. `_extract_formats()` — ensure sz on body_rpr/title_rpr ### 3. `tracked_replace()` — ensure sz on INS rpr ### 4. `tracked_replace()` — fallback for hint-only rFonts runs See previous version of this file for code details. ## CRITICAL: Bold-Stripping Disaster ### What happened First fix attempt: after noticing font issues, **batch-stripped ALL `` tags from all WB INS runs**. This destroyed the original bold formatting: - P19: 风险律师费条件(原文加粗)→ stripped → not bold ✗ - P18: 金额部分(原文加粗)→ stripped → not bold ✗ - P30: "如若违反,律师费将另行重新计付"(原文加粗)→ stripped → not bold ✗ Doro: **"要保持原文的格式不变"** ### Why it was wrong `tracked_replace` correctly inherits the original run's rPr INCLUDING bold. When the original text "在代理过程中..." was bold, the replacement text "风险律师费仅按..." SHOULD also be bold — that's correct format preservation. ### The rule - `tracked_replace` INS inherits original run's rPr → **leave it alone** - `add_clause` uses `_body_rpr` (no bold) or `_title_rpr` (bold) → **correct by design** - **NEVER post-process WB INS to strip/add formatting attributes globally** ### Correct validation approach Compare each WB INS run against the original run **in the same paragraph**, not against a global template. Use `scripts/wb-ins-font-verify.py` for document-agnostic validation. ## Verification Script `scripts/wb-ins-font-verify.py ` — per-paragraph comparison, checks rFonts/sz/hint, exit code 0=pass 1=fail. Document-agnostic (no hardcoded font names). ## Three font-source scenarios in tracked_replace 1. Run has explicit font names → `_ensure_rfonts_complete` fills gaps 2. Run has hint-only rFonts (no names) → fallback to `_body_rpr` font names 3. Run has no rPr at all → use `_body_rpr` directly