python-hwpx-automation 6.7.1__tar.gz → 7.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. {python_hwpx_automation-6.7.1/src/python_hwpx_automation.egg-info → python_hwpx_automation-7.0.2}/PKG-INFO +8 -11
  2. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/README.md +6 -9
  3. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/pyproject.toml +30 -4
  4. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/content.py +14 -12
  5. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/formatting.py +3 -3
  6. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/errors.py +3 -0
  7. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/form_fill.py +52 -13
  8. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/content_edit.py +28 -4
  9. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/layout_style.py +36 -14
  10. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/tracked_changes.py +12 -6
  11. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/identity.json +20 -9
  12. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/mixed_form.py +1 -1
  13. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/dump.py +2 -2
  14. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/mapping.py +4 -1
  15. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/native.py +3 -3
  16. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/commands.py +3 -3
  17. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/document.py +2 -2
  18. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/__init__.py +47 -19
  19. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/builder/core.py +50 -15
  20. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/harvest.py +2 -2
  21. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/presets/proposal.py +10 -10
  22. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/evalplan/runtime.py +36 -1
  23. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/profile.py +1 -1
  24. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/seal.py +1 -1
  25. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/template_formfit.py +1 -1
  26. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/org_chart.py +3 -3
  27. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/content_layout.py +39 -17
  28. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/form_fields.py +108 -10
  29. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/media.py +36 -6
  30. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/memo_style.py +18 -6
  31. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/package_validation.py +3 -3
  32. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/read_query.py +3 -3
  33. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/save_policy.py +15 -3
  34. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/tables.py +4 -7
  35. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/transactions.py +1 -1
  36. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/quality_generation.py +14 -8
  37. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/runtime.py +6 -1
  38. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/tool_contract.py +4 -4
  39. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/upstream.py +11 -11
  40. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workspace.py +13 -0
  41. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2/src/python_hwpx_automation.egg-info}/PKG-INFO +8 -11
  42. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/python_hwpx_automation.egg-info/requires.txt +1 -1
  43. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/LICENSE +0 -0
  44. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/MANIFEST.in +0 -0
  45. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/NOTICE +0 -0
  46. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/setup.cfg +0 -0
  47. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/__init__.py +0 -0
  48. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/__init__.pyi +0 -0
  49. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/__main__.py +0 -0
  50. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/agent_document.py +0 -0
  51. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/api.py +0 -0
  52. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/blind_eval.py +0 -0
  53. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/capabilities.py +0 -0
  54. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/compat.py +0 -0
  55. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/configuration.py +0 -0
  56. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/__init__.py +0 -0
  57. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/context.py +0 -0
  58. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/diff.py +0 -0
  59. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/document.py +0 -0
  60. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/handles.py +0 -0
  61. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/locations.py +0 -0
  62. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/locator.py +0 -0
  63. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/plan.py +0 -0
  64. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/resources.py +0 -0
  65. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/search.py +0 -0
  66. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/transactions.py +0 -0
  67. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/core/txn.py +0 -0
  68. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/document_state.py +0 -0
  69. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/execution_lock.py +0 -0
  70. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/fastmcp_adapter.py +0 -0
  71. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/form_output_models.py +0 -0
  72. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/__init__.py +0 -0
  73. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/_shared.py +0 -0
  74. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/agent_document.py +0 -0
  75. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/authoring.py +0 -0
  76. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/form_fill.py +0 -0
  77. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/quality_render.py +0 -0
  78. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/read_export.py +0 -0
  79. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/specialized.py +0 -0
  80. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/handlers/workflow.py +0 -0
  81. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/hwp_converter.py +0 -0
  82. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/hwp_support.py +0 -0
  83. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/hwpx_ops.py +0 -0
  84. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/identity.py +0 -0
  85. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ingest_adapters.py +0 -0
  86. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/markdown_plan.py +0 -0
  87. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/mcp_cli.py +0 -0
  88. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/metadata/tools_meta.py +0 -0
  89. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/mutation_models.py +0 -0
  90. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/network_policy.py +0 -0
  91. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/__init__.py +0 -0
  92. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/__init__.py +0 -0
  93. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/_batch_verification.py +0 -0
  94. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/__init__.py +0 -0
  95. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/bundle.py +0 -0
  96. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/catalog.py +0 -0
  97. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/model.py +0 -0
  98. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/blueprint/replay.py +0 -0
  99. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/catalog.py +0 -0
  100. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/cli.py +0 -0
  101. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/form_plan.py +0 -0
  102. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/model.py +0 -0
  103. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/path.py +0 -0
  104. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/query.py +0 -0
  105. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/agent/story.py +0 -0
  106. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/advanced_generators.py +0 -0
  107. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/builder/__init__.py +0 -0
  108. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/builder/report.py +0 -0
  109. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/__init__.py +0 -0
  110. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/_support.py +0 -0
  111. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/composer.py +0 -0
  112. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/plan.py +0 -0
  113. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profile.py +0 -0
  114. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +0 -0
  115. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +0 -0
  116. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +0 -0
  117. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +0 -0
  118. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/profile.json +0 -0
  119. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
  120. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +0 -0
  121. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +0 -0
  122. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +0 -0
  123. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +0 -0
  124. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
  125. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +0 -0
  126. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +0 -0
  127. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +0 -0
  128. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +0 -0
  129. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +0 -0
  130. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
  131. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +0 -0
  132. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +0 -0
  133. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +0 -0
  134. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +0 -0
  135. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/profile.json +0 -0
  136. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
  137. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/design/validator.py +0 -0
  138. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/presets/__init__.py +0 -0
  139. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/report_parser.py +0 -0
  140. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/style_profile.py +0 -0
  141. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/authoring/template_analyzer.py +0 -0
  142. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/charting/__init__.py +0 -0
  143. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/compliance/__init__.py +0 -0
  144. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/compliance/official_lint.py +0 -0
  145. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/compliance/pii.py +0 -0
  146. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/document_ops/__init__.py +0 -0
  147. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/document_ops/comparison.py +0 -0
  148. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/document_ops/mail_merge.py +0 -0
  149. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/document_ops/redline.py +0 -0
  150. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/evalplan/__init__.py +0 -0
  151. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/__init__.py +0 -0
  152. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/compose.py +0 -0
  153. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/ir.py +0 -0
  154. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/measure.py +0 -0
  155. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/exam/parser.py +0 -0
  156. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/__init__.py +0 -0
  157. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/classification.py +0 -0
  158. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fill_residue.py +0 -0
  159. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/__init__.py +0 -0
  160. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/apply.py +0 -0
  161. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/engine.py +0 -0
  162. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/measure.py +0 -0
  163. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/policy.py +0 -0
  164. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/report.py +0 -0
  165. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/fit/wordbox.py +0 -0
  166. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/guidance.py +0 -0
  167. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/quality.py +0 -0
  168. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/form_fill/split_run.py +0 -0
  169. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/__init__.py +0 -0
  170. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/composition.py +0 -0
  171. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/data/bank.json +0 -0
  172. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/data/genres.json +0 -0
  173. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/house_style/gianmun.py +0 -0
  174. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/quality/__init__.py +0 -0
  175. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/quality/page_guard.py +0 -0
  176. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/__init__.py +0 -0
  177. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/_hancom_open_rate.ps1 +0 -0
  178. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +0 -0
  179. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +0 -0
  180. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/_render_hwpx_mac.applescript +0 -0
  181. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/block_splits.py +0 -0
  182. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/detectors.py +0 -0
  183. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/diff.py +0 -0
  184. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/fixture_corpus.py +0 -0
  185. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/oracle.py +0 -0
  186. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/page_qa.py +0 -0
  187. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/qa_contracts.py +0 -0
  188. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/qa_metrics.py +0 -0
  189. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/rendering/worker.py +0 -0
  190. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/utilities/__init__.py +0 -0
  191. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/office/utilities/table_compute.py +0 -0
  192. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/__init__.py +0 -0
  193. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/_border_fill.py +0 -0
  194. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/composition.py +0 -0
  195. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/context.py +0 -0
  196. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/planning.py +0 -0
  197. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/ops_services/preview_export.py +0 -0
  198. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/preview_output_models.py +0 -0
  199. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/public-modules.json +0 -0
  200. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/py.typed +0 -0
  201. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/quality.py +0 -0
  202. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/resources.py +0 -0
  203. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/runtime_services.py +0 -0
  204. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/server.py +0 -0
  205. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/storage.py +0 -0
  206. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/tool_bindings.py +0 -0
  207. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/utils/__init__.py +0 -0
  208. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/utils/helpers.py +0 -0
  209. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/visual_qa.py +0 -0
  210. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/__init__.py +0 -0
  211. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/adapters.py +0 -0
  212. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/dispatcher.py +0 -0
  213. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/models.py +0 -0
  214. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/policy.py +0 -0
  215. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/render_contracts.py +0 -0
  216. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/render_metrics.py +0 -0
  217. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/render_queue.py +0 -0
  218. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/render_security.py +0 -0
  219. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/render_transport.py +0 -0
  220. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/rendering.py +0 -0
  221. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/service.py +0 -0
  222. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/state_machine.py +0 -0
  223. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/hwpx_automation/workflow/store.py +0 -0
  224. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/python_hwpx_automation.egg-info/SOURCES.txt +0 -0
  225. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/python_hwpx_automation.egg-info/dependency_links.txt +0 -0
  226. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/python_hwpx_automation.egg-info/entry_points.txt +0 -0
  227. {python_hwpx_automation-6.7.1 → python_hwpx_automation-7.0.2}/src/python_hwpx_automation.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx-automation
