- name
- jaw-hwp
- description
- HWP/HWPX create, read, edit, review, template-fill, QA. Triggers: 한글, .hwp, .hwpx, HWP, HWPX, Korean documents, 한컴오피스, OWPML.
# HWP/HWPX Document Skill
> **Scope**: HWP/HWPX only. Do NOT reference or load skills for other formats
> (DOCX, PPTX, XLSX, PDF). If the task involves a non-HWP format, stop and tell the user.
**OfficeCLI routing and consent rule:**
- First check whether `officecli` is available with a probe that works in the agent's actual shell: `command -v officecli` on POSIX, `Get-Command officecli -ErrorAction SilentlyContinue` in PowerShell. **`command -v` is not a PowerShell builtin or cmdlet** — on Windows it prints nothing, sets no exit code, and raises no error, so it is indistinguishable from "not installed" and the agent asks to install a tool that is already there (#298). `officecli --version` is the portable fallback: a non-zero exit or no output means missing.
- If installed, recommend OfficeCLI first for HWPX work and experimental rhwp-backed binary HWP read/edit.
- If missing, do not auto-install. Present choices before proceeding:
1. Install forked OfficeCLI from `https://github.com/lidge-jun/OfficeCLI` via `bash "$(npm root -g)/cli-jaw/scripts/install-officecli.sh"`.
2. Continue only with lightweight HWP/HWPX fallback scripts for the current task, with limitations stated.
3. Stop or cancel.
- Before taking a lightweight fallback path, ask the user again and state what HWP/HWPX features may be lost.
- If the user chooses lightweight mode, save that preference to memory for future Office work.
- Use upstream/vanilla `iOfficeAI/OfficeCLI` only when the user explicitly asks for upstream behavior.
OfficeCLI is the recommended advanced backend for HWPX work and experimental rhwp-backed binary HWP read/edit.
Lightweight fallback: **Python OOXML/OWPML scripts** (`scripts/*.py`) for what OfficeCLI cannot cover, or when the user chooses lightweight mode: HWP→HWPX conversion, template assembly, pattern-match editing, direct XML edits. See §3.
Triggers: `"한글"`, `".hwpx"`, `".hwp"`, `"HWP"`, `"HWPX"`, Korean documents, 한컴오피스, OWPML.
**OfficeCLI install contract inside cli-jaw:** after user approval only, install or refresh OfficeCLI through `bash "$(npm root -g)/cli-jaw/scripts/install-officecli.sh"`. This installs the supported fork from `https://github.com/lidge-jun/OfficeCLI` used for CJK/rhwp workflows. Do not use direct upstream install snippets unless the task explicitly asks for vanilla upstream OfficeCLI behavior.
**OfficeCLI discovery rule:** run `officecli hwp doctor --json` and `officecli capabilities --json` before claiming binary `.hwp` support. Use `officecli hwp --json` for current rhwp recipes/policies and `officecli help <format> ... --json` for DOCX/XLSX/PPTX-style schema help.
**Same-file execution rule:** run OfficeCLI commands against the same `.hwpx` or `.hwp` sequentially. Do not run `officecli view`, `officecli validate`, `officecli query`, or `officecli get` in parallel against one package. If a file lock occurs, stop and report the exact command and path before making a copy or retrying.
---
## 1. Quick Decision
| Task | OK? | Command |
|------|-----|---------|
| **Format like existing .hwpx** | Yes | `cp source.hwpx target.hwpx && officecli open target.hwpx` — inherit styles. See §2 |
| **Template-based create** | Yes | `python3 scripts/build_hwpx.py --template {base\|gonmun\|minutes\|proposal\|report} --output out.hwpx` — see §4 |
| Create new .hwpx | Yes | `officecli create file.hwpx` |
| Create from Markdown | Yes | `officecli create file.hwpx --from-markdown input.md` |
| Read / analyze .hwpx | Yes | `view text`, `annotated`, `outline`, `stats`, `html`, `markdown`, `tables`, `forms`, `objects` |
| Edit existing .hwpx | Yes | `set`, `add`, `remove`, `move`, `swap` |
| Label-based fill | Yes | `set /table/fill --prop 'fill:label=val'` |
| Form recognize | Yes | `view forms --auto` (label-value auto-detect) |
| Table map | Yes | `view tables` (2D grid + labels) |
| Markdown export | Yes | `view markdown` |
| Equation (수식) | Yes | `add --type equation --prop 'script={1 over 2}'` |
| Object finder | Yes | `view objects` (picture/field/bookmark/equation) |
| Query (expanded) | Yes | `query 'tc[text~=홍길동]'`, `:has()`, `>` combinator |
| Template merge | Yes | `merge template.hwpx out.hwpx --data '{"key":"val"}'` |
| Swap elements | Yes | `swap file.hwpx '/p[1]' '/p[2]'` |
| Column break | Yes | `add --type columnbreak --prop cols=2` |
| Image anchor / floating | Yes | `add --type picture --prop anchor=page --prop halign=center` |
| Field types | Yes | `add --type author\|title\|lastsaveby\|filename` |
| Compare documents | Yes | `compare a.hwpx b.hwpx` (LCS diff + table compare) |
| Security validation | Yes | ZIP bomb, path traversal, symlink, XXE defense |
| Broken ZIP recovery | Yes | corrupted HWPX auto-recovery via Local File Header scan |
| HTML preview | Yes | `view html --browser` |
| Watch live preview | Yes | `watch file.hwpx` |
| Validate .hwpx | Yes | `validate` (9-level check) |
| Raw XML | Yes | `raw`, `raw-set` |
| Watermark (image) | Yes | `add --type watermark --prop src=img.png` (opaque RGB preferred) |
| **Pattern-match editing** | Python (L4) | `scripts/hwpx_cli.py open` → pattern edit XML → `save` — see §16 |
| **Visual QA** | Python (L3) | `scripts/contact_sheet.py` + subagent review with `reference/visual_qa_prompt.md` |
| New form field creation | Blocked | source prototype exists; Hancom verification not closed |
| Diagnose binary .hwp support | Yes, experimental | `officecli hwp doctor --json` then inspect `officecli capabilities --json` |
| Create new .hwp (binary) | Yes, experimental | `officecli create file.hwp --json`; requires packaged `rhwp-field-bridge` or `OFFICECLI_RHWP_API_BIN` |
| Read/render/export .hwp (binary) | Yes, experimental | `officecli view file.hwp text --json`; `svg`, `png`, `pdf`, `markdown`, `thumbnail`, `info`, `diagnostics`, `dump`, `pages` are capability-gated |
| Edit simple .hwp text/fields | Yes, experimental | Use `officecli hwp --json` recipes; prefer `--prop output=out.hwp` |
| Insert new .hwp body text | Yes, experimental | `officecli add file.hwp /text --type paragraph --prop value=본문 --prop output=out.hwp --json`; requires `insert_text.ready=true` |
| Edit .hwp/.hwpx table cell by rhwp coordinates | Yes, experimental | `officecli set file.hwp /table/cell ...`; `.hwpx` also routes through rhwp when mutation runtime is ready |
| Use native rhwp API not yet modeled as a high-level command | Yes, experimental | `officecli view file.hwp native --op get-style-list --json`; `officecli set file.hwp /native-op --prop op=split-paragraph --prop output=out.hwp --json` |
| Export HWPX to .hwp | Yes, experimental | `officecli set input.hwpx /save-as-hwp --prop output=out.hwp --json` |
| Safe in-place .hwp text replace | Yes, experimental | Only when `capabilities.formats.hwp.operations.replace_text.safeInPlace.ready=true`; use `--in-place --backup --verify` |
| Convert .hwp to .hwpx | Fallback | `scripts/hwp_convert.py IN.hwp OUT.hwpx` only when the requested native rhwp operation is not ready or not yet wired |
---
## 2. Reference-Based Editing (Edit > Create from Scratch)
When the user says "format like X.hwpx", "공문 양식처럼", "기존 보고서 스타일", or provides a source file — **start from the source. Don't rebuild from scratch.**
### Workflow
1. **Copy the source**: `cp source.hwpx target.hwpx` — inherits header.xml (styles), section0.xml (structure), META-INF
2. **Open** with `officecli open target.hwpx` — daemon returns immediately (do NOT run as `run_in_background`)
3. **Remove body paragraphs only** — keep `header.xml` (charPr/paraPr/borderFill), `META-INF`, settings
4. **Add new content** using existing styleidref values — they auto-apply
### Why This Matters
HWPX header.xml holds all style definitions (charPr, paraPr, borderFill, listItems). Rebuilding these from scratch:
- Breaks styleidref cross-references in section0.xml
- Loses consistent 공문/보고서 visual conventions
- Breaks validation (`officecli validate` fails)
- Takes 10× longer than modifying the copy
### Template Sources (priority order)
1. **User-provided source file** — first-class template
2. **`tests/fixtures/agentic/*.hwpx`** — realistic samples (gonmun with headings, report, minutes with tables)
3. **`templates/{base,gonmun,minutes,proposal,report}/`** — **Template Assembly system** (see §4)
4. **`officecli create`** blank — only when nothing else applies
### Example — Official Letter (공문) Reuse
```bash
# Method A: direct copy
cp SampleGonmun.hwpx MyGonmun.hwpx
officecli open MyGonmun.hwpx
# Use /table/fill to replace label-value cells
officecli set MyGonmun.hwpx /table/fill --prop '문서번호=2026-123'
officecli set MyGonmun.hwpx /table/fill --prop '수신=관계 부서장'
officecli close MyGonmun.hwpx
# Method B: template assembly (see §4)
python3 scripts/build_hwpx.py --template gonmun --output MyGonmun.hwpx
# Then edit with officecli as above
```
---
## 3. Reference Materials & Script Map
officecli covers most HWPX operations. For template assembly, direct XML editing, HWP conversion, and pattern matching, use these references + Python scripts.
### References (`reference/` — singular)
| File | Read when | Contains |
|------|-----------|----------|
| `reference/hwpx-format.md` | **Before any direct XML edit** | OWPML ZIP structure, namespaces, file layout, mimetype |
| `reference/header-xml-guide.md` | Adding/modifying charPr/paraPr/borderFill/listItems styles | How to add new styles to header.xml — required reading for style customization |
| `reference/section0-xml-guide.md` | Paragraph/table/mixed-formatting direct XML | XML template for section0.xml bodies |
| `reference/style_id_maps.md` | **Style ID lookup for template overlay** | Complete style ID index for base/gonmun/minutes/proposal/report templates |
| `reference/dependencies.md` | First-time setup / environment check | Python/system packages needed (pyhwp, lxml, soffice, JAVA_HOME) |
| `reference/visual_qa_prompt.md` | Visual QA via subagent | Ready-to-use prompt for PDF-image inspection |
| `reference/table_templates/*.xml` | Inserting pre-built tables | 2x6, 3x3, 4x4, 5x4 grid XML fragments |
### Scripts (`scripts/`) — Python OWPML Toolkit
| Script | Run when | Command |
|--------|----------|---------|
| `scripts/hwpx_cli.py` | Unified Python CLI (14+ commands) — unpack, save, text, search, replace, batch-replace, tables, fill-table, validate, page-guard, toc, chunk, search-chunks, repair, content-check, insert-table, structure | `python3 scripts/hwpx_cli.py {command} ...` |
| `scripts/build_hwpx.py` | **Template-based creation** (§4) | `python3 scripts/build_hwpx.py --template {type} --output X.hwpx` |
| `scripts/analyze_template.py` | Inspect template structure before overlay | `python3 scripts/analyze_template.py work/` |
| `scripts/create_document.py` | Create empty or custom HWPX | `python3 scripts/create_document.py OUT.hwpx` |
| `scripts/table_builder.py` | Build table XML from Python objects | Used internally by `insert-table` command |
| `scripts/page_guard.py` | Detect paragraph/table/text drift vs reference doc | `python3 scripts/page_guard.py -r ref.hwpx -o out.hwpx` |
| `scripts/contact_sheet.py` | QA contact sheet (page grid image) | `python3 scripts/contact_sheet.py INPUT.pdf sheet.png` |
| `scripts/validate.py` | 9-level structural validation (Python fallback) | `python3 scripts/validate.py INPUT.hwpx` |
| `scripts/hwp_reader.py` | Read HWP 5.0 binary (OLE2, read-only) | `python3 scripts/hwp_reader.py INPUT.hwp` |
| `scripts/hwp_convert.py` | HWP → HWPX conversion (H2Orestart-based) | `python3 scripts/hwp_convert.py IN.hwp OUT.hwpx` |
| `scripts/text_extract.py` | Extract plain text from HWPX | `python3 scripts/text_extract.py INPUT.hwpx` |
| `scripts/ooxml/pack.py` / `unpack.py` | ZIP atomicity helpers | Used internally by other scripts |
### Fixed-Layout Exam Visual QA
KICE-style exam sheets (`국어 영역`, `수학 영역`, two-column
`<hp:colPr type="NEWSPAPER" colCount="2">`, dense question numbering) are
fixed-layout documents. Treat visual fidelity as stricter than generic text
mutation:
1. **Do not insert QA/proof markers into the visible body**. Strings such as
`[CU TEMPLATE EDIT ...]`, `VISUAL QA`, or `edited via Hancom Office HWP UI`
inside the question body are visual hard failures.
2. Capture before/after screenshots from Hancom Office HWP at the same zoom and
page position. Store proof in screenshot paths, logs, or sidecar evidence,
not in the document's first column, answer choices, header tables, or
floating title/page-number objects.
3. If the requested edit changes exam content, replace only the intended anchor
text/run. Preserve column breaks, question numbering, answer-choice tab
layout, equations, and floating objects.
4. For direct XML edits, strip all `<hp:linesegarray>` layout cache entries
before repacking so Hancom recalculates layout on open.
5. Pass criteria: same page count, same two-column structure, no unexpected
body marker, no visible drift except the requested content change.
### Editing Escalation Ladder
When officecli can't do the job, escalate in this order:
| Level | When | Tool |
|-------|------|------|
| **L1** officecli high-level | Typical add/set/remove, label-fill, view modes | `officecli add/set/remove/query/view/merge` |
| **L2** officecli `raw` / `raw-set` | Direct section0.xml / header.xml tweaks | `officecli raw FILE /Contents/section0.xml` or `raw-set` |
| **L3** Python script | Bulk find/replace, batch-replace, template assembly, pattern-match | `python3 scripts/hwpx_cli.py ...` or `scripts/build_hwpx.py` |
View on GitHub