2.5 KiB
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:
w:eastAsia— CJK falls back to docDefaults (Times New Roman vs 宋体)w:hint="eastAsia"— required for CJK rendering priorityw:sz— not inherited insidew: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 <w:b/> 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_replaceINS inherits original run's rPr → leave it aloneadd_clauseuses_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 <docx> — 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
- Run has explicit font names →
_ensure_rfonts_completefills gaps - Run has hint-only rFonts (no names) → fallback to
_body_rprfont names - Run has no rPr at all → use
_body_rprdirectly