# Project: PDFtoMD

## Repository Role
- 이 저장소는 PDF 문서를 AI Agent가 쉽게 탐색하고 읽을 수 있는 Markdown 문서 묶음으로 변환하는 저장소입니다.
- 목표는 단순 텍스트 추출이 아니라, 읽기 순서, 문단 흐름, 수식, 표, 이미지, 캡션, 본문 참조를 보존한 구조화 변환입니다.
- 텍스트 레이어 PDF, 스캔 PDF, 텍스트/스캔 혼합 PDF를 모두 지원 대상으로 둡니다.
- 1차 목표는 Windows native 환경에서 완전 로컬로 실행되는 CLI/라이브러리 변환 엔진입니다.
- 2차 목표는 PyQt 기반 Windows UI와 선택적 외부 API 연동입니다.
- 변환 결과는 chunk Markdown 파일과 필요한 이미지/표 asset 중심으로 구성합니다.
- 별도 문서 출력 sidecar 산출물은 명시 요청 전까지 범위에 넣지 않습니다.
- 다만 변환 재개를 위한 로컬 runtime cache/state 파일과 stderr/local log 파일은 문서 출력물이 아니므로 허용할 수 있습니다.
- 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`.

## Read First
새 세션이나 새 agent 작업을 시작하면 다음 문서를 먼저 읽습니다.
- `AGENTS.md`
- `PLAN.md`
- `PROGRESS.md`
- `docs/PRD.md`
- `docs/ARCHITECTURE.md`
- `docs/CONVERSION_POLICY.md`
- `docs/HARNESS.md`
- `docs/IMPLEMENTATION_PLAN.md`
- `docs/ADR.md`
- `docs/TOOLCHAIN.md`
- `docs/UI_GUIDE.md`

## 기술 스택
- **Language**: Python 3.11+
- **Environment**: repo-local single `venv`
- **Primary PDF Parser**: `Marker`
- **Primary Mathematical Expression Parser**: `Nougat`
- **PDF Analysis / Splitting**: `PyMuPDF`
- **OCR / Layout Support**: Marker OCR/layout 기능 우선 사용
- **Pre-analysis**: PyMuPDF 등으로 페이지별 텍스트 레이어 품질과 OCR 필요 여부를 사전 판별
- **Table Handling**: Markdown table 우선, 복잡한 표는 제한적 HTML table과 표 영역 이미지 fallback 허용
- **Output Target**: Markdown
- **Runtime**: Windows native, local-first, GPU 기본 사용, VRAM 8GB 기준으로 batch/chunk 크기 제한
- **Verified GPU Baseline**: NVIDIA GeForce GTX 1070 Ti 8GB, `torch==2.7.1+cu126`
- **UI**: `PyQt`는 2차 목표이며 CLI/라이브러리 API를 호출하는 thin client여야 함

## 아키텍처 규칙
### Parser Engine Strategy
- Marker를 기본 PDF parser로 사용합니다.
- Marker는 전체 레이아웃 추적, OCR/layout, reading order, heading, 본문, 표, 그림, 캡션, semantic block role을 담당합니다.
- Nougat은 메인 PDF parser가 아니라 수식용 parser로 사용합니다.
- Nougat은 Marker의 equation block 또는 수식 패턴이 감지된 블록의 수식 문자열 생성에만 사용합니다.
- Nougat 변환 실패 시 정보 유실 방지를 위해 Marker가 추출한 원문 문자열을 fallback으로 사용합니다.
- PyMuPDF는 페이지 수, 텍스트 레이어 품질, chunk 계획, 저수준 PDF/page/image 작업에 사용합니다.
- 세부 변환 정책은 `docs/CONVERSION_POLICY.md`를 우선합니다.

### Reading Order & Paragraph Flow Strategy
PDF는 텍스트를 좌표 기반으로 저장하므로, 사람이 읽는 논리적인 순서로 재구성하는 것이 핵심입니다.
- **Logical Reading Order**: 다단 문서나 삽입 문구가 있는 레이아웃에서 텍스트 흐름을 추적하여 Markdown의 선형 구조로 배치합니다.
- **Paragraph Stitching**: PDF 추출 시 발생하는 행 단위 분절을 제거하고, 문맥과 bounding box 정보를 이용해 완성된 문단으로 병합합니다.
- **Header/Footer Filtering**: 페이지 상/하단 반복 패턴, 페이지 번호, 머리말/꼬리말은 본문 흐름에서 분리하거나 제외합니다.
- **Semantic Mapping**: 제목, 본문, 인용구, 리스트, 표, 그림, 캡션, 수식 등의 의미 역할을 보존합니다.

### Scientific, Mathematical, Table, Figure Strategy
- 수식은 Markdown math delimiter로 표현 가능한 LaTeX를 우선합니다.
- 인라인 수식은 `$ ... $`, 블록 수식은 `$$ ... $$` 형식을 사용합니다.
- 수식 번호와 본문 내 참조 관계는 가능한 한 보존하고 내부 Markdown 링크로 연결합니다.
- LaTeX는 delimiter 짝, `\begin{...}` / `\end{...}` 짝, 흔한 깨짐 패턴을 검증하고 렌더링이 깨지지 않도록 보정합니다.
- CLI 기본 수식 parser는 `nougat`입니다.
- 표는 Markdown table을 우선합니다.
- 병합 셀, 다중 header, 각주 포함 표 등 Markdown table 손실이 큰 경우 제한적으로 HTML `<table>`을 사용합니다.
- 구조화 손실이 큰 표는 원본 보존용 표 영역 이미지 fallback을 함께 연결합니다.
- 이미지는 추출 파일, 캡션, figure 번호, 본문 참조를 함께 연결합니다.
- 이미지 중복 저장을 줄이기 위해 hash 기반 deduplication을 고려합니다.

### Chunk Strategy
- 긴 PDF는 기본적으로 20페이지 단위 chunk로 나누어 변환합니다.
- chunk 경계는 page count보다 논리 block integrity를 우선합니다.
- 문단, 표, 그림, 수식 중간에서 잘림이 발생하면 해당 block을 이전 또는 다음 chunk로 이동해 온전하게 보존합니다.
- 각 chunk Markdown 최상단에는 문서 제목, page range, chunk 번호 등 최소 문맥을 간결한 frontmatter로 포함할 수 있습니다.

### Output Structure
```text
output/
└── document-slug/
    ├── document-slug_001.md
    ├── document-slug_002.md
    ├── document-slug_003.md
    └── images/
        ├── document-slug_fig-001.png
        └── document-slug_fig-003.png
```

세부 규칙:
- chunk Markdown 파일명은 `<slug>_<chunk-index:03d>.md`
- image asset은 `images/`
- figure 번호가 있으면 `{document-slug}_fig-{figure-number}.png`를 우선합니다.
- figure 번호가 없거나 충돌 가능성이 있으면 chunk/page/block identifier를 포함한 결정적 파일명을 사용합니다.
- 같은 입력과 같은 옵션은 같은 output path, anchor, asset naming을 생성해야 합니다.

### Runtime Policy
- 기본 runtime은 `cuda`입니다.
- explicit `--runtime cuda` 또는 `--device cuda`에서 CUDA가 준비되지 않았으면 fail-fast 처리합니다.
- `--runtime auto`는 필요 시 경고 후 CPU fallback을 허용합니다.
- GTX 1070 Ti 8GB 기준 기본 batch size는 1~2 수준으로 보수적으로 잡습니다.
- GPU OOM 발생 시 가능한 경우 batch/page 단위를 줄여 재시도합니다.
- 모델 cache는 명시적 로컬 경로를 사용해 최초 다운로드 이후 offline 실행을 지원해야 합니다.

### Logging And Resume Policy
- CLI는 chunk 단위 진행률과 성공/실패 상태를 표시합니다.
- 경고와 오류는 stderr 및 로컬 log 파일에 기록합니다.
- 생성된 Markdown 내부에는 오류 로그를 삽입하지 않습니다.
- 성공한 chunk는 재실행 시 건너뛰고 실패한 chunk만 resume할 수 있도록 runtime state/cache를 둘 수 있습니다.
- runtime state/cache는 문서 출력 contract가 아니며, 별도 sidecar 문서 산출물과 구분합니다.

### Licensing Policy
- 현재 사용 맥락은 개인용입니다.
- 배포나 상업적 사용 가능성이 생기면 Marker GPL 및 model weight license 조건을 다시 검토해야 합니다.
- 프로세스/API 분리는 라이선스 위험 완화 후보일 뿐이며 법적 결론으로 취급하지 않습니다.

### Git
- 로컬 git을 사용합니다.
- 주소: `C:\git\PDFToMDWithMath`
- 변경사항이 생길 때마다 커밋합니다.
- 커밋 메시지는 conventional commits 형식을 따릅니다.

## 개발 프로세스
- CRITICAL: 새 기능 구현 시 반드시 테스트를 먼저 작성하고, 테스트가 통과하는 구현을 작성합니다. (TDD)
- 1차 구현은 CLI/라이브러리 변환 엔진을 먼저 안정화하고, PyQt UI는 2차 목표로 분리합니다.
- 변환 품질 테스트는 전체 Markdown snapshot 비교보다 heading, 수식, 이미지, 표, 캡션, 링크, 예외 여부 등 부분 검증을 우선합니다.
- 정규식만으로 복잡한 문서를 처리하지 말고, 가능한 경우 Markdown/HTML parser나 구조화된 parser API를 사용합니다.
- `samples/` 폴더의 PDF는 회귀 테스트와 품질 평가용 corpus로 사용합니다.
- `samples/` PDF의 특성은 sample metadata mapping 파일로 관리합니다.
- 연구/기획 요청에서는 구현 코드, phase 파일, custom agent 파일을 만들지 않습니다.
- `scripts/execute.py`는 step 완료 후 결과 커밋을 정리하므로, step 프롬프트 안에서 별도 커밋을 만들 필요는 없습니다.

## Multi-Agent Coordination
- 여러 agent가 일을 나눠서 할 때 **작업 계획의 단일 출처는 repo root의 `PLAN.md`**, **진행 상태의 단일 출처는 repo root의 `PROGRESS.md`**입니다.
- 새 세션이나 새 agent 작업을 시작할 때는 반드시 `AGENTS.md`, `PLAN.md`, `PROGRESS.md`를 먼저 읽어야 합니다.
- 새 agent는 작업을 시작하기 전에 다음 질문에 답할 수 있어야 합니다.
  - 현재 프로젝트 목표는 무엇인가?
  - 내 담당 범위와 하지 말아야 할 범위는 무엇인가?
  - 이미 완료된 작업은 무엇인가?
  - 현재 진행 중인 작업과 막힌 점은 무엇인가?
  - 바로 이어서 해야 할 다음 작업은 무엇인가?
  - 다른 agent와 충돌할 가능성이 있는 파일이나 책임 영역은 무엇인가?
- `PLAN.md`는 앞으로 해야 할 일의 단일 작업 계획 문서로 사용합니다.
- `PLAN.md`에는 목표, 범위, 우선순위, 작업 분해, 담당 agent 또는 역할, 의존성, 수락 기준, 명시적 제외 범위를 기록합니다.
- `PLAN.md`에는 agent가 새로 시작해도 자신의 담당 작업을 선택할 수 있도록 작업 항목을 구체적으로 적습니다.
- `PROGRESS.md`는 어디까지 진행됐는지의 단일 진행 상태 문서로 사용합니다.
- `PROGRESS.md`에는 완료한 작업, 진행 중 작업, 막힌 점, 주요 결정, 검증 결과, 다음에 이어서 할 작업을 기록합니다.
- `PROGRESS.md`의 "Next Work"는 다음 agent가 실제로 이어받을 수 있는 작업 단위로 유지합니다.
- 작업 시작 전 `PROGRESS.md`의 현재 상태와 `PLAN.md`의 담당 범위를 확인하고, 중복 작업이나 충돌 가능성이 있으면 먼저 정리합니다.
- 작업 중 계획이 바뀌면 `PLAN.md`를 먼저 갱신하고, 실제 진행 결과는 `PROGRESS.md`에 반영합니다.
- 작업을 마치거나 중단할 때는 다음 agent가 이어받을 수 있도록 `PROGRESS.md`를 갱신합니다.
- 여러 agent가 병렬로 작업할 경우 각 agent의 담당 파일, 책임 영역, 의존성을 `PLAN.md`에 명확히 기록합니다.
- 병렬 작업 중 완료/실패/차단 상태, 검증 결과, 다음 handoff 내용은 `PROGRESS.md`에 기록합니다.
- `PLAN.md`와 `PROGRESS.md`가 없고 다중 agent 작업이 필요한 경우, 구현 작업을 시작하기 전에 두 파일의 초안을 먼저 만들거나 사용자에게 생성 승인을 요청합니다.
- Harness의 `phases/{phase}/index.json`은 phase 실행 상태용이고, 다중 agent 작업의 전체 계획과 진행 기록은 `PLAN.md`와 `PROGRESS.md`를 우선합니다.

## Custom Agent Planning
- custom agent 파일은 `.codex/agents/<kebab-case-name>.toml`에 둡니다.
- agent 이름은 snake_case를 사용합니다.
- agent 설계 작업은 기본적으로 read-only agent부터 시작합니다.
- 사용자가 명시적으로 승인한 agent만 하나씩 생성합니다.
- 연구/기획 요청에서는 구현 코드, phase 파일, agent 파일을 만들지 않습니다.

## Codex Project Extensions
Project-scoped Codex extensions live under `.codex/`.

### Agents
- `.codex/agents/phase-planner.toml`: Harness phase planning.
- `.codex/agents/harness-reviewer.toml`: Harness repository review.
- `.codex/agents/pdf-toolchain-researcher.toml`: PDF toolchain compatibility and licensing research.
- `.codex/agents/sample-corpus-analyst.toml`: sample PDF corpus analysis.
- `.codex/agents/conversion-architect.toml`: conversion pipeline architecture.
- `.codex/agents/quality-evaluator.toml`: focused quality and regression strategy.
- `.codex/agents/formula-pipeline-specialist.toml`: Nougat/formula pipeline analysis.
- `.codex/agents/layout-table-figure-specialist.toml`: reading order, table, figure, and caption analysis.

### Commands
- `.codex/commands/status.md`: summarize plan/progress/blockers/next work.
- `.codex/commands/env-check.md`: verify Python environment, CUDA, and Nougat CLI.
- `.codex/commands/sample-audit.md`: inspect `samples/` PDF traits.
- `.codex/commands/quality-plan.md`: draft focused pytest strategy.
- `.codex/commands/conversion-policy-review.md`: review policy/architecture/ADR consistency.
- `.codex/commands/model-cache-check.md`: inspect model cache and offline readiness.
- `.codex/commands/phase-draft.md`: draft Harness phase steps.
- `.codex/commands/sprint-contract.md`: draft or review step-level generator/evaluator contracts.

### Skills
- `.codex/skills/pdf-toolchain`: dependency, CUDA, model cache, and license workflow.
- `.codex/skills/sample-corpus`: sample metadata and corpus classification workflow.
- `.codex/skills/conversion-architecture`: parser/renderer/chunk architecture workflow.
- `.codex/skills/formula-quality`: formula parsing and LaTeX validation workflow.
- `.codex/skills/markdown-quality`: Markdown output validation workflow.
- `.codex/skills/windows-runtime`: Windows path, CUDA, model cache, and resume workflow.

### Hooks
- `.codex/hooks/pre_tool_use_policy.py`: blocks high-risk shell commands.
- `.codex/hooks/stop_continue.py`: runs repository validation at stop.
- `.codex/hooks/handoff_policy.py`: enforces `PLAN.md`/`PROGRESS.md` handoff discipline.
- `.codex/hooks/drift_policy.py`: catches high-confidence docs/toolchain/sample metadata drift.
- Hooks are configured in `.codex/hooks.json`; native Windows hook execution may depend on the active Codex surface.

## Harness Workflow
- Harness 운영 규칙의 세부 기준은 `docs/HARNESS.md`를 우선합니다.
- Anthropic식 장기 작업 흐름은 `planner -> generator -> evaluator` 역할 분리를 기본으로 합니다.
- Planner는 phase/step을 만들고, Generator는 한 번에 하나의 step만 수행하며, Evaluator는 구현 agent와 독립된 관점으로 hard threshold를 적용합니다.
- 각 구현 step은 코드 작성 전에 "Sprint Contract"를 명시해야 합니다. 이 contract에는 완료 정의, hard threshold, 담당 파일, 의존성, 검증 명령이 포함되어야 합니다.
- Generator와 Evaluator의 합의나 검토 결과는 대화에만 남기지 말고 파일에 남깁니다. 기본 위치는 `phases/{phase}/stepN.md`, `phases/{phase}/index.json`, `PROGRESS.md`입니다.
- Hook은 보조 장치이며 `stepN.md`의 Acceptance Criteria와 Evaluator 판단을 대체하지 않습니다.
- Harness 자체는 단순하게 유지합니다. 새 agent, hook, command는 실제 실패 모드를 줄일 때만 추가합니다.
- 먼저 `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/CONVERSION_POLICY.md`, `docs/ADR.md`, `docs/TOOLCHAIN.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`.
- Python 검증은 최소한 다음 항목을 포함해야 합니다.
  - `.\venv\python.exe -m pip check`
  - `.\venv\python.exe -m pytest`
  - CUDA runtime/import smoke test
  - `.\venv\Scripts\nougat.exe --help`
- Node 프로젝트면 `package.json`의 `lint`, `build`, `test` 스크립트를 자동 탐지해 순서대로 실행합니다.
- 다른 스택이면 `HARNESS_VALIDATION_COMMANDS` 환경 변수에 줄바꿈 기준으로 검증 커맨드를 지정합니다.

## 명령어
- `conda create -p .\venv python=3.11 -y`: repo-local Python 3.11 환경 생성
- `.\venv\python.exe -m pip install -r requirements.txt`: 검증된 단일 환경 의존성 설치
- `python scripts/validate_workspace.py`: 저장소 검증
- `python scripts/execute.py <phase-dir>`: Codex 기반 phase 순차 실행
- `python scripts/execute.py <phase-dir> --push`: phase 완료 후 브랜치 push
- `python -m pdftomd <input.pdf> --formula-parser nougat --nougat-command .\venv\Scripts\nougat.exe`: Nougat 수식 parser를 사용하는 기본 변환 경로
- `python -m pdftomd <input.pdf> --formula-parser marker`: Nougat 없이 Marker 수식 문자열을 유지하는 compatibility 변환 경로
