diff --git a/docs/architecture/module-ownership.json b/docs/architecture/module-ownership.json index b101ebb3..efb8f82b 100644 --- a/docs/architecture/module-ownership.json +++ b/docs/architecture/module-ownership.json @@ -427,13 +427,13 @@ "path": "src/hwpx/oxml/version_part.py", "disposition": "core", "approvedBy": "cycle-6.4/part-hierarchy-read-models", - "rationale": "version.xml (hv:HCFVersion) read model — same settings.py-idiom package/OXML part parsing, no application workflow or policy. Reverse-engineered from the full vendored corpus (47/47); the vendored 2024-draft OWPML schema's root name/namespace do not match real output" + "rationale": "version.xml (hv:HCFVersion) read model — same settings.py-idiom package/OXML part parsing, no application workflow or policy. Inferred from the full vendored corpus (47/47); the vendored 2024-draft OWPML schema's root name/namespace do not match real output" }, { "path": "src/hwpx/oxml/master_page.py", "disposition": "core", "approvedBy": "cycle-6.4/part-hierarchy-read-models", - "rationale": "masterpage.xml (unnamespaced masterPage root) read model — same settings.py-idiom package/OXML part parsing, no application workflow or policy. Reverse-engineered from the one real corpus example; the vendored 2024-draft OWPML schema's namespace does not match real output" + "rationale": "masterpage.xml (unnamespaced masterPage root) read model — same settings.py-idiom package/OXML part parsing, no application workflow or policy. Inferred from the one real corpus example; the vendored 2024-draft OWPML schema's namespace does not match real output" }, { "path": "src/hwpx/oxml/history_part.py", @@ -499,7 +499,7 @@ "path": "src/hwpx/oxml/document_metadata.py", "disposition": "core", "approvedBy": "cycle-6.12/train-48-document-metadata", - "rationale": "Contents/content.hpf's opf:metadata (title/creator/subject/description/keyword/lastsaveby/CreatedDate/ModifiedDate/date) read model -- same schema-undeclared-part idiom as settings.py/version_part.py (67-fixture real-corpus reverse engineering is the truth source, not the OWPML schema, since opf:/dc: metadata isn't HWPML at all). The write side lives on HwpxPackage itself (opc/package.py), not here, since it must share the exact manifest_tree()/_persist_manifest() object add_manifest_item/remove_manifest_item already use" + "rationale": "Contents/content.hpf's opf:metadata (title/creator/subject/description/keyword/lastsaveby/CreatedDate/ModifiedDate/date) read model -- same schema-undeclared-part idiom as settings.py/version_part.py (67-fixture real-corpus format inference is the truth source, not the OWPML schema, since opf:/dc: metadata isn't HWPML at all). The write side lives on HwpxPackage itself (opc/package.py), not here, since it must share the exact manifest_tree()/_persist_manifest() object add_manifest_item/remove_manifest_item already use" }, { "path": "src/hwpx/oxml/drop_cap.py", @@ -517,13 +517,13 @@ "path": "src/hwpx/oxml/master_page_authoring.py", "disposition": "core", "approvedBy": "cycle-6.13/train-48-master-page-write", - "rationale": "add_master_page (Contents/masterpageN.xml part creation + opf:item manifest registration, no spine itemref needed since master pages aren't reading-order parts) -- opens the write side HwpxOxmlMasterPage's own docstring explicitly deferred (read-only, cycle 6.4 train 15's read=none resolution scope). New module from the start rather than added inline to document_parts.py (only ~82 lines of headroom there, this needed more to build safely without repeating header_part.py's mid-train overflow). Reverse-engineered from the single real master-page sample (error__20250808__...hwpx): the part filename, manifest opf:item id, masterPage root's own id, and a section's hp:masterPage/@idRef all share one string (\"masterpageN\"); textWidth/textHeight on the inner hp:subList stay at the honest \"0\" default (same as every other subList builder) since a single sample gives no basis to reverse the page-geometry formula the real value came from. Section-side reference wiring (hp:masterPage/@idRef append + masterPageCnt sync) lives in section_format.py instead (SectionProperties.add_master_page_reference), not here, since it needs no new module of its own" + "rationale": "add_master_page (Contents/masterpageN.xml part creation + opf:item manifest registration, no spine itemref needed since master pages aren't reading-order parts) -- opens the write side HwpxOxmlMasterPage's own docstring explicitly deferred (read-only, cycle 6.4 train 15's read=none resolution scope). New module from the start rather than added inline to document_parts.py (only ~82 lines of headroom there, this needed more to build safely without repeating header_part.py's mid-train overflow). Inferred from the single real master-page sample (error__20250808__...hwpx): the part filename, manifest opf:item id, masterPage root's own id, and a section's hp:masterPage/@idRef all share one string (\"masterpageN\"); textWidth/textHeight on the inner hp:subList stay at the honest \"0\" default (same as every other subList builder) since a single sample gives no basis to reverse the page-geometry formula the real value came from. Section-side reference wiring (hp:masterPage/@idRef append + masterPageCnt sync) lives in section_format.py instead (SectionProperties.add_master_page_reference), not here, since it needs no new module of its own" }, { "path": "src/hwpx/oxml/field_marks.py", "disposition": "core", "approvedBy": "cycle-6.13/train-48-date-field-proofreading-mark", - "rationale": "add_date_field (hp:fieldBegin type=DATE) + add_proofreading_mark (hp:fieldBegin type=PROOFREADING_MARKS_SIGN) -- paragraph.py's shape/field-authoring overflow destination hit exactly 1600 lines with the two thin delegator methods added (zero headroom left, flagged as a next-cycle chip: this file needs a real extraction pass before more paragraph-level authoring lands). Reverse-engineered from team-lead's real-Hancom GUI probe gold samples (not vendored corpus -- synthetic, scratch-path only), unlike add_hyperlink's established 3-run charPr-isolation pattern, both fields pack ctrl/t children into a single run (matches the observed gold structure exactly; no isolation needed since neither field's display text carries special formatting). DATE field scope is deliberately narrow: only the one observed date_format (\"YYYY년 M월 D일\") is supported since its Command preview-string convention can't be reverse-engineered from a single sample, and cached_text is caller-supplied (this module is not a date formatter). Proofreading-mark field similarly narrows to the one confirmed $RevisionSign index (mark=\"space\"=1) out of the real dialog's 21 total kinds. A genuine schema-vs-reality deviation surfaced during this reverse-engineering: the schema declares FieldType=PROOFREADING_MARKS but real Hancom emits PROOFREADING_MARKS_SIGN -- registered as DEV-043 in docs/owpml-deviations.md. 6.14 train 48/debt3 later added add_path_field (type=PATH) as a third class-attribute delegator here (no new module needed for it -- this file still had headroom)" + "rationale": "add_date_field (hp:fieldBegin type=DATE) + add_proofreading_mark (hp:fieldBegin type=PROOFREADING_MARKS_SIGN) -- paragraph.py's shape/field-authoring overflow destination hit exactly 1600 lines with the two thin delegator methods added (zero headroom left, flagged as a next-cycle chip: this file needs a real extraction pass before more paragraph-level authoring lands). Inferred from team-lead's real-Hancom GUI probe gold samples (not vendored corpus -- synthetic, scratch-path only), unlike add_hyperlink's established 3-run charPr-isolation pattern, both fields pack ctrl/t children into a single run (matches the observed gold structure exactly; no isolation needed since neither field's display text carries special formatting). DATE field scope is deliberately narrow: only the one observed date_format (\"YYYY년 M월 D일\") is supported since its Command preview-string convention can't be inferred from a single sample, and cached_text is caller-supplied (this module is not a date formatter). Proofreading-mark field similarly narrows to the one confirmed $RevisionSign index (mark=\"space\"=1) out of the real dialog's 21 total kinds. A genuine schema-vs-reality deviation surfaced during this format inference: the schema declares FieldType=PROOFREADING_MARKS but real Hancom emits PROOFREADING_MARKS_SIGN -- registered as DEV-043 in docs/owpml-deviations.md. 6.14 train 48/debt3 later added add_path_field (type=PATH) as a third class-attribute delegator here (no new module needed for it -- this file still had headroom)" }, { "path": "src/hwpx/oxml/note_authoring.py", diff --git a/docs/openrate/report-v18.json b/docs/openrate/report-v18.json index 43b0f283..31708db5 100644 --- a/docs/openrate/report-v18.json +++ b/docs/openrate/report-v18.json @@ -14,7 +14,7 @@ "oracle": "mac-gui", "oracle_app": "Hancom Office HWP.app (macOS)", "schemaVersion": "hwpx.openrate.report/v18", - "scopeNote": "v18 measures the two field surfaces this cycle reverse-engineered directly from real Hancom through GUI probes -- the date/time field and the proofreading-mark field -- additive over v1-v17. Both contracts came from documents the editor itself produced (menu-driven insertion, then structural diff), so this batch closes the loop: engine output measured against the same editor that defined the contract. Real Hancom accepted all 10/10. The third surface probed this cycle (titleMark, behind 차례 숨기기/제목 차례 표시) has no stratum here on purpose -- its authoring stayed deferred because the caret-targeting rule could not be measured on this platform (DEV-044). Observer: macOS Hancom GUI oracle (open+render one gate). Session-state discipline applied: a control render preceded the batch and the app was fully restarted before launch.", + "scopeNote": "v18 measures the two field surfaces this cycle inferred directly from real Hancom through GUI probes -- the date/time field and the proofreading-mark field -- additive over v1-v17. Both contracts came from documents the editor itself produced (menu-driven insertion, then structural diff), so this batch closes the loop: engine output measured against the same editor that defined the contract. Real Hancom accepted all 10/10. The third surface probed this cycle (titleMark, behind 차례 숨기기/제목 차례 표시) has no stratum here on purpose -- its authoring stayed deferred because the caret-targeting rule could not be measured on this platform (DEV-044). Observer: macOS Hancom GUI oracle (open+render one gate). Session-state discipline applied: a control render preceded the batch and the app was fully restarted before launch.", "strata": { "authored-date-field": { "judged": 5, diff --git a/docs/openrate/report-v19.json b/docs/openrate/report-v19.json index e5740f92..dbf99a82 100644 --- a/docs/openrate/report-v19.json +++ b/docs/openrate/report-v19.json @@ -14,7 +14,7 @@ "oracle": "mac-gui", "oracle_app": "Hancom Office HWP.app (macOS)", "schemaVersion": "hwpx.openrate.report/v19", - "scopeNote": "v19 measures the PATH (file name) field surface, additive over v1-v18 -- the last of the field trio this cycle group reverse-engineered, and the first batch whose records carry the fieldEnd fieldid retrofit (a gold byte-comparison find: real Hancom accepted v18's output without it, so acceptance alone could never have caught it). Real Hancom accepted all 5/5. Observer: macOS Hancom GUI oracle (open+render one gate). Session-state discipline applied: a control render preceded the batch and the app was fully restarted before launch.", + "scopeNote": "v19 measures the PATH (file name) field surface, additive over v1-v18 -- the last of the field trio this cycle group inferred, and the first batch whose records carry the fieldEnd fieldid retrofit (a gold byte-comparison find: real Hancom accepted v18's output without it, so acceptance alone could never have caught it). Real Hancom accepted all 5/5. Observer: macOS Hancom GUI oracle (open+render one gate). Session-state discipline applied: a control render preceded the batch and the app was fully restarted before launch.", "strata": { "authored-path-field": { "judged": 5, diff --git a/probes/dev004_settings_xml_no_schema.py b/probes/dev004_settings_xml_no_schema.py index feb0d244..5daa8c15 100644 --- a/probes/dev004_settings_xml_no_schema.py +++ b/probes/dev004_settings_xml_no_schema.py @@ -15,7 +15,7 @@ OpenDocument Format 1.0* config schema, verbatim, not a Hancom-private vocabulary. -Our handling: ``hwpx.oxml.settings`` was reverse-engineered directly from +Our handling: ``hwpx.oxml.settings`` was inferred directly from 177 real files (no schema to check against) — ``ApplicationSettings``, ``CaretPosition``, ``ConfigItem``/``ConfigItemSet`` preserve whatever config-item-set/item names and types actually appear rather than diff --git a/probes/dev023_label_avery_layout_schema_match.py b/probes/dev023_label_avery_layout_schema_match.py index 6223d80c..08e105be 100644 --- a/probes/dev023_label_avery_layout_schema_match.py +++ b/probes/dev023_label_avery_layout_schema_match.py @@ -18,7 +18,7 @@ documents when the vendored 47-file corpus has no examples (documented practice, see ``docs/_extra/element-census.json``'s populationNote -- the private corpus's path is deliberately not recorded anywhere, including -here, for privacy). That reverse-engineering (75 files, 436 real +here, for privacy). That format inference (75 files, 436 real ``hp:label`` occurrences) found: (a) the parent is always ``hp:tbl`` (436/436), always as the table's *last* child (spot-checked across several files, matching the schema's own sequence position); (b) all 11 diff --git a/probes/dev038_toc_fiexde_typo_replication.py b/probes/dev038_toc_fiexde_typo_replication.py index 31fae547..9a52f7a8 100644 --- a/probes/dev038_toc_fiexde_typo_replication.py +++ b/probes/dev038_toc_fiexde_typo_replication.py @@ -3,7 +3,7 @@ replicates Hancom's own spelling verbatim -- the same typo-replication class as DEV-004/DEV-009/DEV-026 but in a third subsystem (page cross-reference field parameters, discovered via a different path -- -the M7 native-TOC train's gold-corpus reverse engineering rather than a general census +the M7 native-TOC train's gold-corpus format inference rather than a general census sweep). Despite the module-level docstring's phrasing ("TOC field parameter spelling"), the parameter itself is emitted by ``add_page_crossref`` (CROSSREF), not ``add_native_toc``. diff --git a/scripts/generate_openrate_corpus_v10.py b/scripts/generate_openrate_corpus_v10.py index d86b3db3..9e7f6278 100644 --- a/scripts/generate_openrate_corpus_v10.py +++ b/scripts/generate_openrate_corpus_v10.py @@ -5,7 +5,7 @@ Why v10 exists =============== -Cycle 6.6 (train 23) opened one new authoring surface, reverse-engineered +Cycle 6.6 (train 23) opened one new authoring surface, inferred from real corpus and exposed as ``doc.parts.set_*`` (``src/hwpx/oxml/header_compat.py``): ``hh:compatibleDocument/ @targetProgram``, ``hh:compatibleDocument/hh:layoutCompatibility``'s flag diff --git a/scripts/generate_openrate_corpus_v11.py b/scripts/generate_openrate_corpus_v11.py index 9b7aef8a..fb5f5b68 100644 --- a/scripts/generate_openrate_corpus_v11.py +++ b/scripts/generate_openrate_corpus_v11.py @@ -7,7 +7,7 @@ Cycle 6.7 (train 26) opened one new authoring surface -- ``HwpxOxmlTable. set_label``/``.label``/``.remove_label`` (``src/hwpx/oxml/body.py``, -``src/hwpx/oxml/table.py``) -- reverse-engineered from the maintainer's +``src/hwpx/oxml/table.py``) -- inferred from the maintainer's private real-world corpus (DEV-023, docs/owpml-deviations.md), since the 47-file vendored corpus has zero real ``hp:label`` samples. That private corpus's path is never recorded anywhere (including here); every value diff --git a/scripts/generate_openrate_corpus_v13.py b/scripts/generate_openrate_corpus_v13.py index 8bb798be..4354bcdb 100644 --- a/scripts/generate_openrate_corpus_v13.py +++ b/scripts/generate_openrate_corpus_v13.py @@ -23,7 +23,7 @@ Train 34 shipped ``hp:dutmal``(덧말)/``hp:compose``(글자 겹치기) authoring (``doc.shapes.add_dutmal``/``.add_composed_character``) -- ``hp:compose``'s read model existed since ``6f88e2e`` with no authoring API or capability -registration; ``hp:dutmal`` was reverse-engineered here for the first time, +registration; ``hp:dutmal`` was inferred here for the first time, from a single real-corpus sample whose ``option``/``szRatio`` values directly contradict the schema's own declared constraints (DEV-041). ``authored-dutmal-compose`` is this area's first real-Hancom batch. diff --git a/scripts/generate_openrate_corpus_v16.py b/scripts/generate_openrate_corpus_v16.py index 15ce95f2..2ec365db 100644 --- a/scripts/generate_openrate_corpus_v16.py +++ b/scripts/generate_openrate_corpus_v16.py @@ -18,7 +18,7 @@ width/height variant, proving the TripleLine builder isn't hardcoded to the single real-corpus example it was - reverse-engineered from. + inferred from. * ``authored-text-direction`` 5 ``doc.page.set_text_direction`` -- VERTICAL/VERTICALALL/explicit- HORIZONTAL combined with @@ -407,7 +407,7 @@ def main() -> int: "authored by train 48 across 4 commits) -- authored-document-" "metadata (doc.parts.set_document_metadata, opf:metadata's " "first real-Hancom batch), authored-drop-cap (doc.shapes." - "add_drop_cap, TripleLine dropcapstyle reverse-engineered from " + "add_drop_cap, TripleLine dropcapstyle inferred from " "the single real-corpus example that used it), authored-text-" "direction (doc.page.set_text_direction, zero real-corpus " "VERTICAL/VERTICALALL examples existed before this batch), " diff --git a/scripts/generate_openrate_corpus_v9.py b/scripts/generate_openrate_corpus_v9.py index 13dcde4e..ca306b6a 100644 --- a/scripts/generate_openrate_corpus_v9.py +++ b/scripts/generate_openrate_corpus_v9.py @@ -4,7 +4,7 @@ Why v9 exists ============= -Cycle 6.5 (trains 18-19) opened two new authoring surfaces, reverse-engineered +Cycle 6.5 (trains 18-19) opened two new authoring surfaces, inferred from real corpus: ``doc.shapes.add_container`` (grouping already-built rect/ellipse/polygon members into an ``hp:container``, train 18) and ``paragraph.add_run(text, expand_special_characters=True)`` (converting diff --git a/src/hwpx/_document/fields.py b/src/hwpx/_document/fields.py index 31c7f85d..9c13e9c9 100644 --- a/src/hwpx/_document/fields.py +++ b/src/hwpx/_document/fields.py @@ -663,7 +663,7 @@ def add_form_field( """Create a click-here (누름틀) form field and return it as a :class:`FormField`. The emitted XML follows the real-Hancom CLICKHERE contract - (reverse-engineered from Hancom Office 12.0.0.3288 gold documents). The + (inferred from Hancom Office 12.0.0.3288 gold documents). The prompt (안내문) is materialized as a screen-only red-italic run, exactly as Hancom authors it. The created field is immediately re-read through the standard ``list_form_fields`` matcher — creation fails loudly if the diff --git a/src/hwpx/_document/shapes.py b/src/hwpx/_document/shapes.py index cef335c8..54836189 100644 --- a/src/hwpx/_document/shapes.py +++ b/src/hwpx/_document/shapes.py @@ -764,10 +764,10 @@ def add_drop_cap( char_pr_id_ref: str | int | None = None, para_pr_id_ref: str | int | None = None, ) -> HwpxOxmlInlineObject: - """Insert a drop cap (문단 첫 글자 장식), reverse-engineered from the one + """Insert a drop cap (문단 첫 글자 장식), inferred from the one real-corpus example that carries a non-default ``dropcapstyle`` (``error__20230809__test.hwpx`` -- see ``oxml.drop_cap``'s own - docstring for the full structural reverse engineering and why it + docstring for the full structural format inference and why it supports ``style="TripleLine"`` and ``"DoubleLine"`` only). Element construction (element-building validation included) happens in diff --git a/src/hwpx/oxml/body.py b/src/hwpx/oxml/body.py index 5b6eaf1a..28f3a0ad 100644 --- a/src/hwpx/oxml/body.py +++ b/src/hwpx/oxml/body.py @@ -162,10 +162,10 @@ class Label: always the *last* child of ``hp:tbl`` (real corpus: always after every ``hp:tr`` row, matching ``ParaList XML schema.xml``'s own sequence order -- DEV-023, ``docs/owpml-deviations.md``). Unlike most elements - this registry has reverse-engineered, the schema and 75 real private + this registry has inferred, the schema and 75 real private documents agree completely: all 11 attributes here, no more, no fewer, ``landscape`` the only non-integer one (schema enum ``WIDELY``/ - ``NARROWLY``, only ``WIDELY`` observed in the reverse-engineering + ``NARROWLY``, only ``WIDELY`` observed in the format inference sample -- ``NARROWLY`` is schema-legal but unconfirmed against real output).""" @@ -1378,7 +1378,7 @@ def _table_to_xml(table: Table) -> etree._Element: def _label_to_xml(label: Label) -> etree._Element: # Attribute order matches ParaList XML schema.xml's declared sequence, - # which every real occurrence (436/436, private reverse-engineering + # which every real occurrence (436/436, private format inference # sample) also follows -- see DEV-023. attrs: Dict[str, str] = {} _set_int_attr(attrs, "topmargin", label.topmargin) diff --git a/src/hwpx/oxml/dutmal_compose.py b/src/hwpx/oxml/dutmal_compose.py index 09c3773b..9d766d76 100644 --- a/src/hwpx/oxml/dutmal_compose.py +++ b/src/hwpx/oxml/dutmal_compose.py @@ -101,7 +101,7 @@ def _paragraph_add_dutmal( ) -> HwpxOxmlInlineObject: """Insert ```` -- 덧말(루비형 주석 텍스트). - Low-confidence axis, honestly flagged: reverse-engineered from a + Low-confidence axis, honestly flagged: inferred from a *single* real-corpus sample (``reader_writer__SimpleDutmal.hwpx``), confirmed a first-class Hancom editor menu item by the macOS menu scan (editor surface inventory, cycle 6.8 train 29) but otherwise diff --git a/src/hwpx/oxml/paragraph.py b/src/hwpx/oxml/paragraph.py index 542742ba..2802b00c 100644 --- a/src/hwpx/oxml/paragraph.py +++ b/src/hwpx/oxml/paragraph.py @@ -1074,7 +1074,7 @@ def add_chart( ) -> HwpxOxmlInlineObject: """Insert a native ```` anchor referencing a chartML part. - Emits the real-Hancom chart anchor (contract reverse-engineered in + Emits the real-Hancom chart anchor (contract inferred in specs/055-chart-authoring/evidence/p0/chart-contract.md): the chart content lives in an ECMA-376 chartML part addressed directly by ``chartIDRef`` (real Hancom registers the part in no manifest), and @@ -1148,7 +1148,7 @@ def add_equation( ) -> HwpxOxmlInlineObject: """Insert an inline ```` carrying an EqEdit *script*. - Emits the real-Hancom equation shape (contract reverse-engineered in + Emits the real-Hancom equation shape (contract inferred in specs/054-equation-authoring/evidence/p0/equation-contract.md): the EqEdit source lives in the ```` child, no lineseg cache is written (Hancom re-lays-out on open), and the shape is inline @@ -1233,7 +1233,7 @@ def add_form_field( ) -> HwpxOxmlInlineObject: """Insert a click-here (누름틀) form field at the end of this paragraph. - Emits the real-Hancom CLICKHERE shape (reverse-engineered from Hancom + Emits the real-Hancom CLICKHERE shape (inferred from Hancom Office 12.0.0.3288 gold documents): a ``fieldBegin`` ctrl run carrying the ``Prop``/``Command``/``Direction``/ ``HelpState`` parameters, an optional prompt run showing *prompt* (the diff --git a/src/hwpx/oxml/table.py b/src/hwpx/oxml/table.py index a596952d..68e876f0 100644 --- a/src/hwpx/oxml/table.py +++ b/src/hwpx/oxml/table.py @@ -664,7 +664,7 @@ def remove_caption(self) -> bool: def label(self) -> "Label | None": """This table's ``hp:label`` (Avery-style label-sheet/nameplate print layout), or ``None`` if it doesn't have one. Table-exclusive - (DEV-023, ``docs/owpml-deviations.md`` — reverse-engineered from + (DEV-023, ``docs/owpml-deviations.md`` — inferred from 75 real private documents, structure matches the vendored schema exactly, no deviation to register beyond the element's existence).""" @@ -693,7 +693,7 @@ def set_label( Always placed as the table's *last* child -- every real occurrence (436/436, DEV-023) sits after all ``hp:tr`` rows, matching ``ParaList XML schema.xml``'s own sequence order. Values are not - restricted to the two combinations the reverse-engineering sample + restricted to the two combinations the format inference sample observed (a 2x9 small-label sheet and a 1x2 large-square nameplate layout) -- there is no real-corpus evidence for what other combinations Hancom accepts or rejects, so this does not guess at diff --git a/src/hwpx/tools/toc_author.py b/src/hwpx/tools/toc_author.py index b37308cd..dea6811c 100644 --- a/src/hwpx/tools/toc_author.py +++ b/src/hwpx/tools/toc_author.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 """Author Hancom-native TOC and page cross-reference fields. -Emits the exact field contract reverse-engineered from an owner-authored +Emits the exact field contract inferred from an owner-authored Hancom document (``specs/009-native-toc-xrefs/evidence/ p0-native-toc-xml-contract.md``; gold pair vendored in ``tests/fixtures/m7_toc_gold/``): diff --git a/tests/fixtures/m7_toc_gold/NOTICE.md b/tests/fixtures/m7_toc_gold/NOTICE.md index ba03cc98..606b6421 100644 --- a/tests/fixtures/m7_toc_gold/NOTICE.md +++ b/tests/fixtures/m7_toc_gold/NOTICE.md @@ -1,6 +1,6 @@ # m7_toc_gold — 한컴 네이티브 차례/상호참조 gold fixtures -Owner-authored in real Hancom (2026-07-02) for M7/S-062 P0 reverse-engineering. +Owner-authored in real Hancom (2026-07-02) for M7/S-062 P0 format inference. - `hancom-native-toc-A.hwpx` — 4 outline headings + native 제목차례 (TABLEOFCONTENTS field, entries fresh: pages 1,2,2,3) + 1 CROSSREF diff --git a/tests/test_document_metadata.py b/tests/test_document_metadata.py index d3edea87..61bea096 100644 --- a/tests/test_document_metadata.py +++ b/tests/test_document_metadata.py @@ -3,7 +3,7 @@ ``Contents/content.hpf``'s ``opf:metadata`` -- title/creator/subject/ keyword/CreatedDate/ModifiedDate read+write. -Real-corpus reverse-engineering (67 fixtures, see +Real-corpus format inference (67 fixtures, see ``hwpx.oxml.document_metadata``'s own docstring for the full census) found this block always shares the same shape, and that ``CreatedDate``/ ``ModifiedDate`` are single-format (ISO 8601) while ``date`` (the @@ -120,7 +120,7 @@ def test_setting_a_field_does_not_disturb_other_manifest_content() -> None: def test_real_corpus_metadata_is_readable_without_error() -> None: - """Sanity sweep over the real corpus this feature was reverse-engineered + """Sanity sweep over the real corpus this feature was inferred against -- every fixture must parse without raising, matching the census this module's docstring records (67/67 parsed ok).""" diff --git a/tests/test_drop_cap_authoring.py b/tests/test_drop_cap_authoring.py index dc851c3b..0e70ce35 100644 --- a/tests/test_drop_cap_authoring.py +++ b/tests/test_drop_cap_authoring.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 """Drop cap authoring (문단 첫 글자 장식, cycle 6.12 트레인㊸ 갭②). -Reverse-engineered from the ONE real-corpus example with a non-default +Inferred from the ONE real-corpus example with a non-default ``dropcapstyle`` (``error__20230809__test.hwpx``, hwpxlib_corpus), in ``style="TripleLine"`` and ``"DoubleLine"`` -- Hancom reads, draws and saves the second as it is. ``Margin`` is schema-declared but where Hancom @@ -212,7 +212,7 @@ def test_add_drop_cap_rejects_empty_character() -> None: def test_add_drop_cap_matches_the_real_corpus_structure() -> None: """Structural fidelity check against the one real sample this feature - was reverse-engineered from -- same attribute *names* on the rect and + was inferred from -- same attribute *names* on the rect and the same child element shape (not exact values, which are naturally instance-specific: ids, the character itself, size).""" diff --git a/tests/test_dutmal_compose_authoring.py b/tests/test_dutmal_compose_authoring.py index b4742322..7c6d1c0f 100644 --- a/tests/test_dutmal_compose_authoring.py +++ b/tests/test_dutmal_compose_authoring.py @@ -2,7 +2,7 @@ """덧말(hp:dutmal)·글자 겹치기(hp:compose) 저작 (cycle 6.9 train 34). ``hp:compose``'s read model shipped earlier (commit 6f88e2e); this covers -the authoring side plus the newly-reverse-engineered ``hp:dutmal`` (both +the authoring side plus the newly-inferred ``hp:dutmal`` (both read and write -- see docs/owpml-deviations.md DEV-041 for the schema mismatch its only real-corpus sample exposed). """ @@ -34,7 +34,7 @@ def _run_content(paragraph): # ============================================================================ -# real-corpus read model (locks the reverse-engineering in as a regression) +# real-corpus read model (locks the format inference in as a regression) # ============================================================================ diff --git a/tests/test_oxml_modularization.py b/tests/test_oxml_modularization.py index c33b375c..066350e4 100644 --- a/tests/test_oxml_modularization.py +++ b/tests/test_oxml_modularization.py @@ -256,13 +256,13 @@ def test_frozen_facade_exports_remain_exact() -> None: # CompatibleDocument (hh:layoutCompatibility/compatibleDocument) plus the # settings.xml first-ever read surface (ApplicationSettings, CaretPosition, # ConfigItem, ConfigItemSet, HwpxOxmlSettings) — settings.xml has no - # vendored OWPML schema at all, reverse-engineered from the real corpus. + # vendored OWPML schema at all, inferred from the real corpus. # 120 -> 122: Caption/DrawText fill gap #3/#4 (hp:drawText/textMargin, # hp:caption) — shared live views reused by HwpxOxmlShape, # HwpxOxmlInlineObject, and HwpxOxmlTable rather than duplicated per host. # 122 -> 127: gap #15's part-hierarchy read models — version.xml # (HcfVersion), masterpage.xml (MasterPage), and history.xml (History, - # HistoryEntry, DiffNode). version.xml/masterpage.xml are reverse-engineered + # HistoryEntry, DiffNode). version.xml/masterpage.xml are inferred # from the real corpus like settings.xml before them (and, like it, their # real roots/namespaces drifted from the vendored 2024-draft OWPML schema — # see version_part.py/master_page.py). history.xml has zero real examples diff --git a/tests/test_table_label.py b/tests/test_table_label.py index d1806e33..23512d5e 100644 --- a/tests/test_table_label.py +++ b/tests/test_table_label.py @@ -4,12 +4,12 @@ hp:label (Avery-style label-sheet/nameplate print layout) was the last code-blind high-frequency element the completeness ledger found (64/237 real files in the census population, 27%). The vendored 47-file corpus has -no examples -- structure was reverse-engineered from 75 of the +no examples -- structure was inferred from 75 of the maintainer's private real-world documents (school administrative paperwork). That private corpus's path is never recorded anywhere, including here (privacy) -- every value in this file is synthetic, not copied from any real document. See docs/owpml-deviations.md's DEV-023 -entry for the reverse-engineering evidence (schema/real-output agreement, +entry for the format inference evidence (schema/real-output agreement, the 2 observed attribute-combination clusters, the always-last-child position). """ diff --git a/tests/test_toc_author.py b/tests/test_toc_author.py index 4dc64dd1..c7ecec83 100644 --- a/tests/test_toc_author.py +++ b/tests/test_toc_author.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -"""Native TOC / CROSSREF emission per the reverse-engineered contract. +"""Native TOC / CROSSREF emission per the inferred contract. Emission is verified with the P1 harness (hwpx.tools.toc_fidelity) — the authoring surface and the fidelity harness agree by construction, mirroring