Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/architecture/module-ownership.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion docs/openrate/report-v18.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion docs/openrate/report-v19.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion probes/dev004_settings_xml_no_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion probes/dev023_label_avery_layout_schema_match.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion probes/dev038_toc_fiexde_typo_replication.py
Original file line number Diff line number Diff line change
Expand Up @@ -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``.
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_openrate_corpus_v10.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_openrate_corpus_v11.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_openrate_corpus_v13.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions scripts/generate_openrate_corpus_v16.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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), "
Expand Down
2 changes: 1 addition & 1 deletion scripts/generate_openrate_corpus_v9.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/hwpx/_document/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/hwpx/_document/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/hwpx/oxml/body.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)."""

Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/hwpx/oxml/dutmal_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def _paragraph_add_dutmal(
) -> HwpxOxmlInlineObject:
"""Insert ``<hp:dutmal>`` -- 덧말(루비형 주석 텍스트).

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
Expand Down
Loading
Loading