0036: HwpNativeLoader를 pyhwp-gated 기본값으로 승격
0036: HwpNativeLoader를 pyhwp-gated 기본값으로 승격
- Status: superseded by 0049
- Date: 2026-05-13
- Superseded: 2026-05-15 — pyhwp 0.1b15 API drift로 비공개 100-doc 실 eval에서
hwp_native_rate = 0.0기록 (paragraph-only 추출이 RFP가 의존하는 table/heading 구조 손실). ADR 0049가 pyhwp 백엔드를 kordoc(npm 서브프로세스)으로 교체하고csv_text를 무조건 fallback으로 유지. - Related: ADR 0001 (baseline 불변식),
ingestion.py:_resolve_loader(loader 라우팅), issue #167 (원본 spike), issue #363 (관측성), issue #365 (이 결정), issue #426 (구현)
TL;DR
- HwpNativeLoader가 env-var opt-in이라 한국어 RFP 사용자가 더 나은 파서를 발견 못 함 — pyhwp 설치 감지 시 기본값으로 승격.
BIDMATE_HWP_LOADER=csv를 명시적 opt-out, pyhwp 부재 시 CSV fallback 안전망 유지.- 추후 ADR 0049가 pyhwp 0.1b15 API drift로 인해 kordoc 백엔드로 교체.
배경
HwpNativeLoader (ingestion.py:L131)는 issue #167에서 BIDMATE_HWP_LOADER=native opt-in spike로 추가. Issue #363이 RuntimeWarning + last_fallback_reason 관측성을 추가한 후 fallback 경로가 측정 가능해졌다.
Pre-Phase-3 audit가 env-var 게이트를 “scaffold가 load-bearing이 됨”으로 플래그 — 테이블 구조 추출이 실제로 필요한 한국어 RFP 사용자는 env var를 명시적으로 설정해야 해 더 나은 파서가 기본적으로 invisible. with_tables=True 변형(BIDMATE_HWP_LOADER=native_tables, issue #506)이 이를 가중: 두 미발견 knob이 타깃 corpus의 critical path를 제어.
결정
_resolve_loader (구현은 issue #426 트래킹)가 importlib.util.find_spec("hwp5")로 pyhwp 가용성을 감지하고, 패키지 존재 시 HwpNativeLoader(with_tables=True)를 기본값. BIDMATE_HWP_LOADER=csv가 CSV only 경로 필요 환경의 명시적 opt-out.
Env-var precedence (높음 → 낮음):
BIDMATE_HWP_LOADER=csv→LOADERS["hwp"](CSV fallback, 명시적 opt-out)BIDMATE_HWP_LOADER=native→HwpNativeLoader(with_tables=False)(text-only native)BIDMATE_HWP_LOADER=native_tables→HwpNativeLoader(with_tables=True)(text + tables)- (unset 또는 empty) + pyhwp importable →
HwpNativeLoader(with_tables=True)← 새 기본값 - (unset 또는 empty) + pyhwp 부재 →
LOADERS["hwp"](무변; CI minimal 설치 안전)
HwpNativeLoader.load()가 이미 ImportError를 catch하고 RuntimeWarning과 함께 CSV text로 fallback하므로 case 5는 안전망이며 새 코드 경로 아님.
결과
쉬워진 점:
- pyhwp 설치된 한국어 RFP 사용자가 기본적으로 테이블 구조 획득 — env-var 문서 조회 불필요.
- 관측 가능한
last_fallback_reason필드(issue #363)가 env-var-never-set 케이스가 아닌 실제 pyhwp 실패를 surface해 유용한 signal이 됨. BIDMATE_HWP_LOADER=csv가 발견 가능한, 문서화된 opt-out이지 invisible default 아님.
어려워진 점 / 제약:
- pyhwp가 문서화된 optional 의존성;
requirements-dev.txt또는 별도requirements-hwp.txt가 선언해 기여자가 opt-in 가능해야. - pyhwp 없는 CI smoke/test 실행이 case 5 (CSV fallback) cover해 import-detection 회귀 catch. 기존
EMBEDDING_BACKEND=hashingminimal 설치가 이미 충족. - ADR 0001 naive-baseline 불변식 보존:
naive_baselineeval preset이 HWP 파일을 로드 안 함; loader 기본값 변경이 eval bit-stability에 무영향.
재오픈(Re-open) 조건:
BIDMATE_HWP_LOADER unset으로 1회 make real-eval cycle 후 비공개 100-doc corpus에서 native-loader fallback rate가 20% 초과면 기본값 또는 pyhwp 감지 로직 재검토.
검토한 대안
- 옵션 1 — 폐기(Deprecate): 한국어 RFP 사용자에게서 테이블 추출 capability 제거 — 사용 측정 없이 시기상조. pyhwp가 이미 동작하는데 premature.
- 옵션 3 — visual_ingestion v2에 통합: 올바른 장기 seam이나
visual_ingestion.pyv2가 아직 미scoped. 이 결정을 phase-3 리팩토링에 블로킹하면 발견 가능성 수정이 무기한 지연. - 옵션 4 — 유지 + 관측(Keep + Observe): status quo env-var 게이트. Issue #363 landed 후 관측성이 측정 가능. 추가 deferral은 증거 축적이지만 더 나은 파서를 또 한 eval cycle invisible 유지.