Skip to content

v0.3.0 — Document IR v1.1 + rhwp-py CLI#5

Merged
DanMeon merged 18 commits into
mainfrom
feature/v0.3.0
Apr 28, 2026
Merged

v0.3.0 — Document IR v1.1 + rhwp-py CLI#5
DanMeon merged 18 commits into
mainfrom
feature/v0.3.0

Conversation

@DanMeon
Copy link
Copy Markdown
Owner

@DanMeon DanMeon commented Apr 28, 2026

Summary

Phase 2 두 축 동시 GA — v0.2.0 의 Document IR v1.0 위에 HWP 고유 의미 요소 8 종을 추가하고 (SchemaVersion 1.1), 동시에 Python 고유 가치 (IR / LangChain 청크 / 스키마 export) 를 shell 에서 직접 소비할 수 있는 rhwp-py CLI 를 재도입.

Document IR v1.1 — 8 신규 블록 + Furniture 채움

  • PictureBlock / FormulaBlock / FootnoteBlock / EndnoteBlock / ListItemBlock / CaptionBlock / TocBlock (+ TocEntryBlock) / FieldBlock
  • furniture.page_headers / page_footers / footnotes / endnotes 모두 실제 본문 출고
  • SchemaVersion 1.01.1 (in-place v1 URL, content-addressed alias 발행)

rhwp-py CLI 재도입

  • 서브커맨드: parse / version / schema / ir / blocks / chunks
  • blocks --kind enum 11 종 — IR 확장 GA 와 동기
  • chunks --include-furniture — RAG body/furniture 분리 색인
  • 새 extras: [cli] (typer 만), [cli-chunks] (typer + langchain-text-splitters)
  • 상류 Rust rhwp 바이너리와 PATH 충돌 회피 + 기능 overlap 0

LangChain HwpLoader.include_furniture — body 다음 furniture Document 도 yield (metadata.scope="furniture")

