python-hwpx-automation 7.3.1__tar.gz → 7.3.3__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 (235) hide show
  1. {python_hwpx_automation-7.3.1/src/python_hwpx_automation.egg-info → python_hwpx_automation-7.3.3}/PKG-INFO +13 -16
  2. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/README.md +12 -15
  3. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/pyproject.toml +1 -1
  4. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/content.py +18 -2
  5. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/document.py +2 -3
  6. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/transactions.py +15 -3
  7. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/errors.py +54 -1
  8. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/agent_document.py +5 -0
  9. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/read_export.py +14 -10
  10. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/identity.json +10 -10
  11. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mixed_form.py +3 -1
  12. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/report_parser.py +19 -7
  13. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_hancom_open_rate.ps1 +27 -5
  14. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +4 -1
  15. python_hwpx_automation-7.3.3/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +148 -0
  16. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_render_hwpx_mac.applescript +197 -12
  17. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/cli.py +8 -0
  18. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/mac_session.py +12 -0
  19. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/oracle.py +248 -42
  20. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/worker.py +5 -0
  21. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/context.py +49 -3
  22. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/form_fields.py +3 -0
  23. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/package_validation.py +1 -1
  24. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/planning.py +1 -1
  25. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/read_query.py +21 -16
  26. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/save_policy.py +3 -0
  27. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/transactions.py +1 -0
  28. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/runtime.py +26 -3
  29. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/storage.py +116 -10
  30. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/upstream.py +56 -2
  31. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3/src/python_hwpx_automation.egg-info}/PKG-INFO +13 -16
  32. python_hwpx_automation-7.3.1/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +0 -72
  33. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/LICENSE +0 -0
  34. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/MANIFEST.in +0 -0
  35. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/NOTICE +0 -0
  36. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/setup.cfg +0 -0
  37. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__init__.py +0 -0
  38. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__init__.pyi +0 -0
  39. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__main__.py +0 -0
  40. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/agent_document.py +0 -0
  41. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/api.py +0 -0
  42. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/blind_eval.py +0 -0
  43. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/capabilities.py +0 -0
  44. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/compat.py +0 -0
  45. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/configuration.py +0 -0
  46. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/__init__.py +0 -0
  47. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/context.py +0 -0
  48. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/diff.py +0 -0
  49. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/formatting.py +0 -0
  50. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/handles.py +0 -0
  51. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/locations.py +0 -0
  52. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/locator.py +0 -0
  53. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/plan.py +0 -0
  54. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/resources.py +0 -0
  55. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/search.py +0 -0
  56. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/txn.py +0 -0
  57. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/document_state.py +0 -0
  58. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/execution_lock.py +0 -0
  59. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/fastmcp_adapter.py +0 -0
  60. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/form_fill.py +0 -0
  61. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/form_output_models.py +0 -0
  62. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/__init__.py +0 -0
  63. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/_shared.py +0 -0
  64. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/authoring.py +0 -0
  65. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/content_edit.py +0 -0
  66. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/form_fill.py +0 -0
  67. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/layout_style.py +0 -0
  68. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/quality_render.py +0 -0
  69. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/specialized.py +0 -0
  70. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/tracked_changes.py +0 -0
  71. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/workflow.py +0 -0
  72. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwp_converter.py +0 -0
  73. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwp_support.py +0 -0
  74. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwpx_ops.py +0 -0
  75. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/identity.py +0 -0
  76. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ingest_adapters.py +0 -0
  77. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/markdown_plan.py +0 -0
  78. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mcp_cli.py +0 -0
  79. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/metadata/tools_meta.py +0 -0
  80. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mutation_models.py +0 -0
  81. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/network_policy.py +0 -0
  82. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/__init__.py +0 -0
  83. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/__init__.py +0 -0
  84. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_batch_publication.py +0 -0
  85. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_batch_verification.py +0 -0
  86. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_text_scope.py +0 -0
  87. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/__init__.py +0 -0
  88. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/bundle.py +0 -0
  89. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/catalog.py +0 -0
  90. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/dump.py +0 -0
  91. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/mapping.py +0 -0
  92. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/model.py +0 -0
  93. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/native.py +0 -0
  94. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/replay.py +0 -0
  95. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/catalog.py +0 -0
  96. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/cli.py +0 -0
  97. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/commands.py +0 -0
  98. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/document.py +0 -0
  99. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/form_plan.py +0 -0
  100. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/model.py +0 -0
  101. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/path.py +0 -0
  102. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/query.py +0 -0
  103. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/story.py +0 -0
  104. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/__init__.py +0 -0
  105. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/advanced_generators.py +0 -0
  106. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/__init__.py +0 -0
  107. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/core.py +0 -0
  108. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/report.py +0 -0
  109. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/__init__.py +0 -0
  110. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/_support.py +0 -0
  111. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/composer.py +0 -0
  112. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/harvest.py +0 -0
  113. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/plan.py +0 -0
  114. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profile.py +0 -0
  115. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +0 -0
  116. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +0 -0
  117. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +0 -0
  118. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +0 -0
  119. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/profile.json +0 -0
  120. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
  121. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +0 -0
  122. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +0 -0
  123. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +0 -0
  124. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +0 -0
  125. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
  126. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +0 -0
  127. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +0 -0
  128. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +0 -0
  129. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +0 -0
  130. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +0 -0
  131. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
  132. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +0 -0
  133. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +0 -0
  134. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +0 -0
  135. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +0 -0
  136. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/profile.json +0 -0
  137. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
  138. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/validator.py +0 -0
  139. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/presets/__init__.py +0 -0
  140. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/presets/proposal.py +0 -0
  141. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/style_profile.py +0 -0
  142. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/template_analyzer.py +0 -0
  143. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/charting/__init__.py +0 -0
  144. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/__init__.py +0 -0
  145. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/official_lint.py +0 -0
  146. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/pii.py +0 -0
  147. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/__init__.py +0 -0
  148. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/comparison.py +0 -0
  149. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/mail_merge.py +0 -0
  150. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/redline.py +0 -0
  151. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/evalplan/__init__.py +0 -0
  152. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/evalplan/runtime.py +0 -0
  153. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/__init__.py +0 -0
  154. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/compose.py +0 -0
  155. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/ir.py +0 -0
  156. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/measure.py +0 -0
  157. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/parser.py +0 -0
  158. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/profile.py +0 -0
  159. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/__init__.py +0 -0
  160. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/classification.py +0 -0
  161. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fill_residue.py +0 -0
  162. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/__init__.py +0 -0
  163. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/apply.py +0 -0
  164. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/engine.py +0 -0
  165. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/measure.py +0 -0
  166. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/policy.py +0 -0
  167. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/report.py +0 -0
  168. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/seal.py +0 -0
  169. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/wordbox.py +0 -0
  170. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/guidance.py +0 -0
  171. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/quality.py +0 -0
  172. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/split_run.py +0 -0
  173. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/template_formfit.py +0 -0
  174. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/__init__.py +0 -0
  175. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/composition.py +0 -0
  176. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/data/bank.json +0 -0
  177. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/data/genres.json +0 -0
  178. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/gianmun.py +0 -0
  179. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/org_chart.py +0 -0
  180. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/quality/__init__.py +0 -0
  181. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/quality/page_guard.py +0 -0
  182. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/__init__.py +0 -0
  183. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/__main__.py +0 -0
  184. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/block_splits.py +0 -0
  185. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/detectors.py +0 -0
  186. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/diff.py +0 -0
  187. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/fixture_corpus.py +0 -0
  188. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/page_qa.py +0 -0
  189. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/qa_contracts.py +0 -0
  190. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/qa_metrics.py +0 -0
  191. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/utilities/__init__.py +0 -0
  192. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/utilities/table_compute.py +0 -0
  193. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/__init__.py +0 -0
  194. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/_border_fill.py +0 -0
  195. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/composition.py +0 -0
  196. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/content_layout.py +0 -0
  197. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/media.py +0 -0
  198. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/memo_style.py +0 -0
  199. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/preview_export.py +0 -0
  200. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/tables.py +0 -0
  201. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/preview_output_models.py +0 -0
  202. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/public-modules.json +0 -0
  203. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/py.typed +0 -0
  204. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/quality.py +0 -0
  205. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/quality_generation.py +0 -0
  206. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/resources.py +0 -0
  207. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/runtime_services.py +0 -0
  208. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/server.py +0 -0
  209. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/tool_bindings.py +0 -0
  210. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/tool_contract.py +0 -0
  211. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/__init__.py +0 -0
  212. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/helpers.py +0 -0
  213. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/read_budget.py +0 -0
  214. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/visual_qa.py +0 -0
  215. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/__init__.py +0 -0
  216. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/adapters.py +0 -0
  217. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/dispatcher.py +0 -0
  218. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/evidence_lineage.py +0 -0
  219. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/models.py +0 -0
  220. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/policy.py +0 -0
  221. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_contracts.py +0 -0
  222. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_metrics.py +0 -0
  223. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_queue.py +0 -0
  224. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_security.py +0 -0
  225. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_transport.py +0 -0
  226. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/rendering.py +0 -0
  227. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/service.py +0 -0
  228. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/state_machine.py +0 -0
  229. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/store.py +0 -0
  230. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workspace.py +0 -0
  231. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/SOURCES.txt +0 -0
  232. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/dependency_links.txt +0 -0
  233. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/entry_points.txt +0 -0
  234. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/requires.txt +0 -0
  235. {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/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: 7.3.1
3
+ Version: 7.3.3
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
@@ -74,12 +74,10 @@ Dynamic: license-file
74
74
 
75
75
  <!-- release-state: release-approved -->
76
76
  > [!NOTE]
77
- > 발행이 승인된 7.3.1 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.5.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
78
- > 공개 트레인: `python-hwpx 6.5.0 → python-hwpx-automation 7.2.0 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
79
- > [발행·설치 영수증](docs/releases/2026-09-22-trustworthy-edit-engine.md)
77
+ > 발행이 승인된 7.3.3 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.3 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
78
+ > 공개 트레인: `python-hwpx 6.6.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.4.0`.
80
79
  > 공개 좌표는 core·automation PyPI와 plugin GitHub
81
80
  > Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
82
- > [릴리스 runbook](docs/release-runbook.md)
83
81
 
84
82
  [python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
85
83
  양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
@@ -133,7 +131,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
133
131
  "command": "uvx",
134
132
  "args": [
135
133
  "--from",
136
- "python-hwpx-automation[mcp]==7.2.0",
134
+ "python-hwpx-automation[mcp]==7.3.1",
137
135
  "hwpx-automation-mcp"
138
136
  ],
139
137
  "env": {
@@ -152,10 +150,10 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
152
150
 
153
151
  > 비-HWPX 문서(PDF/DOCX/XLSX/HTML/TXT)를 `document_to_markdown`으로 읽으려면
154
152
  > `pip install "python-hwpx-automation[ingest]"`로 MarkItDown adapter를 함께
155
- > 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 5.0.0`.
153
+ > 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 6.5.0`.
156
154
 
157
- 기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 6.x 동안 그대로 동작합니다 —
158
- 전체 목록과 유지 규칙: [6.x 호환 표면](docs/compatibility-6x.md)
155
+ 기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 그대로 동작합니다 —
156
+ 전체 목록과 유지 규칙: [호환 표면](docs/compatibility-6x.md)
159
157
 
160
158
  ## 한컴으로 PDF 렌더하기
161
159
 
@@ -164,7 +162,7 @@ PDF와 쪽 PNG로 렌더합니다. 별도 환경에서 실행하므로 호출하
164
162
  고정 버전을 건드리지 않습니다.
165
163
 
166
164
  ```bash
167
- uvx --from "python-hwpx-automation[oracle]==7.3.1" \
165
+ uvx --from "python-hwpx-automation[oracle]==7.3.3" \
168
166
  hwpx render-pdf in.hwpx out.pdf --png out/page --json
169
167
  ```
170
168
 
@@ -185,7 +183,8 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
185
183
 
186
184
  ## 안전하게 쓰는 법
187
185
 
188
- 처음부터 모든 도구를 외울 필요는 없습니다. 보통 이렇게 흘러갑니다.
186
+ 처음부터 모든 도구를 외울 필요는 없습니다. 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를,
187
+ 새 문서는 document-plan을 먼저 봅니다. 보통 이렇게 흘러갑니다.
189
188
 
190
189
  1. **읽기** — `get_document_info` → `get_document_outline`/`get_document_text` → `find_text`, `get_table_map`으로 필요한 부분만 파악합니다. (저장하지 않음)
191
190
  2. **안전 수정** — `copy_document`로 사본을 만들고, 가장 작은 변경(`search_and_replace`, `set_table_cell_text`, `apply_document_commands`)을 적용한 뒤 다시 읽어 확인하고, 검토가 끝난 사본을 전달합니다.
@@ -198,7 +197,7 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
198
197
  열림안전을 검사하고, 게이트가 실패하면 아무것도 쓰지 않습니다. capability
199
198
  handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단합니다.
200
199
  보안 상세: [하드닝 가이드](docs/hardening_guide_ko.md) · 옛 이름과의 호환
201
- 식별자: [6.x 호환 표면](docs/compatibility-6x.md)
200
+ 식별자: [호환 표면](docs/compatibility-6x.md)
202
201
 
203
202
  > **위치 계약** — `paragraph_index`는 본문 직속 문단의 0-based 인덱스입니다. 표 안 문단은 여기 섞지 않고
204
203
  > `{"kind":"table_cell_paragraph","table_index":0,"row":0,"col":1,"cell_paragraph_index":0}` 같은 `location`
@@ -219,10 +218,10 @@ handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단
219
218
  | `HWPX_AUTOMATION_WORKFLOW_STORE` | durable workflow SQLite 경로. 기존 `HWPX_WORKFLOW_STORE`보다 우선 | 기존 6.x 상태 경로 |
220
219
  | `LOG_LEVEL` | 로그 레벨 | `INFO` |
221
220
 
222
- 동일 suffix의 기존 `HWPX_MCP_*` 키는 6.x 동안 fallback으로 유지되며, 두 키가
221
+ 동일 suffix의 기존 `HWPX_MCP_*` 키는 fallback으로 유지되며, 두 키가
223
222
  함께 있으면 `HWPX_AUTOMATION_*`이 우선합니다. render·workflow·oracle·plugin
224
223
  연동용 보존 키 전체 목록과 workflow DB 경로 규칙은
225
- [6.x 호환 표면](docs/compatibility-6x.md)에 있습니다.
224
+ [호환 표면](docs/compatibility-6x.md)에 있습니다.
226
225
 
227
226
  경로는 기본적으로 workspace 밖 traversal과 symlink escape를 거부하고, URL 입력은 HTTPS·공개 IP만
228
227
  허용합니다. 원자 rename을 제공하지 않는 호스트의 동시성 주의사항은 [하드닝 가이드](docs/hardening_guide_ko.md)를 보세요.
@@ -253,5 +252,3 @@ python scripts/run_conformance.py run \
253
252
  ## License · Maintainer
254
253
 
255
254
  Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
256
-
257
- 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를 먼저 확인하세요. 새 문서는 document-plan, 에이전트 연결은 선택 MCP와 호스트 플러그인을 사용합니다.
@@ -14,12 +14,10 @@
14
14
 
15
15
  <!-- release-state: release-approved -->
16
16
  > [!NOTE]
17
- > 발행이 승인된 7.3.1 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.5.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
18
- > 공개 트레인: `python-hwpx 6.5.0 → python-hwpx-automation 7.2.0 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
19
- > [발행·설치 영수증](docs/releases/2026-09-22-trustworthy-edit-engine.md)
17
+ > 발행이 승인된 7.3.3 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.3 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
18
+ > 공개 트레인: `python-hwpx 6.6.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.4.0`.
20
19
  > 공개 좌표는 core·automation PyPI와 plugin GitHub
21
20
  > Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
22
- > [릴리스 runbook](docs/release-runbook.md)
23
21
 
24
22
  [python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
25
23
  양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
@@ -73,7 +71,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
73
71
  "command": "uvx",
74
72
  "args": [
75
73
  "--from",
76
- "python-hwpx-automation[mcp]==7.2.0",
74
+ "python-hwpx-automation[mcp]==7.3.1",
77
75
  "hwpx-automation-mcp"
78
76
  ],
79
77
  "env": {
@@ -92,10 +90,10 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
92
90
 
93
91
  > 비-HWPX 문서(PDF/DOCX/XLSX/HTML/TXT)를 `document_to_markdown`으로 읽으려면
94
92
  > `pip install "python-hwpx-automation[ingest]"`로 MarkItDown adapter를 함께
95
- > 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 5.0.0`.
93
+ > 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 6.5.0`.
96
94
 
97
- 기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 6.x 동안 그대로 동작합니다 —
98
- 전체 목록과 유지 규칙: [6.x 호환 표면](docs/compatibility-6x.md)
95
+ 기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 그대로 동작합니다 —
96
+ 전체 목록과 유지 규칙: [호환 표면](docs/compatibility-6x.md)
99
97
 
100
98
  ## 한컴으로 PDF 렌더하기
101
99
 
@@ -104,7 +102,7 @@ PDF와 쪽 PNG로 렌더합니다. 별도 환경에서 실행하므로 호출하
104
102
  고정 버전을 건드리지 않습니다.
105
103
 
106
104
  ```bash
107
- uvx --from "python-hwpx-automation[oracle]==7.3.1" \
105
+ uvx --from "python-hwpx-automation[oracle]==7.3.3" \
108
106
  hwpx render-pdf in.hwpx out.pdf --png out/page --json
109
107
  ```
110
108
 
@@ -125,7 +123,8 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
125
123
 
126
124
  ## 안전하게 쓰는 법
127
125
 
128
- 처음부터 모든 도구를 외울 필요는 없습니다. 보통 이렇게 흘러갑니다.
126
+ 처음부터 모든 도구를 외울 필요는 없습니다. 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를,
127
+ 새 문서는 document-plan을 먼저 봅니다. 보통 이렇게 흘러갑니다.
129
128
 
130
129
  1. **읽기** — `get_document_info` → `get_document_outline`/`get_document_text` → `find_text`, `get_table_map`으로 필요한 부분만 파악합니다. (저장하지 않음)
131
130
  2. **안전 수정** — `copy_document`로 사본을 만들고, 가장 작은 변경(`search_and_replace`, `set_table_cell_text`, `apply_document_commands`)을 적용한 뒤 다시 읽어 확인하고, 검토가 끝난 사본을 전달합니다.
@@ -138,7 +137,7 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
138
137
  열림안전을 검사하고, 게이트가 실패하면 아무것도 쓰지 않습니다. capability
139
138
  handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단합니다.
140
139
  보안 상세: [하드닝 가이드](docs/hardening_guide_ko.md) · 옛 이름과의 호환
141
- 식별자: [6.x 호환 표면](docs/compatibility-6x.md)
140
+ 식별자: [호환 표면](docs/compatibility-6x.md)
142
141
 
143
142
  > **위치 계약** — `paragraph_index`는 본문 직속 문단의 0-based 인덱스입니다. 표 안 문단은 여기 섞지 않고
144
143
  > `{"kind":"table_cell_paragraph","table_index":0,"row":0,"col":1,"cell_paragraph_index":0}` 같은 `location`
@@ -159,10 +158,10 @@ handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단
159
158
  | `HWPX_AUTOMATION_WORKFLOW_STORE` | durable workflow SQLite 경로. 기존 `HWPX_WORKFLOW_STORE`보다 우선 | 기존 6.x 상태 경로 |
160
159
  | `LOG_LEVEL` | 로그 레벨 | `INFO` |
161
160
 
162
- 동일 suffix의 기존 `HWPX_MCP_*` 키는 6.x 동안 fallback으로 유지되며, 두 키가
161
+ 동일 suffix의 기존 `HWPX_MCP_*` 키는 fallback으로 유지되며, 두 키가
163
162
  함께 있으면 `HWPX_AUTOMATION_*`이 우선합니다. render·workflow·oracle·plugin
164
163
  연동용 보존 키 전체 목록과 workflow DB 경로 규칙은
165
- [6.x 호환 표면](docs/compatibility-6x.md)에 있습니다.
164
+ [호환 표면](docs/compatibility-6x.md)에 있습니다.
166
165
 
167
166
  경로는 기본적으로 workspace 밖 traversal과 symlink escape를 거부하고, URL 입력은 HTTPS·공개 IP만
168
167
  허용합니다. 원자 rename을 제공하지 않는 호스트의 동시성 주의사항은 [하드닝 가이드](docs/hardening_guide_ko.md)를 보세요.
@@ -193,5 +192,3 @@ python scripts/run_conformance.py run \
193
192
  ## License · Maintainer
194
193
 
195
194
  Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
196
-
197
- 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를 먼저 확인하세요. 새 문서는 document-plan, 에이전트 연결은 선택 MCP와 호스트 플러그인을 사용합니다.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-hwpx-automation"
7
- version = "7.3.1"
7
+ version = "7.3.3"
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" }]
@@ -14,8 +14,15 @@ from uuid import uuid4
14
14
  from xml.etree import ElementTree as ET
15
15
 
16
16
  from ..compat import patch_python_hwpx
17
- from ..storage import build_hwpx_open_safety_report
18
- from ..upstream import HP_NS as _HP_NS, HwpxDocument, repair_pathological_text_spacing
17
+ from ..storage import build_hwpx_open_safety_report, open_local_document
18
+ from ..upstream import (
19
+ HP_NS as _HP_NS,
20
+ HwpxDocument,
21
+ is_hwp5_source,
22
+ is_hwp5_target,
23
+ repair_pathological_text_spacing,
24
+ )
25
+ from .document import save_doc
19
26
  from .formatting import resolve_style_id
20
27
  from .locations import resolve_paragraph_reference
21
28
 
@@ -500,6 +507,15 @@ def copy_document_file(source: str, destination: str = None) -> str:
500
507
  destination = f"{stem}_copy.{ext}"
501
508
  source_path = Path(source)
502
509
  destination_path = Path(destination)
510
+ if is_hwp5_source(source_path) != is_hwp5_target(destination_path):
511
+ # The destination extension picks the format, so a copy between .hwp
512
+ # and .hwpx is written through the document model, not byte-copied.
513
+ document = open_local_document(source_path, role="copy source")
514
+ try:
515
+ save_doc(document, str(destination_path))
516
+ finally:
517
+ document.close()
518
+ return str(destination_path)
503
519
  if source_path.suffix.lower() != ".hwpx" and destination_path.suffix.lower() != ".hwpx":
504
520
  shutil.copy2(source_path, destination_path)
505
521
  return str(destination_path)
@@ -5,7 +5,7 @@ from pathlib import Path
5
5
  from typing import Any
6
6
 
7
7
  from ..configuration import env_value
8
- from ..storage import LocalDocumentStorage, require_hwpx_editor_open_safe
8
+ from ..storage import LocalDocumentStorage, open_local_document
9
9
  from ..upstream import HwpxDocument, blank_document_template_bytes, open_document
10
10
 
11
11
 
@@ -18,8 +18,7 @@ def _local_storage() -> LocalDocumentStorage:
18
18
  def open_doc(path: str) -> HwpxDocument:
19
19
  if not os.path.exists(path):
20
20
  raise FileNotFoundError(f"파일을 찾을 수 없습니다: {path}")
21
- require_hwpx_editor_open_safe(Path(path), role="local HWPX open")
22
- return open_document(path)
21
+ return open_local_document(Path(path), role="local HWPX open")
23
22
 
24
23
 
25
24
  def save_doc(doc: HwpxDocument, path: str, *, quality: Any = None) -> dict[str, Any]:
@@ -12,8 +12,12 @@ from pathlib import Path
12
12
  from typing import Any, Iterable
13
13
 
14
14
  from .. import quality as quality_contract
15
- from ..storage import build_hwpx_verification_report, require_hwpx_editor_open_safe
16
- from ..upstream import HwpxDocument, open_document
15
+ from ..storage import (
16
+ build_hwpx_verification_report,
17
+ require_hwpx_editor_open_safe,
18
+ require_native_hwp5,
19
+ )
20
+ from ..upstream import HwpxDocument, hwp5_document_bytes, is_hwp5_target, open_document
17
21
 
18
22
  _MAX_SUMMARY_ITEMS = 20
19
23
  _MAX_SNIPPET = 80
@@ -341,9 +345,13 @@ def save_dry_run(
341
345
  document: HwpxDocument, target: str | Path, *, quality: Any = None
342
346
  ) -> dict[str, Any]:
343
347
  target_path = Path(target)
348
+ hwp_target = is_hwp5_target(target_path)
349
+ if hwp_target:
350
+ require_native_hwp5()
351
+ # The gate checks HWPX parts, so an .hwp target is staged as HWPX.
344
352
  fd, tmp_name = tempfile.mkstemp(
345
353
  prefix=f".{target_path.stem}.dry-run.",
346
- suffix=target_path.suffix or ".hwpx",
354
+ suffix=".hwpx" if hwp_target else (target_path.suffix or ".hwpx"),
347
355
  dir=str(target_path.parent),
348
356
  )
349
357
  tmp_path = Path(tmp_name)
@@ -366,6 +374,10 @@ def save_dry_run(
366
374
  "dry-run HWPX failed open-safety verification: "
367
375
  + verification["openSafety"]["summary"]
368
376
  )
377
+ if hwp_target:
378
+ # Raises Hwp5Error (hwp5-write-unsupported) as the real save would.
379
+ hwp5_document_bytes(document)
380
+ verification["format"] = "hwp"
369
381
  diff = semantic_diff(target_path, tmp_path) if target_path.exists() else None
370
382
  verification["filePath"] = str(target_path)
371
383
  verification["dryRunTempDeleted"] = True
@@ -73,6 +73,7 @@ DEFAULT_ERROR_SUGGESTIONS: dict[str, str] = {
73
73
  "EMPTY_MATCH": "찾을 텍스트나 앵커 조건을 실제 문서 내용에 맞게 수정하세요.",
74
74
  "HWP_CONVERSION_FAILED": "원본 HWP가 손상되지 않았는지 확인하고 변환 로그의 원인을 기준으로 다시 시도하세요.",
75
75
  "HWP_TEXT_EXTRACT_FAILED": "HWP 파일을 다른 뷰어에서 열어 유효성을 확인한 뒤 텍스트 추출을 다시 실행하세요.",
76
+ "HWPX_PACKAGE_REQUIRED": "copy_document로 .hwpx 사본을 만들어 이 도구를 쓰고, .hwp가 필요하면 결과를 copy_document로 .hwp 경로에 복사하세요. search_and_replace·set_table_cell_text 같은 문서 편집 도구는 .hwp를 그대로 편집합니다.",
76
77
  "IDEMPOTENT_REPLAY": "이미 적용된 planId입니다. 최신 preview/plan을 새로 만든 뒤 apply를 다시 호출하세요.",
77
78
  "MEMO_NOT_FOUND": "list_memos 또는 문서 리소스에서 memoId를 다시 확인한 뒤 호출하세요.",
78
79
  "MISSING_NODE": "대상 섹션, 문단, 표, 셀이 아직 존재하는지 조회한 뒤 새 앵커로 다시 실행하세요.",
@@ -81,7 +82,10 @@ DEFAULT_ERROR_SUGGESTIONS: dict[str, str] = {
81
82
  "PIPELINE_ERROR": "details.pipelineCode와 hint를 확인한 뒤 preview부터 다시 생성하세요.",
82
83
  "PLAN_RECORD_MISSING": "preview_edit 또는 plan_edit으로 planId를 새로 발급받은 뒤 apply를 다시 호출하세요.",
83
84
  "PREVIEW_REQUIRED": "preview_edit으로 변경 내용을 확인한 뒤 반환된 planId로 apply_edit을 호출하세요.",
84
- "READ_ONLY_HWP_DOCUMENT": "HWP 바이너리는 직접 저장할 수 없습니다. 먼저 HWPX로 변환한 뒤 편집하세요.",
85
+ "HWP_DOCUMENT_UNREADABLE": "한/글에서 문서를 열어 다시 저장한 뒤 사용하세요. details.hwp5Code가 원인입니다.",
86
+ "HWP_ENCRYPTED_DOCUMENT": "한/글에서 문서 암호·배포용 보호를 풀고 다시 저장한 뒤 사용하세요. DRM 문서는 열 수 없습니다.",
87
+ "HWP_WRITE_UNSUPPORTED": "HWP 5.0으로 쓸 수 없는 내용이 있습니다. 출력 경로를 .hwpx로 지정해 저장하세요.",
88
+ "READ_ONLY_HWP_DOCUMENT": "python-hwpx 6.6.0 이상을 설치하면 .hwp 문서를 그대로 열고 편집·저장할 수 있습니다.",
85
89
  "RENDER_PREVIEW_INVALID_MODE": "mode는 'pages' 또는 'long'으로 지정한 뒤 다시 실행하세요.",
86
90
  "RENDER_PREVIEW_INVALID_SCREENSHOT_MODE": "screenshot은 'auto', 'require', 'off' 중 하나로 지정하세요.",
87
91
  "RENDER_PREVIEW_UNAVAILABLE": "matching python-hwpx 버전을 설치하고 MCP 서버를 새로 시작한 뒤 다시 실행하세요.",
@@ -175,3 +179,52 @@ def build_error_payload(
175
179
  suggestion=suggestion
176
180
  or suggestion_for_error(code, details=details, hint=hint),
177
181
  ).model_dump(exclude_none=True, by_alias=True)
182
+
183
+
184
+ class HwpDocumentError(RuntimeError):
185
+ """An ``.hwp`` request the installed engine cannot carry out."""
186
+
187
+ def __init__(
188
+ self, message: str, *, code: str, details: Optional[Dict[str, Any]] = None
189
+ ) -> None:
190
+ super().__init__(message)
191
+ self.code = code
192
+ self.message = message
193
+ self.details = details
194
+
195
+ def to_payload(self) -> Dict[str, Any]:
196
+ return build_error_payload(
197
+ code=self.code, message=self.message, details=self.details
198
+ )
199
+
200
+
201
+ _HWP5_ENCRYPTED_CODES = frozenset({"hwp5-password", "hwp5-distribution", "hwp5-drm"})
202
+
203
+
204
+ def hwp5_error_payload(exc: BaseException) -> Optional[Dict[str, Any]]:
205
+ """The MCP error for python-hwpx's ``Hwp5Error``; None for any other exception.
206
+
207
+ Matched by its ``hwp5-*`` code so this module needs no core import.
208
+ """
209
+
210
+ hwp5_code = getattr(exc, "code", None)
211
+ if not isinstance(hwp5_code, str) or not hwp5_code.startswith("hwp5-"):
212
+ return None
213
+ details = {"hwp5Code": hwp5_code}
214
+ if hwp5_code == "hwp5-write-unsupported":
215
+ return build_error_payload(
216
+ code="HWP_WRITE_UNSUPPORTED",
217
+ message="문서에 HWP 5.0(.hwp)으로 쓸 수 없는 내용이 있어 아무것도 저장하지 않았습니다.",
218
+ details=details,
219
+ )
220
+ if hwp5_code in _HWP5_ENCRYPTED_CODES:
221
+ return build_error_payload(
222
+ code="HWP_ENCRYPTED_DOCUMENT",
223
+ message="암호·배포용·DRM으로 보호된 HWP 문서는 열 수 없습니다.",
224
+ details=details,
225
+ )
226
+ return build_error_payload(
227
+ code="HWP_DOCUMENT_UNREADABLE",
228
+ message="HWP 5.0(.hwp) 문서를 읽을 수 없습니다.",
229
+ details=details,
230
+ )
@@ -9,6 +9,8 @@ from typing import Any
9
9
 
10
10
 
11
11
  from ..document_state import document_state_payload
12
+ from ..errors import HwpDocumentError
13
+ from ..storage import require_hwpx_package
12
14
  from ..agent_document import (
13
15
  AgentChildLimit,
14
16
  AgentCommandList,
@@ -100,6 +102,7 @@ def apply_document_commands(
100
102
  try:
101
103
  resolved_input = resolve_path(filename)
102
104
  resolved_output = resolve_path(output)
105
+ require_hwpx_package(resolved_input, output=resolved_output)
103
106
  quality_contract.assert_write_capability()
104
107
  store = ScopedIdempotencyStore(
105
108
  RUNTIME_SERVICES.idempotency_cache,
@@ -132,6 +135,8 @@ def apply_document_commands(
132
135
  if Path(state_path).exists():
133
136
  payload.update(document_state_payload(state_path))
134
137
  return payload
138
+ except HwpDocumentError:
139
+ raise
135
140
  except Exception as exc:
136
141
  return agent_batch_error_payload(
137
142
  exc,
@@ -35,6 +35,7 @@ from ..office.compliance import DEFAULT_POLICY, mask_pii
35
35
  from ..runtime_services import RUNTIME_SERVICES
36
36
  from ..upstream import (
37
37
  HP_NS,
38
+ hwp5_conversion_report,
38
39
  open_document,
39
40
  )
40
41
  from ..utils.helpers import default_max_chars, resolve_path, truncate_response
@@ -777,16 +778,19 @@ def get_document_info(filename: str) -> dict:
777
778
  path = resolve_path(filename)
778
779
  doc = open_doc(path)
779
780
  file_size = Path(path).stat().st_size
780
- return _with_document_state(
781
- {
782
- "filename": filename,
783
- "sections": len(doc.sections),
784
- "paragraphs": _paragraph_count(doc),
785
- "tables": _table_count(doc),
786
- "file_size": str(file_size),
787
- },
788
- path,
789
- )
781
+ info: dict[str, Any] = {
782
+ "filename": filename,
783
+ "sections": len(doc.sections),
784
+ "paragraphs": _paragraph_count(doc),
785
+ "tables": _table_count(doc),
786
+ "file_size": str(file_size),
787
+ }
788
+ conversion = hwp5_conversion_report(doc)
789
+ if conversion is not None:
790
+ # An .hwp is edited through the document model; this is what it left out.
791
+ info["format"] = "hwp"
792
+ info["hwpConversion"] = conversion
793
+ return _with_document_state(info, path)
790
794
 
791
795
 
792
796
  def get_document_text(
@@ -5,27 +5,27 @@
5
5
  "releaseState": {
6
6
  "status": "release-approved",
7
7
  "candidate": {
8
- "pythonHwpx": "6.5.0",
8
+ "pythonHwpx": "6.6.0",
9
9
  "canonicalDistribution": "python-hwpx-automation",
10
- "canonicalAutomation": "7.3.1",
10
+ "canonicalAutomation": "7.3.3",
11
11
  "compatibilityDistribution": "hwpx-mcp-server",
12
- "compatibility": "7.3.1",
13
- "plugin": "2.3.0",
12
+ "compatibility": "7.3.3",
13
+ "plugin": "2.4.0",
14
14
  "contractHash": "5e5c23651f92785a"
15
15
  },
16
16
  "currentPublic": {
17
- "pythonHwpx": "6.5.0",
17
+ "pythonHwpx": "6.6.0",
18
18
  "primaryDistribution": "python-hwpx-automation",
19
- "primaryApplication": "7.2.0",
20
- "plugin": "2.3.0",
19
+ "primaryApplication": "7.3.1",
20
+ "plugin": "2.4.0",
21
21
  "contractHash": "5e5c23651f92785a"
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
  "previousPublic": {
25
- "pythonHwpx": "6.5.0",
25
+ "pythonHwpx": "6.6.0",
26
26
  "primaryDistribution": "python-hwpx-automation",
27
- "primaryApplication": "7.2.0",
28
- "plugin": "2.3.0",
27
+ "primaryApplication": "7.3.1",
28
+ "plugin": "2.4.0",
29
29
  "contractHash": "5e5c23651f92785a"
30
30
  },
31
31
  "publicationEvidence": null
@@ -41,7 +41,7 @@ from pydantic import (
41
41
  from .execution_lock import PUBLIC_MUTATION_LOCK
42
42
  from .office.agent._batch_publication import GuardedSavePipeline
43
43
  from .office.rendering import resolve_hancom_backend
44
- from .storage import build_hwpx_open_safety_report
44
+ from .storage import build_hwpx_open_safety_report, require_hwpx_package
45
45
  from .utils.helpers import resolve_path
46
46
  from .workspace import (
47
47
  WorkspaceMissingParentGuard,
@@ -1374,6 +1374,7 @@ def analyze_mixed_form_plan(
1374
1374
 
1375
1375
  request = _authorize_public_plan(_payload(plan, apply=False))
1376
1376
  source = Path(request["source"])
1377
+ require_hwpx_package(source, output=request["output"])
1377
1378
  source_snapshot = _capture_path_snapshot(source)
1378
1379
  if source_snapshot.data is None:
1379
1380
  raise FileNotFoundError(source)
@@ -1494,6 +1495,7 @@ def _apply_canonical_mixed_form_plan_locked(
1494
1495
 
1495
1496
  compiled = validate_mixed_form_plan(compiled).to_dict()
1496
1497
  source, output = _authorize_compiled_plan(compiled)
1498
+ require_hwpx_package(source, output=output)
1497
1499
  source_snapshot = _capture_path_snapshot(source)
1498
1500
  if source_snapshot.data is None: # pragma: no cover - compiled plan invariant
1499
1501
  raise FileNotFoundError(source)
@@ -85,14 +85,9 @@ def parse_government_report_text(text: str, *, title: str = "") -> dict[str, Any
85
85
  flush_bullets()
86
86
  flush_table()
87
87
 
88
- if not blocks:
89
- fallback = normalize_cell_text(title) or "본문"
90
- blocks.append({"type": "paragraph", "text": fallback})
91
-
92
- metadata: dict[str, str] = {}
93
88
  normalized_title = normalize_cell_text(title)
94
- if normalized_title:
95
- metadata["title"] = normalized_title
89
+ metadata = {"title": normalized_title} if normalized_title else {}
90
+ blocks = _with_title_block(blocks, normalized_title) or [{"type": "paragraph", "text": "본문"}]
96
91
 
97
92
  return {
98
93
  "schemaVersion": DOCUMENT_PLAN_V2_SCHEMA_VERSION,
@@ -102,6 +97,23 @@ def parse_government_report_text(text: str, *, title: str = "") -> dict[str, Any
102
97
  }
103
98
 
104
99
 
100
+ def _with_title_block(blocks: list[dict[str, Any]], title: str) -> list[dict[str, Any]]:
101
+ """Put *title* at the top of the body as a centred bold paragraph.
102
+
103
+ The plan title and metadata go to the document properties, not the body, so
104
+ a report shows its title only through a body block. A first line that
105
+ already is the title becomes that block instead of a copy.
106
+ """
107
+
108
+ if not title:
109
+ return blocks
110
+ rest = blocks
111
+ if rest and rest[0].get("type") in {"paragraph", "heading"} and rest[0].get("text") == title:
112
+ rest = rest[1:]
113
+ title_block = {"type": "paragraph", "align": "center", "runs": [{"text": title, "bold": True}]}
114
+ return [title_block, *rest]
115
+
116
+
105
117
  def _parse_heading(line: str) -> tuple[int, str] | None:
106
118
  markdown_match = _MARKDOWN_HEADING_RE.match(line)
107
119
  if markdown_match:
@@ -124,13 +124,35 @@ function Copy-ToTrustedTemp {
124
124
  return @{ Directory = $dir; Path = $target }
125
125
  }
126
126
 
127
- function New-HwpObject {
128
- $hwp = New-Object -ComObject "HWPFrame.HwpObject"
127
+ function Register-FilePathCheck {
128
+ # True when Hancom accepted a file-path check module. The module name is a
129
+ # value name under HKCU\SOFTWARE\HNC\HwpAutomation\Modules:
130
+ # HWPX_HANCOM_SECURITY_MODULE first, then Hancom's example name, then every
131
+ # other value registered there. The module type is always "FilePathCheckDLL".
132
+ param($Hwp)
133
+ $names = New-Object System.Collections.Generic.List[string]
134
+ if ($env:HWPX_HANCOM_SECURITY_MODULE) { $names.Add([string]$env:HWPX_HANCOM_SECURITY_MODULE) }
135
+ if (-not $names.Contains("FilePathCheckerModuleExample")) { $names.Add("FilePathCheckerModuleExample") }
129
136
  try {
130
- $null = $hwp.RegisterModule("FilePathCheckerModule", "FilePathCheckerModuleExample")
131
- } catch {
132
- Write-Warning ("RegisterModule FilePathCheckerModule failed: " + $_.Exception.Message)
137
+ $key = Get-Item -LiteralPath "HKCU:\SOFTWARE\HNC\HwpAutomation\Modules" -ErrorAction Stop
138
+ foreach ($name in $key.GetValueNames()) {
139
+ if ($name -and -not $names.Contains($name)) { $names.Add($name) }
140
+ }
141
+ } catch {}
142
+ foreach ($name in $names) {
143
+ try {
144
+ if ([bool]$Hwp.RegisterModule("FilePathCheckDLL", $name)) { return $true }
145
+ } catch {}
133
146
  }
147
+ return $false
148
+ }
149
+
150
+ function New-HwpObject {
151
+ $hwp = New-Object -ComObject "HWPFrame.HwpObject"
152
+ # Inputs are opened from a copy in %TEMP% (Copy-ToTrustedTemp), which Hancom
153
+ # opens without its access-approval prompt. A registered file-path check
154
+ # module is used as well when there is one.
155
+ $null = Register-FilePathCheck $hwp
134
156
  # FR-002a: suppress modal dialogs. The negative controls (FR-005) prove the
135
157
  # suppressed default action is NOT silent auto-repair.
136
158
  try { $null = $hwp.SetMessageBoxMode($MESSAGE_BOX_MODE) } catch {
@@ -98,7 +98,10 @@ end windowNames
98
98
 
99
99
  on listContains(theList, theValue)
100
100
  repeat with x in theList
101
- if (x as string) is theValue then return true
101
+ -- a window without a title (missing value) cannot become a string
102
+ try
103
+ if (x as string) is theValue then return true
104
+ end try
102
105
  end repeat
103
106
  return false
104
107
  end listContains