# Project: PDFtoMD

## Repository Role
- 이 저장소는 PDF 문서를 AI Agent가 쉽게 탐색하고 읽을 수 있는 Obsidian 친화 Markdown 문서 묶음으로 변환하는 저장소입니다.
- 목표는 단순 텍스트 추출이 아니라, 읽기 순서, 문단 흐름, 수식, 표, 이미지, 캡션, 원본 위치 추적성을 보존한 구조화 변환입니다.
- 1차 목표는 Windows native 환경에서 완전 로컬로 실행되는 변환 엔진입니다.
- 2차 목표는 PyQt 기반 Windows UI와 선택적 외부 API 연동입니다.
- Persistent repository instructions live in this `AGENTS.md`.
- Reusable repo-scoped workflows live in `.agents/skills/`.
- Project-scoped custom agents live in `.codex/agents/`.
- Experimental hooks live in `.codex/hooks.json`.

## 기술 스택
- **Language**: Python 3.11+
- **Primary PDF Parser**: `Marker`
- **PDF Analysis / Splitting**: `PyMuPDF`
- **OCR / Layout Support**: `Marker`의 OCR/layout 기능을 우선 사용하고, 필요 시 `Surya` 계열 기능을 보조로 검토
- **Table Handling**: `Pandas`
- **Output Target**: Obsidian 친화 Markdown
- **Runtime**: Windows native, local-first, GPU 기본 사용, VRAM 8GB 기준으로 배치/청크 크기 제한
- **UI**: `PyQt`는 2차 목표

## 아키텍처 규칙
### Parser Engine Strategy
- `Marker`를 1차 기본 PDF parser로 사용한다.
- `Nougat`은 기본 엔진에서 제외하고, 필요 시 향후 수식 품질 비교 또는 fallback 후보로만 다룬다.
- 변환 파이프라인은 `Marker` 출력 형식에 직접 결합하지 않고, 프로젝트 내부 중간 표현(Document Model)을 거쳐 Markdown을 생성한다.
- 원본 `Marker` 결과, 변환 설정, 경고, 실패 정보는 진단 가능하도록 metadata/log 산출물로 보존한다.

### Reading Order & Paragraph Flow Strategy
PDF는 텍스트를 좌표 기반으로 저장하므로, 사람이 읽는 논리적인 순서로 재구성하는 것이 핵심이다.
- **Logical Reading Order**: 다단(Multi-column) 문서나 삽입 문구가 있는 레이아웃에서 텍스트 흐름을 추적하여 Markdown의 선형 구조로 배치한다.
- **Paragraph Stitching**: PDF 추출 시 발생하는 행 단위 분절을 제거하고, 문맥과 블록 정보를 이용해 완성된 문단으로 병합한다.
- **Semantic Mapping**: 단순 텍스트가 아닌 제목(Header), 본문(Body), 인용구(Blockquote), 리스트(List), 표(Table), 그림(Figure), 수식(Equation) 등의 의미 역할을 부여한다.

### Scientific, Mathematical, Table, Figure Strategy
- 수식은 Obsidian에서 렌더링 가능한 LaTeX Markdown을 우선한다.
- 인라인 수식은 `$ ... $`, 블록 수식은 `$$ ... $$` 형식을 사용한다.
- 수식 번호와 본문 내 참조 관계는 가능한 한 보존한다.
- LaTeX는 최소한 delimiter 짝, `\begin{...}` / `\end{...}` 짝, 흔한 깨짐 패턴을 검증한다.
- 단순 표는 Markdown table을 우선하고, 병합 셀/복잡한 표/수식 포함 표는 HTML table 또는 별도 CSV와 Markdown 링크를 허용한다.
- 이미지는 추출 파일, 캡션, figure 번호, 원본 페이지 정보를 함께 연결한다.

### Obsidian Output Strategy
- 출력 Markdown은 Obsidian vault에서 바로 열고 탐색할 수 있어야 한다.
- 문서 간 연결은 Obsidian 내부 링크와 표준 Markdown 호환성을 함께 고려한다.
- 이미지 링크, heading anchor, index 링크, 수식 block, 긴 표 링크 규칙은 프로젝트 표준으로 고정한다.
- Windows와 Obsidian에서 안전한 slug 기반 파일명을 사용하고, 원본 파일명은 metadata에 보존한다.

### Source Provenance & Index Strategy
- 변환된 주요 블록은 가능한 한 원본 PDF의 page, page range, block id, bbox, 변환된 md 파일, heading, line 위치와 연결한다.
- index 파일은 단순 목차가 아니라 AI Agent가 필요한 내용을 찾기 위한 탐색 지도 역할을 해야 한다.
- 긴 PDF는 기본적으로 20페이지 단위 chunk로 나누고, chunk별 변환 결과와 상태를 보존한다.
- 실패한 chunk만 재시도할 수 있도록 캐시와 상태 파일을 설계한다.

## 개발 프로세스
- CRITICAL: 새 기능 구현 시 반드시 테스트를 먼저 작성하고, 테스트가 통과하는 구현을 작성할 것 (TDD).
- 1차 구현은 CLI/라이브러리 변환 엔진을 먼저 안정화하고, PyQt UI는 2차 목표로 분리한다.
- 변환 품질 테스트는 전체 Markdown snapshot 비교보다 heading, 수식, 이미지, 표, index 링크, 예외 여부 등 부분 검증을 우선한다.
- `samples/` 폴더의 PDF는 회귀 테스트와 품질 평가용 corpus로 사용한다.
- 커밋 메시지는 conventional commits 형식을 따를 것 (`feat:`, `fix:`, `docs:`, `refactor:`).
- `scripts/execute.py`는 step 완료 후 코드/메타데이터 커밋을 정리하므로, step 프롬프트 안에서 별도 커밋을 만들 필요는 없음.

## Harness Workflow
- 먼저 `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md` 를 읽고 기획/설계 의도를 파악할 것.
- 단계별 실행 계획이 필요하면 repo skill `harness-workflow`를 사용해 `phases/` 아래 파일을 설계할 것.
- 변경사항 리뷰가 필요하면 repo skill `harness-review` 또는 Codex의 `/review`를 사용할 것.
- `phases/{phase}/index.json`은 phase 진행 상태의 단일 진실 공급원으로 취급할 것.
- 각 `stepN.md`는 독립된 Codex 세션에서도 실행 가능하도록 자기완결적으로 작성할 것.

## 검증
- 기본 검증 스크립트는 `python scripts/validate_workspace.py`.
- Node 프로젝트면 `package.json`의 `lint`, `build`, `test` 스크립트를 자동 탐지해 순서대로 실행.
- 다른 스택이면 `HARNESS_VALIDATION_COMMANDS` 환경 변수에 줄바꿈 기준으로 검증 커맨드를 지정.

## 명령어
- `python scripts/execute.py <phase-dir>`: Codex 기반 phase 순차 실행
- `python scripts/execute.py <phase-dir> --push`: phase 완료 후 브랜치 push
- `python scripts/validate_workspace.py`: 저장소 검증