기타 cleanup

  • aparse 가 stdlib asyncio.to_thread 사용 — aiofiles 의존성 제거 (의미·성능 동등)
  • 문서 컨벤션 정합성 정리 — 업스트림 monorepo 잔재 (pyo3-bindings.md 등) 제거 + docs/upstream/ 정책 등재 + Archive 정책 (v1.0+) 도입
  • .claude/hooks/docs-lint.py — PostToolUse hook 으로 docs/*.md 자동 검증 (Status 헤더 / monorepo 잔재 / cross-link / broken link)

Why

  • RAG / LLM 파이프라인 사용자: v0.2.0 IR 의 UnknownBlock 폴백 영역 (그림 / 수식 / 각주 / 목록 / 캡션 / 목차 / 필드) 을 first-class 로 노출 — 검색 정확도 + 출처 역추적 가능
  • Shell 사용자: pip install "rhwp-python[cli]" 만으로 vector indexer 파이프라인에 rhwp-py blocks --format ndjson | jq ... / rhwp-py chunks --size 1000 --format ndjson 직접 결합
  • v0.2.0 호환: 모든 공개 API 보존, 추가만 — 기존 코드는 그대로 동작 (UnknownBlock 폴백 + extra="forbid" 정책 상 furniture.endnotes 신규 키만 schema_version 분기 필요, 본문에 명시)
  • 외부 의존 최소화: aiofiles 제거로 [async] extras 가 빈 배열로 정리 (v0.4.0 에서 키 자체 제거 검토)

Related Issues

Test plan

  • uv run pytest -m "not slow"430 passed (S2 291 → S3 405 → S4 신규 24 + smoke 1, 2 skipped 샘플 부재)
  • uv run pyright python/ tests/<scoped> — 0 errors
  • cargo clippy --all-targets -- -D warnings — clean
  • Schema regenerate diff — no diff (1,261 lines / 20 $defs)
  • CLI smoke — 6 서브커맨드 모두 노출, ndjson/json/text 포맷 검증, exit code 1/2 검증
  • code-reviewer fresh-context 검증 — Critical 0 / Major 3 / Minor 5 / Nit 3 모든 fix 적용
  • Cargo.toml 0.2.00.3.0 bump — publish.yml verify-version 통과 준비
  • (사용자) 실제 HWP 3종 (일반 / 장문 / HWPX) 으로 examples + rhwp-py {parse,blocks,chunks,schema} 출력 육안 검증
  • (머지 후) GitHub Release v0.3.0 publish → publish.yml PyPI 배포 + publish-schema.yml schema alias 발행

🤖 Generated with Claude Code

DanMeon and others added 12 commits April 26, 2026 18:54
변경사항:
- PictureBlock + ImageRef Pydantic 모델 도입 + Block 유니온/_KNOWN_KINDS 확장
- Document.bytes_for_image(picture) 헬퍼 — bin:// URI → raw bytes (5단계 fail-fast 검증)
- furniture.page_headers/page_footers 채움 — Control::Header/Footer + master pages walk
- SchemaVersion 1.0 → 1.1, hwp_ir_v1.json 재생성 ($defs 10→12)
- Rust ir.rs: RawPicture/RawImageRef 구조체 + picture walker + lookup_bin_data_bytes
- mapper: ext→mime 12종 매핑 + _flatten_paragraph 가 pictures 도 emit
- LangChain HwpLoader: PictureBlock 분기 (description→content, image_uri/mime→meta)
- 신규 테스트 51개 (test_ir_picture.py + test_ir_furniture.py)
- 기존 테스트 갱신: schema_version 1.1, PictureBlock 알려진 kind 추가
- CI scoped pyright 목록에 신규 테스트 파일 2개 추가
- docs/implementation/v0.3.0/stages/stage-1.md (신규) + roadmap README 인덱스

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- FormulaBlock / FootnoteBlock / EndnoteBlock 모델 추가, _KNOWN_KINDS 6 종 확장
- Furniture.endnotes 신규 + footnotes 타입 list[FootnoteBlock] 강화 + iter_blocks/walk 재귀 경로 확장
- Rust ir.rs walker 가 Control::Equation/Footnote/Endnote 추출 — FurnitureAcc 누적 struct 도입
- simple_eq_text_alt 토큰 경계 인식으로 재작성 — naive String::replace 가 sqrtish/discover 같은 식별자 부분 매치하던 약점 정정
- LangChain loader _block_to_content_and_meta 가 새 3 종 블록 분기 처리 (text_alt, marker_prov 메타)
- JSON Schema hwp_ir_v1.json 재생성 (12 → 15 $defs)
- 테스트 — test_ir_formula.py / test_ir_footnote.py 신규 (44 케이스), Rust unit 7 건 (토큰 경계), 기존 7 개 갱신
- stage-2.md + CI pyright scope 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- 5 신규 Pydantic 모델: ListItemBlock / CaptionBlock / TocBlock+TocEntryBlock / FieldBlock (+ FieldKind 닫힌 Literal 14+unknown)
- PictureBlock.caption / TableBlock.caption_block 부착 (v0.2.0 caption: str 호환 보존)
- Rust ir.rs raw 추출기 5종 + ParaShape.head_type / FieldType 14종 / Caption 구조화 매핑
- _KNOWN_KINDS 6→10 종, Block 유니온 11 변형, _walk_blocks 가 CaptionBlock 재귀 진입
- schema _harden_unknown_variant 가 _KNOWN_KINDS SSOT 사용 — leaf-only toc_entry 가 not.enum 에서 빠지도록 (round-trip 깨짐 fix)
- marker placeholder 결정을 Rust → Python 으로 이동 (mapper 도메인 분기 컨벤션 준수)
- LangChain HwpLoader 가 4 신규 블록 매핑 + Picture/Table caption_block 폴백 + Formula/Field 평문 추출
- 신규 테스트 4 파일 (test_ir_list/caption/toc/field, 110 테스트) + 기존 10 파일 보강
- stage-3.md 작성, roadmap README 갱신, CI scoped pyright list 확장

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ma GA

변경사항:
- rhwp-py CLI 재도입 — parse/version/schema/ir/blocks/chunks 서브커맨드
  - python/rhwp/cli/{__init__,__main__,_state,app,ir,chunks}.py 신규
  - typer 지연 로드 (미설치 시 exit 2 + 친절 에러), [cli] / [cli-chunks] extras
  - blocks --kind 11 종 enum (paragraph/table + 8 신규 + all), --format json|ndjson|text
- HwpLoader.include_furniture 옵션 — body 다음 furniture (page_headers/footers/footnotes/endnotes) 도 LangChain Document 로 yield (metadata.scope="furniture")
- Content-addressed schema alias — publish-schema.yml 가 hwp_ir_v1-sha256-<hash>.json alongside 발행 (reproducible 참조)
- pyproject.toml: rhwp-py entry point + [cli]/[cli-chunks] extras + [langchain] 에 langchain-text-splitters 추가 + ruff per-file B008 ignore (typer 관용 패턴)
- 신규 테스트 24 개 — tests/test_cli.py (20, typer importorskip) + test_langchain_loader_ir.py include_furniture 4 케이스
- CI test-without-extras skip count 4 → 5 (typer 추가), pyright scoped 목록에 test_cli.py 추가
- README v0.3.0 신규 섹션 + CHANGELOG [0.3.0] 릴리스 노트 + docs/implementation/v0.3.0/stages/stage-4.md
- 의존성 업데이트 (uv.lock)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- docs/design/pyo3-bindings.md (1,184줄) 삭제 — 업스트림 같은 리포 작업 시점 청사진, 현재 분사 리포 컨벤션과 불일치
- docs/CONVENTIONS.md: pyo3-bindings 등재 3곳 제거 + docs/upstream/ 디렉토리 정책 등재 + implementation stage 의 "Frozen + Target (부모 GA 전)" case 명시
- docs/upstream/issue-find-control-text-positions.md: 제목 헤더 + Status 메타 추가
- docs/roadmap/README.md / v0.3.0/ir-expansion.md: pyo3-bindings cross-link 제거 + 같은 디렉토리 spec 직접 link 위반 1건 (ir-expansion → cli) phase-2 우회로 변경
- README.md: 사용자-facing 본문에서 submodule 메커니즘 / v0.3.0 신규 H3 / content-addressed alias 안내 제거 (CONTRIBUTING.md / CHANGELOG 위임), Document IR 도입부 지원 종류 일반화

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- .claude/hooks/docs-lint.py 신규 — docs/*.md 편집 후 4종 검증 (Status 헤더 / 업스트림 잔재 키워드 / 같은 vX.Y.Z spec 직접 link / 깨진 .md link). 위반 시 exit 2 로 LLM 컨텍스트에 노출
- .claude/settings.json 신규 — PostToolUse hook 등록 (Edit/Write/MultiEdit matcher), 팀 공유용
- .gitignore — settings.local.json 만 ignore (settings.json 은 hook 등록 위해 공유)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- docs/CONVENTIONS.md — Archive 정책 (v1.0+) 절 추가. Major GA 시점 직전 major frozen spec 들을 docs/archive/v0/ 로 이동 (인덱스 비대화 / 검색 노이즈 완화 목적). v1.0 GA 전까지 작업 없음, 미래 reminder 성격
- CLAUDE.md — Git workflow 절에 Branch naming 한 줄 추가 (MINOR = feature/vX.Y.0 long-lived, PATCH = <type>/<topic> Conventional Commits 어휘 — fix/chore/refactor/docs/build/ci/perf/test/revert)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- python/rhwp/document.py — aparse 본문이 aiofiles.open() → asyncio.to_thread(_read_bytes, path) 로 교체. 새 헬퍼 _read_bytes(path) -> bytes
- pyproject.toml — [async] extras = [] 빈 배열 (pip install rhwp[async] 명령 호환 유지), [dependency-groups] testing 에서 aiofiles>=23 제거
- tests/test_async.py — module-level importorskip("aiofiles") 제거. 신규 테스트: no_external_dependency / raises_file_not_found_for_missing_path. 의미 없어진 import_error_without_aiofiles 케이스 삭제
- .github/workflows/ci.yml — test-without-extras expected skip count 5 → 4 (test_async.py 가 더 이상 gated 아님)
- python/rhwp/integrations/langchain.py — docstring 의 aiofiles 언급 제거, ImportError raises 항목 제거
- CLAUDE.md — Async direction + Tests 절의 aiofiles 언급 제거 + stdlib 패턴으로 교체
- CHANGELOG.md — [0.3.0] 에 Changed 섹션 신설 (aiofiles 제거 entry)
- docs/implementation/v0.3.0/aparse-cleanup.md 신규 — 결정 비교 표 보존 (aiofiles vs stdlib 메커니즘, 옵션 a/b/c, unsendable 해결 옵션 A/B/C)
- uv.lock — aiofiles 제거 반영

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- docs/CONVENTIONS.md — § "Implementation log 구조" 절 신설. stages/stage-N.md (spec § 구현 스테이지 분할 작업) vs <topic>.md 직속 평면 (spec 없는 작은 작업) 두 종류 분류 명시. branch prefix <type>/<topic> 와 직속 파일 1:1 mapping 명문화. CHANGELOG 한 줄로 충분한 변경은 파일 zero. 미래 ad-hoc note 5개+ 모이면 chores/ 디렉토리화 검토 (YAGNI). 본 패턴이 spec-driven AI coding 진영 (MADR / Cline decisions / OpenSpec) 의 결정 보존 trend 와 정합함을 명시

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread .claude/hooks/docs-lint.py Fixed
DanMeon and others added 6 commits April 28, 2026 15:43
변경사항:
- .claude/hooks/docs-lint.py — `(v[\d.]+(?:\.[\d.]+)*)` 를 SemVer 정확 매칭 `(v\d+\.\d+\.\d+)` 으로 단순화. 이전 패턴은 [\d.]+ 가 두 그룹에서 같은 char 매칭 가능해 catastrophic backtracking (CodeQL py/redos high) — `v.....` 류 input 에 exponential time. v0.3.0 / v0.3.1 등 사용처는 모두 cover, 의도된 거부 input 은 instant reject
- .github/codeql-config.yml paths-ignore 에 external (submodule) / examples (demo) / benches (마이크로 벤치) 추가 — production 책임 영역 외 자동 제외, 향후 submodules: recursive 도입 시에도 방어적

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- all-tests-passed 잡 추가 (re-actors/alls-green@release/v1)
- test / test-slow / test-core-only 모두 통과해야 성공
- 매트릭스 / 잡 추가 시 ruleset 수동 업데이트 불필요

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- KNOWN_ISSUES.md 신설 — Document 단일 스레드 모델 / async 진입점 / PDF stdout 노이즈 / 읽기·렌더링 전용 등 운영상 제약 정리
- README.md / README_EN.md 의 "알려진 제약 (Phase 1)" 섹션을 KNOWN_ISSUES 링크 + roadmap 링크로 축약, "(Phase 1)" 표제 제거 (Phase 2 결과 반영 시점이라 부정확)
- "표 / 이미지 / 수식 구조화 접근 없음" 항목 제거 — Document IR (v0.2.0 표 + v0.3.0 8 신규 블록) 으로 해결

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- build_raw_document 에서 paragraphs Vec 을 총 단락 수로 pre-allocate (큰 문서 realloc 회피)
- CHANGELOG v0.3.0 의 상류 submodule 핀 기재 정정 (bea635b → 033617e bump, upstream v0.6.x → v0.7.7 380 commits)
- to_ir() 에 GIL 해제 불가 사유 주석 추가 (DocumentCore 의 RefCell 캐시로 !Sync, py.detach Ungil 바운드 불만족)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
변경사항:
- build-linux-wheel 잡 신설 — abi3 wheel 1회 빌드 후 artifact 업로드
- Linux 잡(test×4, slow, core-only) wheel 재사용 — maturin 호출 6→1회
- macOS/Windows 는 test-other-os 잡으로 분리, 자체 빌드 유지
- Swatinem/rust-cache@v2 save-if 를 main 푸시 한정으로 — PR 잡 캐시 저장 단계 생략
- actions/upload-artifact@v7, actions/download-artifact@v8 (최신 메이저)
- all-tests-passed needs 에 build-linux-wheel, test-other-os 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@DanMeon DanMeon merged commit 55e28c0 into main Apr 28, 2026
13 checks passed
@DanMeon DanMeon deleted the feature/v0.3.0 branch April 28, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants