---
name: gdi-hwpx
description: 조립된 GDI 정책보고서 마크다운(drafts/99_full.md 등)을 경북연구원 양식 한글 문서(.hwpx)로 변환한다. 딸깍 개발실 md2hwpx 엔진(검증본)을 그대로 재사용해 양식의 스타일(장/절/항/목·▮/❍/-/※ 글머리·표/그림제목·자료주·각주)을 입힌다. /gdi-finalize 의 마지막 HWPX 산출 단계, 또는 "보고서를 한글(.hwpx)로 만들어줘"·"hwpx 변환" 요청 시 사용. (구 hwpx-autofill-conversion 스킬의 대체)
---

# gdi-hwpx — 마크다운 → 경북연구원 양식 .hwpx

조립된 보고서 마크다운을 **양식(.hwpx)의 스타일을 입혀** 한글 문서로 변환한다.
딸깍 개발실 `md2hwpx` 엔진(`parser.js`→`presetManager.js`→`hwpxBuilder.js`)을 **0줄 수정 스냅샷**으로
세션 안 Node 에서 그대로 구동한다. 한컴 호환 노하우(네임스페이스 prefix 함정 회피·표 병합/테두리·
글머리 변형 매핑·폰트 보존)가 이미 들어 있어, 범용 템플릿-스플라이싱 방식보다 안정적이다.

## 실행 (Bash 로 Node 스크립트 호출)

저장소 루트에서 실행한다. 아래 `<P>` = 활성 과제 폴더 `projects/<연도_과제명>`(루트 `ACTIVE_PROJECT.txt` 첫 비주석 줄)로 치환:

```bash
# 기본 양식(번들)으로 변환 — 가장 흔한 경로
node .claude/skills/gdi-hwpx/build_hwpx.mjs --md <P>/drafts/99_full.md --out <P>/output/report.hwpx

# 사용자 양식을 직접 지정 (<P>/sources/ 에 둔 .hwpx)
node .claude/skills/gdi-hwpx/build_hwpx.mjs --md <P>/drafts/99_full.md --template <P>/sources/gdi_template.hwpx --out <P>/output/report.hwpx

# 양식의 스타일 목록만 확인 (매핑 점검·작성용)
node .claude/skills/gdi-hwpx/build_hwpx.mjs --template <P>/sources/gdi_template.hwpx --print-styles
```

옵션: `--mapping <json>`(매핑 강제 지정) · `--no-fit-columns`(표 열폭 균등) · `--quiet`.
성공 시 `✅ 완료` + 자가검증(mimetype·XML 태그 균형) 결과를 출력한다. 실패하면 비0 종료코드.

## ★ 마크다운 작성 규약 (이 매핑대로 써야 위계가 정확히 입혀짐)

보고서 본문 마크다운은 GDI 위계를 아래 규칙으로 표기한다. (gdi-analyst·gdi-policy-maker 가 준수)

| 마크다운 | GDI 위계 | 번들 양식 스타일 |
|---|---|---|
| `# 제목` | 제N장 (장) | 장 |
| `## 제목` | 제N절 (절) | 제1절 |
| `### 1. 제목` | 항 (1.) | 1. |
| `#### 1) 제목` | 목 (1)) | 1) |
| `■ …` 또는 `▮ …` (줄 시작) | ▮ 킬러메시지 | ▮ |
| `❍ …` 또는 `○ …` | ❍ 구체설명 | 본문○ |
| `- …` | - 세부·통계 | 본문- |
| `※ …` | ※ 참고·출처 | ※ |
| 일반 문단 | 본문 | 바탕글 |
| `\| a \| b \|` 표 | 표 | 셀=표내용 |
| `[표 N-M] 제목` (표 바로 위 줄) | 표 제목 | 표제목 |
| `[그림 N-M] 제목` | 그림 제목 | 그림제목 |
| `자료 : …` (줄 시작) | 자료·주 | 자료,주 |

- 글머리(■/❍/-/※)는 **줄 맨 앞**에 기호 + 공백 + 내용으로 쓴다.
- 표는 GFM 표. 단위는 표 제목·헤더에 `(단위: %)`처럼 표기.
- 위 기호와 다른 양식을 쓰면, 스킬이 양식 스타일 **이름·글머리 문자**로 자동 매핑한다(아래).

## 양식·매핑 동작

