Repository navigation
Changed (BREAKING)
- cellยทstampยทstructural ํธ์ง๊ธฐ์ ์
๋ ฅ decode๋
DECODE_FAILED, no-op validateยทencodeยท์ฌdecode๋INPUT_NOT_ROUNDTRIP_SAFE, ํธ์ง ๋ฌธ์ ๊ฒ์ฆ์VALIDATION_FAILED, ์ถ๋ ฅ ์์ฑ์ENCODE_FAILED, ์ฐ์ถ๋ฌผ ๊ฒ์ฆ์SELF_VERIFY_FAILED๋ก ๋ถ๋ฅํ๋ค. ๋ณดํธ ํ๋ ์นจ๋ฒ์PROTECTED_FIELD_RANGE, source-mapยทprovenance ๋ถ๋ณ์์INTERNAL_INVARIANT๋ค. CLIยทMCPยทPython์ด ๊ฐ์ ์ฝ๋๋ฅผ ๋ฐํํ๋ค. - stamp์ delta ๊ฒ์ฆ ์ฝ๋๋
SELF_VERIFY_FAILED, ๊ฐ์ ์ ์ค๋ณต ์ง์ ์CELL_TARGET_DUPLICATE๋ก ํต์ผํ๋ค. - CLI ์ข ๋ฃ ์ํ๋ ๋ช ๋ น๊ณผ ๋น๊ณต๊ฐ typed ์ฝ๋๋ก ๊ฒฐ์ ํ๋ฉฐ, ๊ฐ์ ๋ช ๋ นยท์ฝ๋์ ์ข ๋ฃ ๊ฐ์ ์ค๋ฅ payload๋ ๋ฐ์ ๊ฒฝ๋ก์ ๋ฐ๋ผ ๋ฌ๋ผ์ง์ง ์๋๋ค. ์๋ ๋ค ํธ์ง๊ธฐ ๋ณ๊ฒฝ๊ตฐ๊ณผ ๋ค์ I/O ๋ ๋ณ๊ฒฝ๊ตฐ, validate ํ ๋ณ๊ฒฝ๊ตฐ(๋ชจ๋ ์ผ๊ณฑ ๋ณ๊ฒฝ๊ตฐ)์ ์ ์ฉํ๋ค.
| ๋ช ๋ นยท์คํจ | ์ด์ ์ข ๋ฃ | 0.18 ์ข ๋ฃ |
|---|---|---|
| delete-paraยทinsert-para: no-op validateยทencodeยท์ฌdecode | 2 | 1 |
| stamp: no-op validateยทencodeยท์ฌdecode | 2 | 1 |
| set-cell: ์ ๋ ฅ decodeยท์๋ณธ ํจํค์ง ์ฝ๊ธฐ | 1 | 2 |
| delete-paraยทinsert-para: ์ถ๋ ฅ decodeยท์ฐ์ถ๋ฌผ ์ฝ๊ธฐยทfragment ํ์ฑ | 2 | 1 |
-
Draft
apply_set_cells๊น์ด ์ด๊ณผ๋CellEditError::NestingTooDeep { section: usize, reason }์ด๋ฉฐ Display๋nesting depth exceeds the limit: {reason}๋ค. ๋ฐ์ดํธ ์ ๋ ฅ์ decode ๊ด๋ฌธ์์ ๋จผ์ ๊ฑฐ๋ถํ๋ค. -
to_json์ ํ์๋ ํต๊ณผํ์ง๋ง Core ์ค์ฒฉ ๊น์ด 32๋จ๊ณ๋ฅผ ๋๋ HWPX ์ ๋ ฅ์์GRID_ADDR_PROJECTION_FAILED๋์ ์ฝ๊ธฐ ๋จ๊ณ์DECODE_FAILED๋ฅผ ๋ฐํํ๋ค. -
stamp-plan์ ์ด์ ์ ์ฑ๊ณตํ๋ ๊ฐ์ ๊น์ด ์ด๊ณผ ์ ๋ ฅ์ ์ฝ๊ธฐ ๋จ๊ณ์์DECODE_FAILED๋ก ๊ฑฐ๋ถํ๋ค. -
fillยทstampยทinsert-paraยทdelete-paraยทset-cellยทpatch๋ ๊ฐ์ ๊น์ด ์ด๊ณผ ์ ๋ ฅ์์ ์ด์ decode ๋จ๊ณ์์ ์คํจํ๊ณ , ๋ฉ์์ง๋Core error:๋ฅผ ํฌํจํ ๊น์ด ์ด๊ณผ ์ง๋จ์ผ๋ก ๋ฐ๋๋ค. ์ฌ์ฏ ํธ์ง๊ธฐ ๋ชจ๋ ์๋ ๋จ๊ณ ๋ถ๋ฅ์ ๋ฐ๋ผDECODE_FAILED๋ฅผ ๋ฐํํ๋ค. -
CLIยทMCP๋ ๊ณตํต
OpsCode::as_str()๋ฅผ ์ถ๋ ฅํ๋ค.DECODE_ERROR,UNKNOWN_PRESET,INDEX_OUT_OF_RANGE๋ฑ์ ์ฐฝ๊ตฌ๋ณ ๋ณ๋ช ์ ์ ๊ฑฐํ๋ค. ์ ๋ฐํ ๊ธฐ์กด ๋๋ฉ์ธ ์ฝ๋์ ์๋ฏธ ์์ค ์ฝ๋๋ ๊ทธ๋๋ก ์ ๋ฌํ๋ค. -
read์ ๊ตฌ์ญยทํยทํ๋ ๋ถ์ฌ๋
SECTION_OUT_OF_RANGE,TABLE_NOT_FOUND,FIELD_NOT_FOUND๋ก ํตํฉํ๋ค. ๊ด๋ จ read variant 3๊ฐ์ ์๋น์๊ฐ ์์ด์งSectionWorkflowFailed,SetCellFailed,StampFailed,StructuralEditFailed๋ฐ ์ lookup์ ์ญ์ ํ๋ค. -
์ ๋ ฅ ๋ถ์ฌ/๊ธฐํ ์ฝ๊ธฐ/ํฌ๊ธฐ ์ํ/์ถ๋ ฅ I/O๋
FILE_NOT_FOUND/FILE_READ_FAILED/INPUT_TOO_LARGE/FILE_WRITE_FAILED์ด๋ค. MCP ์ถ๋ ฅ ๊ฒฝ๋ก ์ ์ฑ ๊ฑฐ๋ถ๋INVALID_OUTPUT_PATH์ด๋ค. -
INVALID_SETยทDUPLICATE_SET๊ณผ ์ง๋จ์ฉ ๋ค ์ฝ๋, ์ด ์ฌ์ฏ CLI ์ ์ฉ ์ฝ๋๋ CLI ์์์ ์ ์งํ๋ค. ์ ๋ ฅ ๋ถ์ฌยท์ฝ๊ธฐ ์คํจ๋ to-mdยทconvert-hwp5 2, ๋๋จธ์ง 1์ด๋ฉฐ ์ถ๋ ฅ I/O๋ ๊ตฌ์กฐ ํธ์งยทconvert-hwp5 2, ๋๋จธ์ง 1์ด๋ค.INPUT_TOO_LARGE๋ ์ผ๋ฐ ํ์ผ ์ฌ์ ๊ฒ์ฌยทFIFO ๋ชจ๋ 1, convert-hwp5์FILE_WRITE_FAILED๋ ์ฐ๊ธฐยทํ์ stat ์คํจ ๋ชจ๋ 2์ด๋ค. -
Python ํ์ผ I/O๋
HwpForgeError+OSError๊ณ์ธต๊ณผ ์ ๋ ฅ ๋ถ์ฌ ํ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค. ๊ด์ญ catchยทOS ํ๋ยทcopyยทpickle์ ๋ณด์กดํ๋ฉฐ ์ ํํ ํ์ ๋น๊ตยทPermissionErrorํฌ์ฐฉ์๋ ๋ณ๊ฒฝ์ด ์๋ค. ๋ถ๋ชจ ๋๋ ํฐ๋ฆฌ๊ฐ ์๋Document.save๋FileNotFoundError๋์HwpForgeIOError๋ก ํฌ์ฐฉํด์ผ ํ๋ค. -
to-pdfยทconvert-hwp5์ HWP5 ๋์ฝ๋ ์คํจ๋
HWP5_CONVERT_FAILED๋์HWP5_DECODE_FAILED๋ฅผ ์ถ๋ ฅํ๋ค. convert-hwp5 ์ถ๋ ฅ ์ฐ๊ธฐ ์คํจ๋FILE_WRITE_FAILED, to-md ์ ๋ ฅ ์คํจ๋FILE_NOT_FOUNDยทFILE_READ_FAILEDยทINPUT_TOO_LARGE๋ก ๊ตฌ๋ถํ๋ค. ์๋ ๋ I/O ๋ณ๊ฒฝ๊ตฐ ์ธ์ ์ข ๋ฃ ๊ฐ์ ์ ์งํ๋ค. -
MCP ์ง๋ ฌํ ์คํจ
SERIALIZE_ERRORยทSTAMP_MANIFEST_SERIALIZE๋JSON_SERIALIZE_FAILED๋ก ํตํฉํ๋ค. -
CLI ๊ตฌ์กฐ ํธ์ง์
UNCARRIED_ZIP_ENTRIES๋INPUT_ENTRIES_NOT_CARRIED,STRUCTURAL_EDIT_FAILED๋ ๊ตฌ์ฒด ๋๋ฉ์ธ ์ฝ๋ ๋๋UPSTREAM_UNMAPPED๋ก ์ ๋ฌํ๋ค. -
set-cellยทstamp์ ์๋ฏธ ์์ค์
SET_CELL_CODEC_FAILEDยทSTAMP_CODEC_FAILED๋์ENCODE_SEMANTIC_LOSS์ด๋ค. -
patchยทfill์ ์ค๋ฅ๋ฅผ ์คํจ ๋จ๊ณ์ ์์ธ์ผ๋ก ๋๋๋ค. ์ ๊ตฌ ๊ฒ์ฌ๋ฅผ ํต๊ณผํ ๋ค ์๋ณธ์ ์ฝ๊ฑฐ๋ decode ํ์ง ๋ชปํ๋ฉดPATCH_FAILEDยทFILL_FAILED๋์DECODE_FAILED๋ค. ํธ์งํ ๋ฌธ์์ ๊ฒ์ฆ ์คํจ๋VALIDATION_FAILED, ์ถ๋ ฅ ์์ฑ ์คํจ๋ENCODE_FAILED, ๋ณดํธ ํ๋์ ๊ฐยท๋ฒ์ ๋ณ๊ฒฝ์PROTECTED_FIELD_RANGE, ๋ด๋ถ source mapยท์์น ๋ถ๋ณ์ ํ์์INTERNAL_INVARIANT๋ค.PATCH_FAILED๋ ๋ณด์กด patch ๊ฐ ๋ฐ์ง ์๋ ๋ณ๊ฒฝ๊ณผ metadata ๋ถ์ฌยท๋ถ์ผ์น์๋ง,FILL_FAILED๋ ํ๋ ๋ชฉ๋ก ์ง๋จ์๋ง ๋จ๋๋ค. -
fill์ ๋ด๋ถ patch ์ ์์ธ์ ๊ทธ๋๋ก ์ ๋ฌํ๋ฏ๋กPATCH_FAILED๋ ๋ผ ์ ์๋ค(์: ๋ค์ ๋ง๋ค ์ ์๋ ์ธ๋ผ์ธ ํ์ง๊ฐ ๋ ์นธ). ๊ฒ์ฌ ์์๋ ๊ทธ๋๋ก๋ผ metadata ๊ฐ ์๊ณ XML ๋ ์์๋ patch ๋ ๊ณ์PATCH_FAILED๋ค. CLI ์ข ๋ฃ ๊ฐ์ ๋ ๋ช ๋ น ๋ชจ๋ ๋ฐ๋ ์ฝ๋์์๋ ์ด์ PATCH_FAILEDยทFILL_FAILED์ ๊ฐ์ 2 ๋ค(patch ์ ๊ตฌ์ญ ๋ฒ์ ๊ฑฐ๋ถSECTION_OUT_OF_RANGE1 ์ ๊ทธ๋๋ก). -
convert-hwp5ยทto-pdf(CLI)์ Pythonconvert_hwp5ยทto_pdf์ HWP5 ๋ณํ ์คํจ๋ ๋จ๊ณ๋ณ ์ฝ๋๋ฅผ ๋ธ๋ค. ์ฝ์ ๋ฌธ์์ Core ๊ฒ์ฆ ์คํจ๋VALIDATION_FAILED, HWPX ์ถ๋ ฅ ์์ฑ ์คํจ๋ENCODE_FAILED์ด๊ณ , ๋์ฝ๋๊ฐ ์ค์ค๋ก ๊ฑฐ๋ถํ ์คํ์ผยทํ ๋๋ฆฌ ์ฐธ์กฐ(์: ์ ์๊ฐ ์๋ ํ ํ ๋๋ฆฌ ๋ฒํธ)๋HWP5_CONVERT_FAILED๋์HWP5_DECODE_FAILED๋ค.HWP5_CONVERT_FAILED๋ ์์ฑํ ํจํค์ง์ ์ค ๋ฐฐ์น ์ ๋ณด๋ฅผ ๋ค์ ์ ํ๋ ๋จ๊ณ์๋ง ๋จ๋๋ค. ๋ CLI ๋ช ๋ น์ ์ข ๋ฃ ๊ฐ์ ๋ฐ๋ ์ฝ๋์์๋ ์ด์ ๊ณผ ๊ฐ์ 2 ์ด๊ณ , ํํธ๋ ๊ทธ๋๋ก๋ค. Pythonconvert_hwp5ยทDocument.to_pdf์์๋ ๋์ฝ๋๊ฐ ๊ฑฐ๋ถํ ์ฐธ์กฐ์ ํํธ๊ฐ ์ฝ๋๋ฅผ ๋ฐ๋ผCheck that the source is a supported HWP5 document์์Check that the file is a valid HWP5 document๋ก ๋ฐ๋๋ค(๊ฒ์ฆยท์ถ๋ ฅ ์์ฑ ์คํจ์ ํํธ๋ ๊ทธ๋๋ก).
I/O์ validate์ ์ข ๋ฃ ๊ฐ ๋ณ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ๋ค. ํธ์ง๊ธฐ์ ๋ค ๋ณ๊ฒฝ๊ตฐ์ ์ ํ์ ์ ์๋ค.
| ๋ช ๋ นยท์คํจ | ์ด์ ์ฝ๋ยท์ข ๋ฃ | 0.18 ์ฝ๋ยท์ข ๋ฃ |
|---|---|---|
| to-mdยทconvert-hwp5์ ํฌ๊ธฐ ํ๋๋ฅผ ๋๋ FIFO ์ ๋ ฅ | DECODE_FAILEDยทHWP5_DECODE_FAILED / 2 |
INPUT_TOO_LARGE / 1 |
| convert-hwp5์ ์ฐ๊ธฐ ์ฑ๊ณต ์งํ stat ์คํจ | FILE_WRITE_FAILED / 1 |
FILE_WRITE_FAILED / 2 |
| validate: ํ์๋ ํต๊ณผํ๊ณ Core ์ค์ฒฉ ๊น์ด๊ฐ 32 ๋ฅผ ๋๋ HWPX | ํ์ (valid:false) / 3 |
DECODE_FAILED / 2 |
validate๋ ํ์๋ ํต๊ณผํ์ง๋ง Core ์ค์ฒฉ ๊น์ด๊ฐ 32 ๋ฅผ ๋๋ HWPX ์์ ํ์ (valid:false) ๋์DECODE_FAILED๋ก ์คํจํ๋ค. HWPX decode ์ง์ ์ ์ด ์ด ๊น์ด๋ฅผ ๊ฑฐ๋ถํ๊ธฐ ๋๋ฌธ์ด๋ฉฐ(์ค๋ฅ E4008), ํ์ ํ๋(ํ ์ค์ฒฉยทXML ์์ฐ)์ ๊ฑธ๋ฆฐ ๋ฌธ์๋ 0.17.1 ์์๋DECODE_FAILED์์ผ๋ฏ๋ก ๊ทธ๋๋ก๋ค. ์ดํ: Rust ops ์validate๋Ok(ValidateOutput { ok: false, .. })๋์Err๋ฅผ ๋ฐํํ๊ณ , MCPhwpforge_validate๋valid:false๋ฐ์ดํฐ ๋์ ๋๊ตฌ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ฉฐ, PythonDocument.validate()๋ok: False๋ฅผ ๋๋ ค์ฃผ์ง ์๊ณ ์ฝ๋DECODE_FAILED์HwpForgeError๋ฅผ ์ผ์ผํจ๋ค. CLI ๋ stdout ํ์ ๊ณผ ์ข ๋ฃ 3 ๋์ stderr ์DECODE_FAILED์ ์ข ๋ฃ 2 ๋ฅผ ๋ธ๋ค. ๊น์ด ์ด๊ณผ๋ฅผ ํ์ ์ผ๋ก ๋ฐ๋ ํธ์ถ๋ถ๋ ์ค๋ฅ ๊ฒฝ๋ก์์ ์ฒ๋ฆฌํ๋ค.- HWPX์์ ์ฝ์ ๋ณธ๋ฌธ์ CR์ด
\r๋์\n์ผ๋ก ๋์จ๋ค(to-json, Python, MCP, ๋ฌด์์ค Markdown). ์ดํ:\r์ ๊ธฐ๋๋ ์ฝ๋๋ฅผ ๊ณ ์น๊ณ , 0.17์์ ๋ด๋ณด๋ธ ๋ณด์กด metadata ์ค CR์ด ๋ ์นธ์ด ์์ผ๋ฉด ๋ค์ ๋ด๋ณด๋ธ ๋ค patchํ๋ค. ์์ธํ ๊ฒ์hwpforge-smithy-hwpxํญ๋ชฉ์ ๋ณธ๋ค.
Changed
hwpforge-*ํฌ๋ ์ดํธ๋ผ๋ฆฌ์ ์์กด ์๊ตฌ๊ฐ"0"(0.x ์๋ฌด ๋ฒ์ ) ๋์ ๋ฆด๋ฆฌ์ค ๋ฒ์ (์:"0.18.0")์ ์ต์ ๋ฒ์ ์ผ๋ก ์๊ตฌํ๋ค. ๊ทธ๋์ cargo ๊ฐ ์ด ์์กด์ ๋ค๋ฅธhwpforge-*ํฌ๋ ์ดํธ์ ์ด์ minor ๋ฅผ ๊ณ ๋ฅด์ง ์๋๋ค.hwpforge-*๋ฅผ ์ง์ ์ฌ๋ฌ ๊ฐ ์์กดํ๋ค๋ฉด ํจ๊ป ์ฌ๋ฆฐ๋ค.INPUT_NOT_ROUNDTRIP_SAFEํํธ๋ ์ฝ๋ฑ ๊ฐญ ์์ ๋๊ธฐ ์๋ด ๋์ ์๋ณธ์ ๋ณด์กดํ๋ ํ ์คํธto-json(section) โ patchยท๋๋ฆํfill๊ฒฝ๋ก๋ฅผ ์๋ดํ๋ค. MCP stamp๋ ํด๋น ๋๊ตฌ ์ด๋ฆ์ผ๋ก ๊ฐ์ ์๋ด๋ฅผ ์ ๊ณตํ๋ค.
Fixed
convert(CLIยทMCPยทPythonconvert_md)๊ฐ Markdown ์ ๋์์ด ๋น ์ด๋ฏธ์ง(![x]())๋ฅผ 0.17.0 ์ฒ๋ผIMAGE_EMBED_SKIPPED๊ฒฝ๊ณ ์ ํจ๊ป ๋บ๋ค. 0.17.1 ์์๋ ๊ฒฝ๊ณ ์์ด 50ร30mm ๋น ๊ทธ๋ฆผ ํ๋ก ๋จ์๋ค. ํ์ปด์ด ์์ฐ์ ์์ ์ฑ ์ ์ฅํ ๊ทธ๋ฆผ ํ(#266)์ ๊ทธ๋๋ก ๋จ๋๋ค.- HWPX ๊ตฌ์ญ(
<hs:sec>) ๋ฐ๋ก ์๋์ ๋์ฌ ์ฝ์ง ๋ชปํ๋ ๊ธยท์์ยท<hp:t>๋ฅผCONTENT_LOST (section_content)๊ฒฝ๊ณ ๋ก ์๋ฆฌ๊ณ ,restyleยทset-cellยทstamp๋ ๊ทธ๋ฐ ๋ฌธ์๋ฅผ ๊ฑฐ๋ถํ๋ค. ์ ์๋ ๊ฒฝ๊ณ ์์ด ๊ทธ ๊ธ์ ๋บ๋ค. ์์ธํ ๊ฒ์hwpforge-smithy-hwpxํญ๋ชฉ์ ๋ณธ๋ค. - HWP ๋ฌถ์ ์ ๊ทธ๋ฆผ์ ํ
๋๋ฆฌ ์์ค ๊ฒฝ๊ณ ๊ฐ ์์ค์ ํ์ ํ ์ ์ข
๋ฅ๋ฅผ ํจ๊ป ์ ๋๋ค(
border: line type 2, thickness 0). ์ ์๋ ๋๊ป๋ง ์ ์ด, ๋๊ป 0 ์ธ ํ ๋๋ฆฌ๊ฐ ์ ์์ค์ธ์ง ๋ณด์ด์ง ์์๋ค(#256 ํ์).
์ ๊ทธ๋ ์ด๋ ์ฃผ์
- HWP ๋ณํ์ ๊น์ด ์ด๊ณผ: HWP5 ๋์ฝ๋๋ ์ปจํ
์ด๋๋ง๋ค ๊น์ด๋ฅผ 1์ฉ ์ธ์ด 32์์ ๋ฉ์ถ์ง๋ง Core ๋ ์บก์
ยท๋ฌถ์ ์ ๋ํ์ ํ ๊ฒน์ 2 ์ด์์ผ๋ก ์ผ๋ค. ๊ทธ๋์ ๋์ฝ๋ ์ํ ์์ HWP ๋ฌธ์๋ Core ๊น์ด 32๋จ๊ณ๋ฅผ ๋์ผ๋ฉด
convert-hwp5ยทto-pdf์ Pythonconvert_hwp5๊ฐVALIDATION_FAILED๋ก ์คํจํ ์ ์๋ค. 0.17.1 ์ ๊น์ด ํ๋(#267)๊ฐ HWP ๋ณํ์๋ ๊ฑธ๋ฆฐ๋ค๋ ๋ป์ด๋ค. ์ค์ HWP ๋ฌธ์์์ ์ด๋ ๊ฒ ์คํจํ๋ ๊ฒฝ์ฐ๋ ์ธก์ ํ์ง ์์๋ค. - ์คํฌ ์์น (#270, 0.17.1): ์ ์ฅ์์ ์์ด์ ํธ ์คํฌ์ด
.claude/skills/์์skills/๋ก ์ฎ๊ฒจ์ก๋ค. 0.17.1 CHANGELOG ์ ๋น ์ก๋ ํญ๋ชฉ์ด๋ค.