3
- Version: 6.7.1
3
+ Version: 7.0.2
4
4
  Summary: Task-oriented HWPX document automation for Python, with an optional MCP adapter.
5
5
  Author: Kohkyuhyun
6
6
  License-Expression: Apache-2.0
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  License-File: NOTICE
23
- Requires-Dist: python-hwpx<6,>=5.7.0
23
+ Requires-Dist: python-hwpx<7,>=6.0.2
24
24
  Requires-Dist: pydantic<3,>=2.11
25
25
  Requires-Dist: cryptography>=42.0
26
26
  Requires-Dist: anyio>=4.0
@@ -74,15 +74,12 @@ Dynamic: license-file
74
74
 
75
75
  <!-- release-state: release-approved -->
76
76
  > [!NOTE]
77
- > 소스 트리는 **아직 공개되지 않은 6.7.1 후보**입니다(양식개체·기안문 장르:
78
- > 체크박스 저작 프리미티브와 `compose_official_draft`/`compose_simple_draft`,
79
- > 136 도구, core 바닥 5.7.0). 현재 공개 트레인은 여전히
80
- > `python-hwpx 5.6.0 → python-hwpx-automation 6.6.4 → hwpx-plugin 1.6.0`
81
- > (계약 `19898dba41495c47`)입니다.
82
- > 후보는 core·automation PyPI와 plugin GitHub
83
- > Release·marketplace·실제 marketplace 설치까지 확인한 뒤에만 승격하며, 기존
84
- > 5.x 설치는 별도 발행된 `hwpx-mcp-server 5.1.1`이 보호합니다. 절차와 상태
85
- > 머신: [릴리스 runbook](docs/release-runbook.md)
77
+ > 공개 트레인: `python-hwpx 6.1.0 python-hwpx-automation 7.0.1
78
+ > hwpx-plugin 2.0.0`. automation 7.0.2 패치(Windows 저장 수리 #98,
79
+ > 업로드 경로 안내 #75) release-approved 상태이며, 원격
80
+ > 진실(core·automation PyPI와 plugin GitHub
81
+ > Release·marketplace·실제 marketplace 설치) 관찰 전까지 공개 좌표를
82
+ > 승격하지 않습니다 [릴리스 runbook](docs/release-runbook.md)
86
83
 
87
84
  [python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
88
85
  양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
@@ -14,15 +14,12 @@
14
14
 
15
15
  <!-- release-state: release-approved -->
16
16
  > [!NOTE]
17
- > 소스 트리는 **아직 공개되지 않은 6.7.1 후보**입니다(양식개체·기안문 장르:
18
- > 체크박스 저작 프리미티브와 `compose_official_draft`/`compose_simple_draft`,
19
- > 136 도구, core 바닥 5.7.0). 현재 공개 트레인은 여전히
20
- > `python-hwpx 5.6.0 → python-hwpx-automation 6.6.4 → hwpx-plugin 1.6.0`
21
- > (계약 `19898dba41495c47`)입니다.
22
- > 후보는 core·automation PyPI와 plugin GitHub
23
- > Release·marketplace·실제 marketplace 설치까지 확인한 뒤에만 승격하며, 기존
24
- > 5.x 설치는 별도 발행된 `hwpx-mcp-server 5.1.1`이 보호합니다. 절차와 상태
25
- > 머신: [릴리스 runbook](docs/release-runbook.md)
17
+ > 공개 트레인: `python-hwpx 6.1.0 python-hwpx-automation 7.0.1
18
+ > hwpx-plugin 2.0.0`. automation 7.0.2 패치(Windows 저장 수리 #98,
19
+ > 업로드 경로 안내 #75) release-approved 상태이며, 원격
20
+ > 진실(core·automation PyPI와 plugin GitHub
21
+ > Release·marketplace·실제 marketplace 설치) 관찰 전까지 공개 좌표를
22
+ > 승격하지 않습니다 [릴리스 runbook](docs/release-runbook.md)
26
23
 
27
24
  [python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
28
25
  양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-hwpx-automation"
7
- version = "6.7.1"
7
+ version = "7.0.2"
8
8
  description = "Task-oriented HWPX document automation for Python, with an optional MCP adapter."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Kohkyuhyun" }]
@@ -24,12 +24,14 @@ classifiers = [
24
24
  "Typing :: Typed",
25
25
  ]
26
26
  dependencies = [
27
- # 5.0 is the floor, not a preference: this package declares the `hwpx` console
27
+ # 6.0 is the floor, not a preference: this package declares the `hwpx` console
28
28
  # name that core used to own, and core only stops declaring it at 5.0. Pinning
29
29
  # the bounded major here is what makes "no valid install has two declarers"
30
30
  # true rather than hopeful, and prevents the next core major from silently
31
- # breaking an already-published automation line.
32
- "python-hwpx>=5.7.0,<6", # HWPX object model, OXML/OPC, format-native primitives
31
+ # breaking an already-published automation line. WP-F (engine surface 6.0):
32
+ # this line adapted to the new namespace surface (design §9 WP-F) — the dev0
33
+ # pre-release qualifier tracks core's own not-yet-tagged 6.0 identity.
34
+ "python-hwpx>=6.0.2,<7", # HWPX object model, OXML/OPC, format-native primitives
33
35
 
34
36
  "pydantic>=2.11,<3",
35
37
  "cryptography>=42.0",
@@ -124,6 +126,30 @@ include = ["hwpx_automation*"]
124
126
  # exercise, and their tests import them by bare name.
125
127
  pythonpath = ["src", "scripts"]
126
128
  addopts = "-q"
129
+ # WP-F (core 6.0 namespace adaptation, design §9): any DeprecationWarning this
130
+ # package's own code triggers by calling core's pre-7.0 legacy shim surface is
131
+ # a real regression -- error by default, and name each known non-automation
132
+ # source precisely rather than silencing DeprecationWarning wholesale.
133
+ filterwarnings = [
134
+ "error::DeprecationWarning",
135
+ # hwpx-core's own internal modules still call its pre-6.0 facade
136
+ # internally (core's own migration debt, not automation's -- out of this
137
+ # package's control/scope).
138
+ "ignore::DeprecationWarning:hwpx\\._document\\._legacy",
139
+ "ignore::DeprecationWarning:hwpx\\.form_fit\\.measure",
140
+ "ignore::DeprecationWarning:hwpx\\.ingest\\.hwpx_converter",
141
+ "ignore::DeprecationWarning:hwpx\\.tools\\.mail_merge",
142
+ "ignore::DeprecationWarning:hwpx\\.tools\\.redline",
143
+ # test_fuzz_harness_wired dynamically imports whichever co-located
144
+ # python-hwpx* sibling checkout happens to carry scripts/fuzz (by design
145
+ # it does not pin to PYTHON_HWPX_REPO -- see that test's own docstring);
146
+ # that checkout's migration state is outside this package's control.
147
+ "ignore::DeprecationWarning:fuzz\\.runner",
148
+ # SWIG-generated C-extension types (from a rendering/test dependency)
149
+ # lack __module__ on some builtin types under newer CPython -- a
150
+ # third-party artifact, never an hwpx-sourced warning.
151
+ "ignore:builtin type \\w+ has no __module__ attribute:DeprecationWarning",
152
+ ]
127
153
 
128
154
  [tool.mypy]
129
155
  python_version = "3.10"
@@ -274,7 +274,9 @@ def delete_paragraph_from_doc(doc: HwpxDocument, paragraph_index: int) -> int:
274
274
  return total
275
275
 
276
276
  try:
277
- doc.remove_paragraph(paragraph_index)
277
+ # remove_paragraph is demoted in 6.0 with no namespace replacement
278
+ # (design table row 101) — the paragraph object owns .remove() now.
279
+ paragraphs[paragraph_index].remove()
278
280
  except (ValueError, IndexError) as exc:
279
281
  raise RuntimeError("삭제할 문단 요소를 섹션에서 찾을 수 없습니다.") from exc
280
282
  return total - 1
@@ -317,19 +319,19 @@ def get_table_data(doc: HwpxDocument, table_index: int) -> dict:
317
319
 
318
320
  def get_table_map_in_doc(doc: HwpxDocument) -> dict:
319
321
  """문서의 표 메타데이터를 LLM 친화적인 JSON 형태로 반환한다."""
320
- result = doc.get_table_map()
322
+ result = doc.tables.map()
321
323
  tables = list(result.get("tables", []))
322
324
  return {"tables": tables, "count": len(tables)}
323
325
 
324
326
 
325
327
  def find_cell_by_label_in_doc(doc: HwpxDocument, label_text: str, direction: str = "right") -> dict:
326
328
  """라벨 셀 기준으로 대상 셀을 찾는다."""
327
- return doc.find_cell_by_label(label_text, direction=direction)
329
+ return doc.tables.find_cell_by_label(label_text, direction=direction)
328
330
 
329
331
 
330
332
  def fill_by_path_in_doc(doc: HwpxDocument, mappings: dict[str, str]) -> dict:
331
333
  """라벨 기반 경로 구문으로 표 셀을 채운다."""
332
- return doc.fill_by_path(mappings)
334
+ return doc.tables.fill_by_path(mappings)
333
335
 
334
336
 
335
337
  def set_cell_text(
@@ -429,7 +431,7 @@ def _apply_table_border_fill(
429
431
  col: int = None,
430
432
  ) -> str:
431
433
  """테두리/음영 borderFill을 만들어 표 전체 또는 한 셀에 적용한다."""
432
- border_fill_id = doc.ensure_border_fill(
434
+ border_fill_id = doc.styles.ensure_border_fill(
433
435
  border_type=border_type or "SOLID",
434
436
  border_color=border_color or "#000000",
435
437
  border_width=border_width or "0.12 mm",
@@ -736,20 +738,20 @@ def add_memo_to_doc(
736
738
  create=True,
737
739
  )
738
740
  paragraph = resolved.paragraph
739
- memo_count_before = len(doc.memos)
741
+ memo_count_before = len(doc.notes.memos)
740
742
  try:
741
- doc.add_memo_with_anchor(text or "", paragraph=paragraph)
743
+ doc.notes.add_memo(text or "", anchor=paragraph)
742
744
  except Exception as exc: # noqa: BLE001
743
745
  if not _looks_like_mixed_xml_type_error(exc):
744
746
  raise
745
747
  # Clean up any partially-created memo from the failed native call
746
- current_memos = doc.memos
748
+ current_memos = doc.notes.memos
747
749
  while len(current_memos) > memo_count_before:
748
750
  try:
749
- doc.remove_memo(current_memos[-1])
751
+ doc.notes.remove_memo(current_memos[-1])
750
752
  except Exception: # noqa: BLE001
751
753
  break
752
- current_memos = doc.memos
754
+ current_memos = doc.notes.memos
753
755
  logger.warning("메모 추가 중 혼합 XML 타입 충돌 감지, fallback 경로 사용: %s", exc)
754
756
  _add_memo_with_anchor_fallback(paragraph, text or "")
755
757
  return {"memo_added": True, "location": resolved.location}
@@ -775,9 +777,9 @@ def remove_memo_from_doc(
775
777
  if memo_id:
776
778
  memo_ids.add(memo_id)
777
779
 
778
- for memo in list(doc.memos):
780
+ for memo in list(doc.notes.memos):
779
781
  if memo.id in memo_ids:
780
- doc.remove_memo(memo)
782
+ doc.notes.remove_memo(memo)
781
783
 
782
784
  removed_anchor = False
783
785
  for run_element in _memo_anchor_runs(paragraph, memo_ids):
@@ -406,10 +406,10 @@ def create_style_in_doc(
406
406
  name = (style_name or "").strip()
407
407
  if not name:
408
408
  raise ValueError("style_name cannot be empty")
409
- if not doc.headers:
409
+ if not doc.parts.headers:
410
410
  raise RuntimeError("document does not contain any headers to host styles")
411
411
 
412
- header = doc.headers[0]
412
+ header = doc.parts.headers[0]
413
413
  styles_element = document_styles_element(doc)
414
414
 
415
415
  for style in _iter_unique_styles(doc):
@@ -427,7 +427,7 @@ def create_style_in_doc(
427
427
  }
428
428
 
429
429
  base_style_id = _default_base_style_id(doc)
430
- base_style = doc.style(base_style_id)
430
+ base_style = doc.styles.get(base_style_id)
431
431
  if base_style is None:
432
432
  raise RuntimeError(f"failed to resolve base style id: {base_style_id}")
433
433
 
@@ -36,6 +36,7 @@ class CommonErrorModel(BaseModel):
36
36
 
37
37
 
38
38
  ERROR_CODE_TO_MCP_CODE: dict[str, int] = {
39
+ "CLIENT_UPLOAD_PATH_UNAVAILABLE": -32602,
39
40
  "DOCUMENT_NOT_FOUND": -32044,
40
41
  "PERMISSION_DENIED": -32043,
41
42
  "TABLE_INDEX_OUT_OF_RANGE": -32042,
@@ -57,6 +58,7 @@ DEFAULT_ERROR_SUGGESTIONS: dict[str, str] = {
57
58
  "AMBIGUOUS_TARGET": "검색 조건을 더 구체화하거나 limit=1로 미리보기를 다시 생성하세요.",
58
59
  "BYTE_PATCH_OPEN_SAFETY_FAILED": "반환된 openSafety 진단을 확인하고 일반 저장/복구 경로로 다시 생성하세요.",
59
60
  "CAPABILITY_SKEW": "core/automation/plugin ToolSpec 계약 불일치로 쓰기가 차단되었습니다. mcp_server_health의 최소 버전과 contract hash에 맞춰 다시 설치한 뒤 호스트를 재시작하세요.",
61
+ "CLIENT_UPLOAD_PATH_UNAVAILABLE": "대화에 업로드된 파일의 내부 경로는 로컬 MCP 서버에서 읽을 수 없습니다. 파일을 PC에 저장한 뒤 실제 로컬 경로를 전달하세요.",
60
62
  "FIELD_OVERFLOW": "값이 칸에 넘칩니다. fitPolicy(mode=wrap_then_shrink/shrink/truncate_with_report) 또는 overflow=warn으로 다시 채우거나 값을 줄이세요. details.visualComplete.suggestedRetry 참고.",
61
63
  "STALE_LINESEG_DETECTED": "오래된 lineseg 레이아웃 캐시가 남았습니다. 해당 문단을 다시 편집해 캐시를 무효화한 뒤 저장하세요.",
62
64
  "VISUAL_COMPLETE_FAILED": "한컴 렌더에서 겹침/넘침 등 시각 결함이 감지되었습니다. details.visualComplete를 확인하고 수정 후 다시 저장하세요.",
@@ -120,6 +122,7 @@ def category_for_error(error_code: str) -> ErrorCategory:
120
122
  if error_code.startswith("NETWORK_"):
121
123
  return "network"
122
124
  if error_code in {
125
+ "CLIENT_UPLOAD_PATH_UNAVAILABLE",
123
126
  "INVALID_ARGUMENT",
124
127
  "WORKSPACE_PATH_INVALID",
125
128
  "DOCUMENT_LOCATOR_REQUIRED",
@@ -311,7 +311,10 @@ def apply_form_fill_workflow(
311
311
  if mapping.get("kind") == "form-field":
312
312
  before_fields = _document_form_fields(doc)
313
313
  before_field = _find_form_field_by_mapping(before_fields, mapping)
314
- fill_result = doc.fill_form_field(
314
+ # fields.fill now returns a frozen FieldFillResult rather
315
+ # than a dict (design §2.3) — read its attributes directly
316
+ # instead of the old after_value/style_before/... dict keys.
317
+ fill_result = doc.fields.fill(
315
318
  str(mapping.get("value", "")),
316
319
  field_index=int(mapping["field_index"]),
317
320
  )
@@ -320,10 +323,10 @@ def apply_form_fill_workflow(
320
323
  {
321
324
  **mapping,
322
325
  "before_text": mask_pii(_before_ff, DEFAULT_POLICY) if mask else _before_ff,
323
- "after_text": fill_result["after_value"],
324
- "style_before": fill_result.get("style_before"),
325
- "style_after": fill_result.get("style_after"),
326
- "style_preserved": bool(fill_result.get("style_preserved", False)),
326
+ "after_text": fill_result.after,
327
+ "style_before": list(fill_result.style_before),
328
+ "style_after": list(fill_result.style_after),
329
+ "style_preserved": bool(fill_result.style_preserved),
327
330
  }
328
331
  )
329
332
  elif mapping.get("kind") == "cell":
@@ -589,7 +592,7 @@ def _build_mapping_analysis(doc: Any, canonical_input: dict[str, Any]) -> dict[s
589
592
  if native_mapping is not None:
590
593
  resolved.append(native_mapping)
591
594
  continue
592
- matches = doc.find_cell_by_label(label, direction=direction).get("matches", [])
595
+ matches = doc.tables.find_cell_by_label(label, direction=direction).get("matches", [])
593
596
  if len(matches) == 1:
594
597
  match = matches[0]
595
598
  cell = match["target_cell"]
@@ -681,14 +684,50 @@ def _build_mapping_analysis(doc: Any, canonical_input: dict[str, Any]) -> dict[s
681
684
  return {"resolved": resolved, "unresolved": unresolved, "formFields": form_field_strategy}
682
685
 
683
686
 
687
+ def _form_field_to_legacy_dict(field: Any, *, index: int) -> dict[str, Any]:
688
+ """Rebuild the 5.x form-field dict shape from a 6.0 ``FormField`` view.
689
+
690
+ Mirrors ``ops_services.form_fields._form_field_to_legacy_dict`` — kept
691
+ local (not imported) since this lower-level workflow module sits below
692
+ the service layer and importing from it would invert that dependency
693
+ direction. ``index`` is load-bearing here: downstream mapping resolution
694
+ (``_resolved_explicit_form_field_mapping``/``_find_form_field_by_mapping``)
695
+ matches on ``field["index"]`` to build ``field_index=`` fill targets.
696
+ """
697
+
698
+ location = field.location
699
+ return {
700
+ "index": index,
701
+ "field_id": field.field_id,
702
+ "id": field.field_id,
703
+ "fieldid": field.field_id,
704
+ "name": field.name,
705
+ "prompt": field.prompt,
706
+ "instruction": field.prompt,
707
+ "memo": field.memo,
708
+ "dirty": field.element.get("dirty", ""),
709
+ "is_placeholder": field.is_placeholder,
710
+ "current_value": field.value,
711
+ "field_type": field.field_type,
712
+ "control_type": field.field_type,
713
+ "section_index": location.section_index,
714
+ "paragraph_index": location.paragraph_index,
715
+ "paragraph_index_in_section": location.paragraph_index_in_section,
716
+ "run_index": location.run_index,
717
+ "child_index": location.child_index,
718
+ "has_end": field.has_end,
719
+ "parameters": [parameter.to_dict() for parameter in field.parameters],
720
+ }
721
+
722
+
684
723
  def _document_form_fields(doc: Any) -> list[dict[str, Any]]:
685
- list_fields = getattr(doc, "list_form_fields", None)
686
- if not callable(list_fields):
687
- return []
688
- fields = list_fields()
689
- if not isinstance(fields, list):
690
- return []
691
- return [copy.deepcopy(field) for field in fields if isinstance(field, dict)]
724
+ # fields.all now returns tuple[FormField, ...] rather than list[dict]
725
+ # (design §2.3/§2.5) — reconstruct the established dict shape since
726
+ # FormField has no to_dict() of its own.
727
+ return [
728
+ _form_field_to_legacy_dict(field, index=index)
729
+ for index, field in enumerate(doc.fields.all)
730
+ ]
692
731
 
693
732
 
694
733
  def _normalize_match_text(value: Any) -> str:
@@ -787,7 +787,10 @@ def insert_picture(
787
787
  section_index=section_index,
788
788
  align=align,
789
789
  )
790
- picture_refs = doc.picture_references()
790
+ # media.picture_references now returns tuple[PictureRef, ...] rather
791
+ # than list[dict] (design §2.5) — .to_dict() per entry keeps this
792
+ # handler's own dict-shaped response unchanged.
793
+ picture_refs = [ref.to_dict() for ref in doc.media.picture_references()]
791
794
  result = {
792
795
  "ok": True,
793
796
  "filename": filename,
@@ -821,19 +824,40 @@ def replace_picture(
821
824
  target_path = resolve_path(output) if output else path
822
825
  doc = open_doc(path)
823
826
  image_data = _decode_image_base64(image_base64)
824
- replacement = doc.replace_picture(
827
+ # media.replace_picture now returns a frozen PictureReplacement (design
828
+ # §2.4) whose own .to_dict() uses different field names than this op's
829
+ # established response contract (old_binaryItemIDRef/new_binaryItemIDRef/
830
+ # removedOldImage/geometryPreserved/picture_index/section_index), which
831
+ # existing callers/tests depend on — rebuild that exact shape instead.
832
+ replacement = doc.media.replace_picture(
825
833
  image_data,
826
834
  image_format,
827
835
  picture_index=picture_index,
828
836
  binary_item_id_ref=binary_item_id_ref,
829
837
  remove_orphaned=remove_orphaned,
830
838
  )
839
+ replaced_section_index = next(
840
+ (
841
+ index
842
+ for index, section in enumerate(doc.sections)
843
+ if section.element is replacement.picture.paragraph.section.element
844
+ ),
845
+ None,
846
+ )
847
+ replacement_payload = {
848
+ "picture_index": picture_index,
849
+ "section_index": replaced_section_index,
850
+ "old_binaryItemIDRef": replacement.previous_item_id,
851
+ "new_binaryItemIDRef": replacement.item_id,
852
+ "removedOldImage": bool(replacement.removed_orphans),
853
+ "geometryPreserved": True,
854
+ }
831
855
  result = {
832
856
  "ok": True,
833
857
  "filename": filename,
834
858
  "outputPath": target_path,
835
- "replacement": replacement,
836
- "pictureReferences": doc.picture_references(),
859
+ "replacement": replacement_payload,
860
+ "pictureReferences": [ref.to_dict() for ref in doc.media.picture_references()],
837
861
  "idIntegrity": _id_integrity_payload(doc),
838
862
  }
839
863
  if dry_run:
@@ -294,7 +294,10 @@ def set_paragraph_format(
294
294
  if guard is not None:
295
295
  return guard
296
296
  doc = open_doc(path)
297
- result = doc.set_paragraph_format(
297
+ # apply_paragraph_format now returns a frozen ParagraphFormatResult
298
+ # (design §2.4) rather than a dict — .to_dict() keeps this handler's own
299
+ # dict-shaped response (filename merged below) unchanged.
300
+ result = doc.styles.apply_paragraph_format(
298
301
  paragraph_index=paragraph_index,
299
302
  paragraph_indexes=paragraph_indexes,
300
303
  alignment=alignment,
@@ -308,7 +311,7 @@ def set_paragraph_format(
308
311
  keep_with_next=keep_with_next,
309
312
  keep_lines=keep_lines,
310
313
  page_break_before=page_break_before,
311
- )
314
+ ).to_dict()
312
315
  result["filename"] = filename
313
316
  if dry_run:
314
317
  return _with_dry_run_verification(result, doc, path)
@@ -342,7 +345,10 @@ def set_page_setup(
342
345
  if guard is not None:
343
346
  return guard
344
347
  doc = open_doc(path)
345
- result = doc.set_page_setup(
348
+ # page.setup now returns a frozen PageSetup (design §2.4) rather than a
349
+ # dict — .to_dict() keeps this handler's own dict-shaped response
350
+ # (filename merged below) unchanged.
351
+ result = doc.page.setup(
346
352
  paper_size=paper_size,
347
353
  width_mm=width_mm,
348
354
  height_mm=height_mm,
@@ -358,7 +364,7 @@ def set_page_setup(
358
364
  columns=columns,
359
365
  column_gap_mm=column_gap_mm,
360
366
  section_index=section_index,
361
- )
367
+ ).to_dict()
362
368
  result["filename"] = filename
363
369
  if dry_run:
364
370
  return _with_dry_run_verification(result, doc, path)
@@ -398,13 +404,26 @@ def set_header_footer(
398
404
  if guard is not None:
399
405
  return guard
400
406
  doc = open_doc(path)
401
- wrapper = doc.set_header_footer(
402
- kind=kind,
403
- text=text,
404
- content=content,
405
- section_index=section_index,
406
- page_type=page_type,
407
- )
407
+ # set_header_footer is demoted in 6.0 with no namespace replacement
408
+ # (design table row 102, kind= dispatch removed) — dispatch here
409
+ # instead, replicating the normalization the removed method used to do.
410
+ normalized_kind = kind.strip().lower() if isinstance(kind, str) else kind
411
+ if normalized_kind == "header":
412
+ wrapper = doc.page.set_header(
413
+ text=text,
414
+ content=content,
415
+ section_index=section_index,
416
+ page_type=page_type,
417
+ )
418
+ elif normalized_kind == "footer":
419
+ wrapper = doc.page.set_footer(
420
+ text=text,
421
+ content=content,
422
+ section_index=section_index,
423
+ page_type=page_type,
424
+ )
425
+ else:
426
+ raise ValueError("kind must be 'header' or 'footer'")
408
427
  result = {
409
428
  "filename": filename,
410
429
  "headerFooter": _header_footer_payload(wrapper, kind=kind, page_type=page_type),
@@ -435,7 +454,7 @@ def set_page_number(
435
454
  if guard is not None:
436
455
  return guard
437
456
  doc = open_doc(path)
438
- wrapper = doc.set_page_number(
457
+ wrapper = doc.page.set_page_number(
439
458
  target=target,
440
459
  page_type=page_type,
441
460
  format=format,
@@ -478,7 +497,10 @@ def set_list_format(
478
497
  if guard is not None:
479
498
  return guard
480
499
  doc = open_doc(path)
481
- result = doc.set_list_format(
500
+ # apply_list_format now returns a frozen ListFormatResult (design §2.4)
501
+ # rather than a dict — .to_dict() keeps this handler's own dict-shaped
502
+ # response (filename merged below) unchanged.
503
+ result = doc.styles.apply_list_format(
482
504
  paragraph_index=paragraph_index,
483
505
  paragraph_indexes=paragraph_indexes,
484
506
  kind=kind,
@@ -486,7 +508,7 @@ def set_list_format(
486
508
  bullet_char=bullet_char,
487
509
  number_format=number_format,
488
510
  start=start,
489
- )
511
+ ).to_dict()
490
512
  result["filename"] = filename
491
513
  if dry_run:
492
514
  return _with_dry_run_verification(result, doc, path)
@@ -483,30 +483,36 @@ def add_tracked_edit(
483
483
  paragraph = doc.paragraphs[paragraph_index]
484
484
  before_text = _tracked_paragraph_text(paragraph)
485
485
  if edit_type == "insert":
486
- change_id = doc.add_tracked_insert(
486
+ # tracking.insert/delete/replace now return TrackedChange /
487
+ # TrackedReplacement objects rather than bare int/tuple
488
+ # (design §2.6) — .change_id (and .delete/.insert for the
489
+ # replace case, in the same delete-then-insert order 5.x
490
+ # returned) keeps this handler's own int-list response shape
491
+ # unchanged.
492
+ change = doc.tracking.insert(
487
493
  paragraph,
488
494
  edit["text"],
489
495
  author=author,
490
496
  date=normalized_date,
491
497
  )
492
- change_ids = [change_id]
498
+ change_ids = [change.change_id]
493
499
  elif edit_type == "delete":
494
- change_id = doc.add_tracked_delete(
500
+ change = doc.tracking.delete(
495
501
  paragraph,
496
502
  match=edit.get("match"),
497
503
  author=author,
498
504
  date=normalized_date,
499
505
  )
500
- change_ids = [change_id]
506
+ change_ids = [change.change_id]
501
507
  elif edit_type == "replace":
502
- replace_ids = doc.add_tracked_replace(
508
+ replacement = doc.tracking.replace(
503
509
  paragraph,
504
510
  edit["old"],
505
511
  edit["new"],
506
512
  author=author,
507
513
  date=normalized_date,
508
514
  )
509
- change_ids = list(replace_ids)
515
+ change_ids = [replacement.delete.change_id, replacement.insert.change_id]
510
516
  else: # pragma: no cover - validation prevents this branch
511
517
  raise ValueError(f"unsupported tracked edit type: {edit_type}")
512
518
  edit_results.append(
@@ -5,23 +5,34 @@
5
5
  "releaseState": {
6
6
  "status": "release-approved",
7
7
  "candidate": {
8
- "pythonHwpx": "5.7.0",
8
+ "pythonHwpx": "6.1.0",
9
9
  "canonicalDistribution": "python-hwpx-automation",
10
- "canonicalAutomation": "6.7.1",
10
+ "canonicalAutomation": "7.0.2",
11
11
  "compatibilityDistribution": "hwpx-mcp-server",
12
- "compatibility": "6.7.1",
13
- "plugin": "1.7.0",
14
- "contractHash": "98510af22d13899c"
12
+ "compatibility": "7.0.2",
13
+ "plugin": "2.0.0",
14
+ "contractHash": "34a91560759dc47a"
15
15
  },
16
16
  "currentPublic": {
17
- "pythonHwpx": "5.6.0",
17
+ "pythonHwpx": "6.1.0",
18
18
  "primaryDistribution": "python-hwpx-automation",
19
- "primaryApplication": "6.6.4",
20
- "plugin": "1.6.0",
21
- "contractHash": "19898dba41495c47"
19
+ "primaryApplication": "7.0.1",
20
+ "plugin": "2.0.0",
21
+ "contractHash": "34a91560759dc47a"
22
22
  },
23
23
  "promotionGate": "Three states are mandatory: unreleased-candidate while auditing; release-approved only after separate owner approval and while currentPublic still names the previously observed coherent stack; released only in a follow-up commit after remote truth is observed for core, canonical automation, the compatibility distribution, the plugin GitHub release, the marketplace entry, and a real marketplace install. The automation tag workflow publishes only release-approved, leaves currentPublic unchanged, and hands an attached receipt to plugin publication."
24
24
  },
25
+ "releaseFloors": {
26
+ "description": "Frozen historical coordinates. Unlike releaseState these do not advance train by train; they pin the pre-6.0 legacy compatibility cap that every core 5 resolution must be observed against. They live here so the release path has no version literal that is not declared data.",
27
+ "legacyCompatibilityDistribution": "hwpx-mcp-server",
28
+ "legacyCompatibilityVersion": "5.1.1",
29
+ "legacyCoreVersion": "4.2.0",
30
+ "legacyCoreSpecifiers": [
31
+ ">=4.2.0",
32
+ "<5"
33
+ ],
34
+ "legacyCoreRequirementCount": 3
35
+ },
25
36
  "identifiers": [
26
37
  {
27
38
  "surface": "repository",
@@ -2393,7 +2393,7 @@ def _specialized_allowed_members(source_bytes: bytes) -> set[str]:
2393
2393
  members = {str(section.part_name) for section in document.document.sections}
2394
2394
  members.update(
2395
2395
  str(header.part_name)
2396
- for header in getattr(document.document, "headers", ())
2396
+ for header in getattr(document.document.parts, "headers", ())
2397
2397
  )
2398
2398
  if not members:
2399
2399
  raise ValueError("specialized form operation has no editable document members")
@@ -115,7 +115,7 @@ def _numbering_properties(agent: HwpxAgentDocument, record: NodeRecord) -> dict[
115
115
  if record.kind != "paragraph":
116
116
  return None
117
117
  paragraph = record.native
118
- para_pr = agent.document.paragraph_property(paragraph.element.get("paraPrIDRef"))
118
+ para_pr = agent.document.styles.paragraph_property(paragraph.element.get("paraPrIDRef"))
119
119
  heading = para_pr.heading if para_pr is not None else None
120
120
  if heading is None or not heading.type or str(heading.type).upper() == "NONE":
121
121
  return None
@@ -143,7 +143,7 @@ def _numbering_properties(agent: HwpxAgentDocument, record: NodeRecord) -> dict[
143
143
  def _style_dependency(agent: HwpxAgentDocument, record: NodeRecord) -> dict[str, Any] | None:
144
144
  if record.kind == "paragraph":
145
145
  paragraph = record.native
146
- style = agent.document.style(paragraph.element.get("styleIDRef"))
146
+ style = agent.document.styles.get(paragraph.element.get("styleIDRef"))
147
147
  properties = {
148
148
  "category": "paragraph",
149
149
  "name": record.summary.get("style"),
@@ -299,8 +299,11 @@ def materialize_dependencies(
299
299
  elif family == "resource":
300
300
  asset_path = str(properties["assetPath"])
301
301
  suffix = asset_path.rsplit(".", 1)[-1]
302
+ # media.add_image now returns a BinaryItem rather than a bare
303
+ # str (design §2.6) — str(...) is the documented migration
304
+ # buffer (item_id), keeping this identity payload a plain string.
302
305
  item["identity"] = {
303
- "binaryItemIDRef": document.add_image(assets[asset_path], suffix),
306
+ "binaryItemIDRef": str(document.media.add_image(assets[asset_path], suffix)),
304
307
  "mediaType": properties["mediaType"],
305
308
  }
306
309
  else: # pragma: no cover - validated dependency family exhaustiveness