리뷰가 잡은 것 중 무거운 둘.
1. 테스트가 한 방향으로만 샜다. `REC_MIN_WIDTH` 를 100 으로 올려도 통과했다
— 앞의 두 단언은 상수가 커질수록 더 잘 통과하기 때문이다(가드가 더 많이
잡아 주고, 세션은 폭이 클수록 잘 돈다). 그 상태면 높이 48 기준 폭 100
미만 크롭, 즉 글자 한두 개짜리 박스가 전부 조용히 버려진다. 이 PR 이
없애려는 손실과 같은 종류다. 상수 옆에 `const _: () = assert!(REC_MIN_WIDTH
<= 16, …)` 를 걸어 컴파일 자체를 막는다 — 상수를 만지는 사람이 테스트를
돌리기 전에 걸리는 편이 낫다. 상한 16 은 "5~16 은 잉크가 있어도 빈 문자열,
40 은 제대로 읽음" 실측에서 온 수다. 상수 주석의 "pins both sides" 도
사실이 아니었으므로 함께 고쳤다.
2. 캐스케이드 비용 분석이 절반이었다. `id_for_doc` 이 접는 건 composite 가
아니라 base PARSER_VERSION 이라 이 bump 는 모든 이미지·PDF 문서의 doc_id 를
바꾸고, `purge_workspace_path_for_parser_bump` 로 store 를 통째로 다시 쓴다.
게다가 기본 엔진이 `ollama-vision` 이고 OCR 이 기본 off 라 버그가 닿지 않는
KB 도 같은 비용을 낸다. 엔진 범위로 좁히는 대안(`ocr_engine_version_for_sig`
전용 토큰)이 더 정확하지만, #232 선례 옆에 두 번째 무효화 경로를 만드는
값이 단일 사용자 저장소에서는 이득보다 크다고 보고 base bump 를 유지했다.
빠져 있던 비용과 이 판단 근거를 HOTFIXES 에 적었다.
나머지:
- 테스트가 `ModelPaths::from_default_dir()` 을 써서 `KEBAB_IMAGE_OCR_MODEL_DIR`
를 탔다. 상수를 배포되는 모델에 붙들어 두는 게 목적이므로 `CARGO_MANIFEST_DIR`
에서 경로를 직접 만든다.
- PDF OCR 실패 노트가 `err={}` 라 anyhow 의 가장 바깥 context(`rec session run`)
만 남고 ORT 원인이 잘렸다. 이슈가 안내한 `provenance_json LIKE '%Invalid input
shape%'` 가 PDF 문서를 한 건도 못 찾는 원인이다. `{e:#}` 로 이미지 경로와
형식을 맞췄다.
- `ingest.rs` 주석 4곳이 옛 버전을 현재형으로 말했다 (#232 가 자기 bump 때
같은 자리를 갱신한 선례).
- `pdf_page_v1.rs` 테스트 픽스처의 하드코딩된 버전 문자열을 버전 중립으로.
`kebab-chunk` 는 §8 경계상 `kebab-parse-pdf` 를 import 할 수 없어 실제 버전을
넣으면 bump 마다 또 상한다.
- HOTFIXES: 이 커밋이 밀어 버린 줄 번호 참조 제거, 클래스 수 검사 논거를 약한
대로 정직하게 다시 씀(정적 그래프 메타데이터라 `from_paths` 로 옮길 수 있다),
따라갈 수 없는 `§3.4` 참조 정리, 내부 용어와 어색한 소제목 정리.
- DOGFOOD: §13.4 이미지 코퍼스를 실제 분류·장수로 채우고 §1.2 에 paddle-onnx
설정 + 시나리오 1.2.f. 240 은 파일 수이고 ingest 대상은 tif 를 뺀 239 라는
차이를 HOTFIXES 와 양쪽에 밝혔다.
- parse 컴포넌트 README: Image 에 빠져 있던 PARSER_VERSION 줄, "v1 유일 구현"
이라는 틀린 서술과 다이어그램에 없던 `OnnxPaddleOcr`.
검증: 워크스페이스 1301 passed / 0 failed, clippy -D warnings 경고 없음.
`run_rec` 과 상수는 240 장 측정 때와 바이트 동일 — 이번 변경은 컴파일 시점
단언과 테스트 본문뿐이라 36/240 → 0/240 결과는 그대로다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>