- **양식 = 스타일·페이지 설정 도너.** 양식의 글꼴/크기/정렬/글머리/여백/머리말·꼬리말 설정을 가져오고,
  **본문 내용은 마크다운으로 100% 교체**한다(양식의 표지·샘플 본문은 사용 안 함 — 아래 한계 참조).
- **자동 매핑:** 양식 스타일의 **이름**(장·제1절·1.·표내용 등)과 **실제 글머리 문자**(■/○/-)를 보고
  마크다운 패턴을 자동 연결한다. (`automap.mjs` — md2hwpx 휴리스틱 포팅)
- **번들 기본 양식**(`templates/gdi-default.hwpx`)을 쓰면 전용 정밀 매핑(`mapping.gdi.json`)이 자동 적용된다.
- **매핑 교정:** 자동 매핑이 틀리면 `--print-styles` 로 styleId 를 확인하고
  `{ "h2": "5", "bullet:❍": "1", ... }` 형태 JSON 을 `--mapping` 으로 넘긴다.

## 조판 레이어 (finalize/ — 표지·목차·간지·쪽번호 자동화)

본문 변환(`build_hwpx.mjs`)은 **본문만** 만든다. 그 위에 경북연구원 **조판 레이어**(겉/속표지·연구진·요약·목차·표목차·그림목차·장별 간지·장 박스·절 투명표·항 페이지·머리말 쪽번호·참고문헌 박스·뒷표지)를 입히려면 `finalize/finalize_layout.mjs` 를 이어서 실행한다. 양식(`templates/gdi-default.hwpx`)의 **검증된 OWPML 조각**(`finalize/_frag_raw/`)을 그대로 splice 하고 본문에서 장/절/항·표/그림 캡션을 수집해 목차류를 자동 생성하므로 한컴 호환이 보장된다.

> **★페이지 크기 = 양식 native 190×260mm(53,858×73,700 HWPUNIT, 본문폭 35,150) — A4 아님.** A4로 강제하면 표지·머리말·간지의 절대좌표가 어긋난다. 따라서 표지 secPr(native)을 그대로 쓰고, A4(42,520폭)로 만들어진 본문(`report_그림.hwpx`)의 **표·그림은 native 본문폭(35,150)으로 자동 축소**한다(`rescaleBodyToNative`). 1mm=283.465 HWPUNIT. 상세 규칙은 `docs/경북연구원_정책과제_작성지침.md` §8.

```bash
# 1) 본문(그림 임베드 포함) HWPX 생성 → 2) 조판 레이어 적용
node .claude/skills/gdi-hwpx/finalize/finalize_layout.mjs \
  --in <P>/output/report_그림.hwpx \
  --summary <P>/drafts/90_summary.md \
  --config <P>/finalize.config.json \
  --out <P>/output/report_최종.hwpx
```

- **입력:** `--in` 본문 HWPX(그림 임베드본 `report_그림.hwpx`; A4폭이어도 native로 자동 축소) · `--summary` 요약 md(요약 페이지 생성) · `--config` 표지 치환값 JSON(제목·연구번호·영문제목; **연구진·발간정보는 플레이스홀더 유지**) · `--out` 최종 HWPX.
- **적용 규칙:** 장→간지+빈 페이지 · 장 본문 시작=장 박스(상단 실선)+절 투명표 · 절→투명표+새 페이지 · 항(1.)→새 페이지(단 절 바로 아래 첫 항 제외) · 머리말 쪽번호(요약=로마자/본문=아라비아; 홀수=장제목 우측, 짝수=보고서 제목 좌측) · 참고문헌=상하실선 중앙정렬 박스+style20 · 뒷표지=양식 발행정보 표.
- **표지:** 저자·연구진명은 샘플 표기 유지(2번째 연구책임→공동연구), 붉은 가이드문구 제거, 대구경북연구원 로고는 native서 자동 비표시.
- **검증:** `finalize/render_pdf.ps1 <hwpx> <pdf>`(한컴 COM)으로 PDF 렌더 → **native 영역(538×737pt) 크롭**해 육안 확인.
- **재사용:** 조각은 번들 양식 기준 추출. **다른 양식**은 `_frag_raw/` 재추출 + **그 양식의 용지·본문폭으로 좌표·축소비율 재산정**(`finalize/hwpx_util.mjs`의 `splitTopLevelParas` 활용).

### 한컴에서 마치는 단계
- **목차류 쪽번호:** `000` 플레이스홀더 → **[도구]-[차례/색인]-[차례 만들기]**로 자동 채움. (목차 절은 우측탭+실선리더, 항은 인라인 000.)
- **표지 `[확인요망]`:** 연구진·발간등록번호 등 확정값 교체.
- **PDF 내보내기:** 용지를 **'문서 크기(190×260)'** 로 지정(기본 A4면 내용이 A4 좌상단 배치됨).

## 한계

- **표지 인적·발간정보:** `[연구진 확인요망]`·`[발간등록번호 확인요망]` 플레이스홀더로 둔다(고유명사 날조 금지). 한컴에서 확정값으로 교체.
- **목차류 페이지번호:** 위 「한컴에서 마치는 1단계」 참조.
- **이미지:** `build_hwpx.mjs` 단계는 `imageRegistry: null`(자동임베드 미지원). 그림 임베드는 별도 후처리(메모리 `gdi-hwpx-figure-table-finalize`). 본문 HWPX에 이미 임베드된 상태로 `finalize_layout` 에 넘기면 그대로 보존된다.

## 그림(이미지) 삽입 — 참고문헌 원본 활용 (CLAUDE.md §4.4.1 연계)

GDI 보고서 그림은 **3경로**(CLAUDE.md §4.4.1): ① **원본 도표 그대로**(`sources/` 추출 삽입) · ② **모식도·개념도·예시도 = 이미지 AI 프롬프트**(GPT Image/Nano Banana로 사람이 생성 → PNG) · ③ **데이터 그래프 = 실데이터 표 → 딸깍개발실 차트 딸깍**으로 차트화. **데이터·수치를 이미지 AI로 그리지 않는다(날조 방지).** 아래는 ① 원본 추출 절차(②는 프롬프트를 사람이 생성, ③은 표를 차트 딸깍이 처리):

1. **추출 (PyMuPDF):**
   - 페이지 전체: `page.get_pixmap(dpi=200).save(out_png)`
   - 영역 크롭: `page.get_pixmap(clip=fitz.Rect(x0,y0,x1,y1), dpi=200)`
   - 원본이 래스터 객체면: `page.get_images()` → `doc.extract_image(xref)` 로 직접 추출
2. **보관:** `<P>/drafts/figures/fig_{N-M}_{슬러그}.png` + `<P>/drafts/figures/_sources.md` 에 출처 로그(파일·원본문헌·쪽).
3. **초안 표기:** 본문 md 에는 `[그림 N-M] 제목` + 다음 줄 자료주만 둔다(이미지 자리표시). **경로별:** ① 원본 = `자료 : {저자}, 「{제목}」, {기관}, {연도}, p.{쪽}.`(재작도면 끝에 `…를 바탕으로 재작성`) / ② 개념도 = 캡션 + `※ 이미지 생성 프롬프트 … GPT Image/Nano Banana: "…"` + `자료 : 저자 작성(생성형 AI 활용)` / ③ 데이터 = 캡션 + `※ 차트 변환용 데이터 — 딸깍개발실 차트 딸깍` + GFM 표 + 자료주.
4. **HWPX 삽입(자동):** `finalize/a4_upconvert.py`(본문 A4 폭 보정 — 그림이 없어도 finalize 전 필수) → `finalize/embed_figs.py <in> <out> <manifest.json>`(manifest: `[{"caption":"[그림 N-M]","png":"…","width_ratio":1.0}]`)로 본문 캡션 앞에 `hp:pic` 임베드. 검증된 조각(BinData figimgN + content.hpf opf:item) 재현이며, finalize의 `rescaleBodyToNative`가 figimg를 native 폭으로 자동 축소한다. 렌더 PDF에서 이미지-캡션 쪽 분리 시 `width_ratio` 축소로 해소. (참고: 추출 헬퍼 `finalize/extract_fig.py` — `--blocks`로 좌표 파악 후 클립 렌더.)

## 검증

```bash
node .claude/skills/gdi-hwpx/selftest.mjs    # 22 PASS — 위계 연결·태그 균형·dangling 참조 점검
```

엔진 스냅샷을 갱신했거나 동작이 의심되면 셀프테스트를 먼저 돌린다. 엔진 갱신 방법은 `NOTES.md` 참조.
