python-hwpx-automation 6.0.3__py3-none-any.whl

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 (217) hide show
  1. hwpx_automation/__init__.py +61 -0
  2. hwpx_automation/__init__.pyi +27 -0
  3. hwpx_automation/__main__.py +8 -0
  4. hwpx_automation/agent_document.py +392 -0
  5. hwpx_automation/api.py +136 -0
  6. hwpx_automation/blind_eval.py +407 -0
  7. hwpx_automation/capabilities.py +110 -0
  8. hwpx_automation/compat.py +48 -0
  9. hwpx_automation/configuration.py +60 -0
  10. hwpx_automation/core/__init__.py +2 -0
  11. hwpx_automation/core/content.py +762 -0
  12. hwpx_automation/core/context.py +111 -0
  13. hwpx_automation/core/diff.py +53 -0
  14. hwpx_automation/core/document.py +37 -0
  15. hwpx_automation/core/formatting.py +513 -0
  16. hwpx_automation/core/handles.py +24 -0
  17. hwpx_automation/core/locations.py +205 -0
  18. hwpx_automation/core/locator.py +162 -0
  19. hwpx_automation/core/plan.py +680 -0
  20. hwpx_automation/core/resources.py +42 -0
  21. hwpx_automation/core/search.py +296 -0
  22. hwpx_automation/core/transactions.py +434 -0
  23. hwpx_automation/core/txn.py +48 -0
  24. hwpx_automation/document_state.py +95 -0
  25. hwpx_automation/errors.py +174 -0
  26. hwpx_automation/execution_lock.py +15 -0
  27. hwpx_automation/fastmcp_adapter.py +672 -0
  28. hwpx_automation/form_fill.py +1177 -0
  29. hwpx_automation/form_output_models.py +223 -0
  30. hwpx_automation/handlers/__init__.py +2 -0
  31. hwpx_automation/handlers/_shared.py +377 -0
  32. hwpx_automation/handlers/agent_document.py +257 -0
  33. hwpx_automation/handlers/authoring.py +750 -0
  34. hwpx_automation/handlers/content_edit.py +1078 -0
  35. hwpx_automation/handlers/form_fill.py +607 -0
  36. hwpx_automation/handlers/layout_style.py +660 -0
  37. hwpx_automation/handlers/quality_render.py +566 -0
  38. hwpx_automation/handlers/read_export.py +1295 -0
  39. hwpx_automation/handlers/specialized.py +624 -0
  40. hwpx_automation/handlers/tracked_changes.py +589 -0
  41. hwpx_automation/handlers/workflow.py +105 -0
  42. hwpx_automation/hwp_converter.py +227 -0
  43. hwpx_automation/hwp_support.py +94 -0
  44. hwpx_automation/hwpx_ops.py +1439 -0
  45. hwpx_automation/identity.json +263 -0
  46. hwpx_automation/identity.py +18 -0
  47. hwpx_automation/ingest_adapters.py +85 -0
  48. hwpx_automation/markdown_plan.py +216 -0
  49. hwpx_automation/mcp_cli.py +29 -0
  50. hwpx_automation/metadata/tools_meta.py +40 -0
  51. hwpx_automation/mixed_form.py +3007 -0
  52. hwpx_automation/mutation_models.py +401 -0
  53. hwpx_automation/network_policy.py +232 -0
  54. hwpx_automation/office/__init__.py +14 -0
  55. hwpx_automation/office/agent/__init__.py +125 -0
  56. hwpx_automation/office/agent/_batch_verification.py +383 -0
  57. hwpx_automation/office/agent/blueprint/__init__.py +58 -0
  58. hwpx_automation/office/agent/blueprint/bundle.py +282 -0
  59. hwpx_automation/office/agent/blueprint/catalog.py +136 -0
  60. hwpx_automation/office/agent/blueprint/dump.py +520 -0
  61. hwpx_automation/office/agent/blueprint/mapping.py +312 -0
  62. hwpx_automation/office/agent/blueprint/model.py +722 -0
  63. hwpx_automation/office/agent/blueprint/native.py +621 -0
  64. hwpx_automation/office/agent/blueprint/replay.py +622 -0
  65. hwpx_automation/office/agent/catalog.py +252 -0
  66. hwpx_automation/office/agent/cli.py +647 -0
  67. hwpx_automation/office/agent/commands.py +1383 -0
  68. hwpx_automation/office/agent/document.py +801 -0
  69. hwpx_automation/office/agent/form_plan.py +1760 -0
  70. hwpx_automation/office/agent/model.py +808 -0
  71. hwpx_automation/office/agent/path.py +155 -0
  72. hwpx_automation/office/agent/query.py +230 -0
  73. hwpx_automation/office/agent/story.py +207 -0
  74. hwpx_automation/office/authoring/__init__.py +3542 -0
  75. hwpx_automation/office/authoring/advanced_generators.py +154 -0
  76. hwpx_automation/office/authoring/builder/__init__.py +52 -0
  77. hwpx_automation/office/authoring/builder/core.py +996 -0
  78. hwpx_automation/office/authoring/builder/report.py +195 -0
  79. hwpx_automation/office/authoring/design/__init__.py +30 -0
  80. hwpx_automation/office/authoring/design/_support.py +144 -0
  81. hwpx_automation/office/authoring/design/composer.py +282 -0
  82. hwpx_automation/office/authoring/design/harvest.py +305 -0
  83. hwpx_automation/office/authoring/design/plan.py +69 -0
  84. hwpx_automation/office/authoring/design/profile.py +88 -0
  85. hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +1 -0
  86. hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +1 -0
  87. hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +1 -0
  88. hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +1 -0
  89. hwpx_automation/office/authoring/design/profiles/application_form/profile.json +25 -0
  90. hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
  91. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +1 -0
  92. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +1 -0
  93. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +1 -0
  94. hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +24 -0
  95. hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
  96. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +1 -0
  97. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +1 -0
  98. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +1 -0
  99. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +1 -0
  100. hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +25 -0
  101. hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
  102. hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +1 -0
  103. hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +1 -0
  104. hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +1 -0
  105. hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +1 -0
  106. hwpx_automation/office/authoring/design/profiles/report/profile.json +25 -0
  107. hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
  108. hwpx_automation/office/authoring/design/validator.py +107 -0
  109. hwpx_automation/office/authoring/presets/__init__.py +22 -0
  110. hwpx_automation/office/authoring/presets/proposal.py +538 -0
  111. hwpx_automation/office/authoring/report_parser.py +141 -0
  112. hwpx_automation/office/authoring/style_profile.py +437 -0
  113. hwpx_automation/office/authoring/template_analyzer.py +657 -0
  114. hwpx_automation/office/compliance/__init__.py +38 -0
  115. hwpx_automation/office/compliance/official_lint.py +478 -0
  116. hwpx_automation/office/compliance/pii.py +388 -0
  117. hwpx_automation/office/document_ops/__init__.py +13 -0
  118. hwpx_automation/office/document_ops/comparison.py +62 -0
  119. hwpx_automation/office/document_ops/mail_merge.py +73 -0
  120. hwpx_automation/office/document_ops/redline.py +35 -0
  121. hwpx_automation/office/evalplan/__init__.py +36 -0
  122. hwpx_automation/office/evalplan/runtime.py +2762 -0
  123. hwpx_automation/office/exam/__init__.py +44 -0
  124. hwpx_automation/office/exam/compose.py +282 -0
  125. hwpx_automation/office/exam/ir.py +44 -0
  126. hwpx_automation/office/exam/measure.py +163 -0
  127. hwpx_automation/office/exam/parser.py +150 -0
  128. hwpx_automation/office/exam/profile.py +123 -0
  129. hwpx_automation/office/form_fill/__init__.py +66 -0
  130. hwpx_automation/office/form_fill/classification.py +108 -0
  131. hwpx_automation/office/form_fill/fill_residue.py +242 -0
  132. hwpx_automation/office/form_fill/fit/__init__.py +36 -0
  133. hwpx_automation/office/form_fill/fit/apply.py +24 -0
  134. hwpx_automation/office/form_fill/fit/engine.py +24 -0
  135. hwpx_automation/office/form_fill/fit/measure.py +50 -0
  136. hwpx_automation/office/form_fill/fit/policy.py +28 -0
  137. hwpx_automation/office/form_fill/fit/report.py +28 -0
  138. hwpx_automation/office/form_fill/fit/seal.py +457 -0
  139. hwpx_automation/office/form_fill/fit/wordbox.py +1343 -0
  140. hwpx_automation/office/form_fill/guidance.py +704 -0
  141. hwpx_automation/office/form_fill/quality.py +961 -0
  142. hwpx_automation/office/form_fill/split_run.py +333 -0
  143. hwpx_automation/office/form_fill/template_formfit.py +656 -0
  144. hwpx_automation/office/house_style/__init__.py +196 -0
  145. hwpx_automation/office/house_style/composition.py +68 -0
  146. hwpx_automation/office/house_style/data/bank.json +625 -0
  147. hwpx_automation/office/house_style/data/genres.json +43 -0
  148. hwpx_automation/office/quality/__init__.py +14 -0
  149. hwpx_automation/office/quality/page_guard.py +277 -0
  150. hwpx_automation/office/rendering/__init__.py +145 -0
  151. hwpx_automation/office/rendering/_hancom_open_rate.ps1 +374 -0
  152. hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +162 -0
  153. hwpx_automation/office/rendering/_render_hwpx.ps1 +72 -0
  154. hwpx_automation/office/rendering/_render_hwpx_mac.applescript +249 -0
  155. hwpx_automation/office/rendering/block_splits.py +76 -0
  156. hwpx_automation/office/rendering/detectors.py +151 -0
  157. hwpx_automation/office/rendering/diff.py +153 -0
  158. hwpx_automation/office/rendering/fixture_corpus.py +215 -0
  159. hwpx_automation/office/rendering/oracle.py +909 -0
  160. hwpx_automation/office/rendering/page_qa.py +245 -0
  161. hwpx_automation/office/rendering/qa_contracts.py +293 -0
  162. hwpx_automation/office/rendering/qa_metrics.py +241 -0
  163. hwpx_automation/office/rendering/worker.py +290 -0
  164. hwpx_automation/office/utilities/__init__.py +12 -0
  165. hwpx_automation/office/utilities/table_compute.py +477 -0
  166. hwpx_automation/ops_services/__init__.py +1 -0
  167. hwpx_automation/ops_services/_border_fill.py +283 -0
  168. hwpx_automation/ops_services/composition.py +55 -0
  169. hwpx_automation/ops_services/content_layout.py +322 -0
  170. hwpx_automation/ops_services/context.py +213 -0
  171. hwpx_automation/ops_services/form_fields.py +557 -0
  172. hwpx_automation/ops_services/media.py +178 -0
  173. hwpx_automation/ops_services/memo_style.py +477 -0
  174. hwpx_automation/ops_services/package_validation.py +166 -0
  175. hwpx_automation/ops_services/planning.py +201 -0
  176. hwpx_automation/ops_services/preview_export.py +585 -0
  177. hwpx_automation/ops_services/read_query.py +601 -0
  178. hwpx_automation/ops_services/save_policy.py +604 -0
  179. hwpx_automation/ops_services/tables.py +539 -0
  180. hwpx_automation/ops_services/transactions.py +616 -0
  181. hwpx_automation/preview_output_models.py +69 -0
  182. hwpx_automation/public-modules.json +206 -0
  183. hwpx_automation/py.typed +1 -0
  184. hwpx_automation/quality.py +351 -0
  185. hwpx_automation/quality_generation.py +725 -0
  186. hwpx_automation/runtime.py +321 -0
  187. hwpx_automation/runtime_services.py +100 -0
  188. hwpx_automation/server.py +259 -0
  189. hwpx_automation/storage.py +747 -0
  190. hwpx_automation/tool_bindings.py +170 -0
  191. hwpx_automation/tool_contract.py +982 -0
  192. hwpx_automation/upstream.py +755 -0
  193. hwpx_automation/utils/__init__.py +2 -0
  194. hwpx_automation/utils/helpers.py +29 -0
  195. hwpx_automation/visual_qa.py +667 -0
  196. hwpx_automation/workflow/__init__.py +55 -0
  197. hwpx_automation/workflow/adapters.py +482 -0
  198. hwpx_automation/workflow/dispatcher.py +213 -0
  199. hwpx_automation/workflow/models.py +243 -0
  200. hwpx_automation/workflow/policy.py +198 -0
  201. hwpx_automation/workflow/render_contracts.py +173 -0
  202. hwpx_automation/workflow/render_metrics.py +196 -0
  203. hwpx_automation/workflow/render_queue.py +482 -0
  204. hwpx_automation/workflow/render_security.py +172 -0
  205. hwpx_automation/workflow/render_transport.py +369 -0
  206. hwpx_automation/workflow/rendering.py +206 -0
  207. hwpx_automation/workflow/service.py +758 -0
  208. hwpx_automation/workflow/state_machine.py +65 -0
  209. hwpx_automation/workflow/store.py +747 -0
  210. hwpx_automation/workspace.py +1694 -0
  211. python_hwpx_automation-6.0.3.dist-info/METADATA +279 -0
  212. python_hwpx_automation-6.0.3.dist-info/RECORD +217 -0
  213. python_hwpx_automation-6.0.3.dist-info/WHEEL +5 -0
  214. python_hwpx_automation-6.0.3.dist-info/entry_points.txt +3 -0
  215. python_hwpx_automation-6.0.3.dist-info/licenses/LICENSE +178 -0
  216. python_hwpx_automation-6.0.3.dist-info/licenses/NOTICE +14 -0
  217. python_hwpx_automation-6.0.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,206 @@
1
+ {
2
+ "schemaVersion": "python-hwpx-automation.public-modules/v1",
3
+ "scope": "All Python modules shipped by the canonical 6.x distribution. Base-public modules must import without the optional MCP SDK; the five adapter modules require the mcp extra by design.",
4
+ "moduleCount": 177,
5
+ "moduleSha256": "4fb2c3852fef3aa83ff1c8ddbbb40feca55889b478cfabfa7e304f25c22d5c06",
6
+ "basePublicModuleCount": 172,
7
+ "basePublicModuleSha256": "ae0e52305fae27f664d71c475a9d40041c02b635955259cf9b9a622b81371547",
8
+ "basePublicModules": [
9
+ "hwpx_automation",
10
+ "hwpx_automation.__main__",
11
+ "hwpx_automation.agent_document",
12
+ "hwpx_automation.api",
13
+ "hwpx_automation.blind_eval",
14
+ "hwpx_automation.capabilities",
15
+ "hwpx_automation.compat",
16
+ "hwpx_automation.configuration",
17
+ "hwpx_automation.core",
18
+ "hwpx_automation.core.content",
19
+ "hwpx_automation.core.context",
20
+ "hwpx_automation.core.diff",
21
+ "hwpx_automation.core.document",
22
+ "hwpx_automation.core.formatting",
23
+ "hwpx_automation.core.handles",
24
+ "hwpx_automation.core.locations",
25
+ "hwpx_automation.core.locator",
26
+ "hwpx_automation.core.plan",
27
+ "hwpx_automation.core.resources",
28
+ "hwpx_automation.core.search",
29
+ "hwpx_automation.core.transactions",
30
+ "hwpx_automation.core.txn",
31
+ "hwpx_automation.document_state",
32
+ "hwpx_automation.errors",
33
+ "hwpx_automation.execution_lock",
34
+ "hwpx_automation.form_fill",
35
+ "hwpx_automation.form_output_models",
36
+ "hwpx_automation.handlers",
37
+ "hwpx_automation.handlers._shared",
38
+ "hwpx_automation.handlers.agent_document",
39
+ "hwpx_automation.handlers.authoring",
40
+ "hwpx_automation.handlers.content_edit",
41
+ "hwpx_automation.handlers.form_fill",
42
+ "hwpx_automation.handlers.layout_style",
43
+ "hwpx_automation.handlers.read_export",
44
+ "hwpx_automation.handlers.specialized",
45
+ "hwpx_automation.handlers.tracked_changes",
46
+ "hwpx_automation.handlers.workflow",
47
+ "hwpx_automation.hwp_converter",
48
+ "hwpx_automation.hwp_support",
49
+ "hwpx_automation.hwpx_ops",
50
+ "hwpx_automation.identity",
51
+ "hwpx_automation.ingest_adapters",
52
+ "hwpx_automation.markdown_plan",
53
+ "hwpx_automation.mcp_cli",
54
+ "hwpx_automation.metadata.tools_meta",
55
+ "hwpx_automation.mixed_form",
56
+ "hwpx_automation.mutation_models",
57
+ "hwpx_automation.network_policy",
58
+ "hwpx_automation.office",
59
+ "hwpx_automation.office.agent",
60
+ "hwpx_automation.office.agent._batch_verification",
61
+ "hwpx_automation.office.agent.blueprint",
62
+ "hwpx_automation.office.agent.blueprint.bundle",
63
+ "hwpx_automation.office.agent.blueprint.catalog",
64
+ "hwpx_automation.office.agent.blueprint.dump",
65
+ "hwpx_automation.office.agent.blueprint.mapping",
66
+ "hwpx_automation.office.agent.blueprint.model",
67
+ "hwpx_automation.office.agent.blueprint.native",
68
+ "hwpx_automation.office.agent.blueprint.replay",
69
+ "hwpx_automation.office.agent.catalog",
70
+ "hwpx_automation.office.agent.cli",
71
+ "hwpx_automation.office.agent.commands",
72
+ "hwpx_automation.office.agent.document",
73
+ "hwpx_automation.office.agent.form_plan",
74
+ "hwpx_automation.office.agent.model",
75
+ "hwpx_automation.office.agent.path",
76
+ "hwpx_automation.office.agent.query",
77
+ "hwpx_automation.office.agent.story",
78
+ "hwpx_automation.office.authoring",
79
+ "hwpx_automation.office.authoring.advanced_generators",
80
+ "hwpx_automation.office.authoring.builder",
81
+ "hwpx_automation.office.authoring.builder.core",
82
+ "hwpx_automation.office.authoring.builder.report",
83
+ "hwpx_automation.office.authoring.design",
84
+ "hwpx_automation.office.authoring.design._support",
85
+ "hwpx_automation.office.authoring.design.composer",
86
+ "hwpx_automation.office.authoring.design.harvest",
87
+ "hwpx_automation.office.authoring.design.plan",
88
+ "hwpx_automation.office.authoring.design.profile",
89
+ "hwpx_automation.office.authoring.design.validator",
90
+ "hwpx_automation.office.authoring.presets",
91
+ "hwpx_automation.office.authoring.presets.proposal",
92
+ "hwpx_automation.office.authoring.report_parser",
93
+ "hwpx_automation.office.authoring.style_profile",
94
+ "hwpx_automation.office.authoring.template_analyzer",
95
+ "hwpx_automation.office.compliance",
96
+ "hwpx_automation.office.compliance.official_lint",
97
+ "hwpx_automation.office.compliance.pii",
98
+ "hwpx_automation.office.document_ops",
99
+ "hwpx_automation.office.document_ops.comparison",
100
+ "hwpx_automation.office.document_ops.mail_merge",
101
+ "hwpx_automation.office.document_ops.redline",
102
+ "hwpx_automation.office.evalplan",
103
+ "hwpx_automation.office.evalplan.runtime",
104
+ "hwpx_automation.office.exam",
105
+ "hwpx_automation.office.exam.compose",
106
+ "hwpx_automation.office.exam.ir",
107
+ "hwpx_automation.office.exam.measure",
108
+ "hwpx_automation.office.exam.parser",
109
+ "hwpx_automation.office.exam.profile",
110
+ "hwpx_automation.office.form_fill",
111
+ "hwpx_automation.office.form_fill.classification",
112
+ "hwpx_automation.office.form_fill.fill_residue",
113
+ "hwpx_automation.office.form_fill.fit",
114
+ "hwpx_automation.office.form_fill.fit.apply",
115
+ "hwpx_automation.office.form_fill.fit.engine",
116
+ "hwpx_automation.office.form_fill.fit.measure",
117
+ "hwpx_automation.office.form_fill.fit.policy",
118
+ "hwpx_automation.office.form_fill.fit.report",
119
+ "hwpx_automation.office.form_fill.fit.seal",
120
+ "hwpx_automation.office.form_fill.fit.wordbox",
121
+ "hwpx_automation.office.form_fill.guidance",
122
+ "hwpx_automation.office.form_fill.quality",
123
+ "hwpx_automation.office.form_fill.split_run",
124
+ "hwpx_automation.office.form_fill.template_formfit",
125
+ "hwpx_automation.office.house_style",
126
+ "hwpx_automation.office.house_style.composition",
127
+ "hwpx_automation.office.quality",
128
+ "hwpx_automation.office.quality.page_guard",
129
+ "hwpx_automation.office.rendering",
130
+ "hwpx_automation.office.rendering.block_splits",
131
+ "hwpx_automation.office.rendering.detectors",
132
+ "hwpx_automation.office.rendering.diff",
133
+ "hwpx_automation.office.rendering.fixture_corpus",
134
+ "hwpx_automation.office.rendering.oracle",
135
+ "hwpx_automation.office.rendering.page_qa",
136
+ "hwpx_automation.office.rendering.qa_contracts",
137
+ "hwpx_automation.office.rendering.qa_metrics",
138
+ "hwpx_automation.office.rendering.worker",
139
+ "hwpx_automation.office.utilities",
140
+ "hwpx_automation.office.utilities.table_compute",
141
+ "hwpx_automation.ops_services",
142
+ "hwpx_automation.ops_services._border_fill",
143
+ "hwpx_automation.ops_services.composition",
144
+ "hwpx_automation.ops_services.content_layout",
145
+ "hwpx_automation.ops_services.context",
146
+ "hwpx_automation.ops_services.form_fields",
147
+ "hwpx_automation.ops_services.media",
148
+ "hwpx_automation.ops_services.memo_style",
149
+ "hwpx_automation.ops_services.package_validation",
150
+ "hwpx_automation.ops_services.planning",
151
+ "hwpx_automation.ops_services.preview_export",
152
+ "hwpx_automation.ops_services.read_query",
153
+ "hwpx_automation.ops_services.save_policy",
154
+ "hwpx_automation.ops_services.tables",
155
+ "hwpx_automation.ops_services.transactions",
156
+ "hwpx_automation.preview_output_models",
157
+ "hwpx_automation.quality",
158
+ "hwpx_automation.quality_generation",
159
+ "hwpx_automation.runtime_services",
160
+ "hwpx_automation.storage",
161
+ "hwpx_automation.tool_contract",
162
+ "hwpx_automation.upstream",
163
+ "hwpx_automation.utils",
164
+ "hwpx_automation.utils.helpers",
165
+ "hwpx_automation.visual_qa",
166
+ "hwpx_automation.workflow",
167
+ "hwpx_automation.workflow.adapters",
168
+ "hwpx_automation.workflow.dispatcher",
169
+ "hwpx_automation.workflow.models",
170
+ "hwpx_automation.workflow.policy",
171
+ "hwpx_automation.workflow.render_contracts",
172
+ "hwpx_automation.workflow.render_metrics",
173
+ "hwpx_automation.workflow.render_queue",
174
+ "hwpx_automation.workflow.render_security",
175
+ "hwpx_automation.workflow.render_transport",
176
+ "hwpx_automation.workflow.rendering",
177
+ "hwpx_automation.workflow.service",
178
+ "hwpx_automation.workflow.state_machine",
179
+ "hwpx_automation.workflow.store",
180
+ "hwpx_automation.workspace"
181
+ ],
182
+ "mcpAdapterModuleCount": 5,
183
+ "mcpAdapterModuleSha256": "89fa1f67eebb1b370021c6285be567f1926155188f5e2df35a6a4a49b1cffb61",
184
+ "mcpAdapterModules": [
185
+ {
186
+ "module": "hwpx_automation.fastmcp_adapter",
187
+ "reason": "Imports FastMCP protocol types and implements the adapter boundary."
188
+ },
189
+ {
190
+ "module": "hwpx_automation.handlers.quality_render",
191
+ "reason": "Returns MCP protocol content blocks from adapter-facing quality handlers."
192
+ },
193
+ {
194
+ "module": "hwpx_automation.runtime",
195
+ "reason": "Composes the FastMCP runtime and protocol types."
196
+ },
197
+ {
198
+ "module": "hwpx_automation.server",
199
+ "reason": "Starts the optional MCP transport."
200
+ },
201
+ {
202
+ "module": "hwpx_automation.tool_bindings",
203
+ "reason": "Binds pure ToolSpec data to FastMCP runtime handlers."
204
+ }
205
+ ]
206
+ }
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,351 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Automation quality contract (VisualComplete Phase F).
3
+
4
+ Every write funnels through the one ``python-hwpx`` SavePipeline gate and reports a
5
+ uniform ``VisualCompleteReport``. This module owns:
6
+
7
+ * :func:`resolve_policy` — turn a model-facing ``quality`` block into a
8
+ :class:`~hwpx.quality.QualityPolicy` (default = transparent, i.e. today's
9
+ open-safety-only behaviour, so the contract is invisible until a caller opts in).
10
+ * :func:`save_through_pipeline` / :func:`visual_complete_block` — run the gate and
11
+ map the report to an MCP payload (``ok`` / ``visualComplete`` / structured
12
+ ``errors`` carrying retry-able codes + ``suggestedRetry``).
13
+ * :class:`QualityGateError` — raised when an elevated policy's gate fails so the
14
+ write is **withheld** (fail-closed) and the model sees the structured error.
15
+ * the **capability handshake** (:func:`capability_state` / :func:`assert_write_capability`)
16
+ — core/automation/plugin versions + a hash that **fails closed on skew** (e.g. a
17
+ ``python-hwpx`` too old to expose the SavePipeline gate).
18
+ """
19
+ from __future__ import annotations
20
+
21
+ import hashlib
22
+ import importlib.util
23
+ import os
24
+ from importlib.metadata import PackageNotFoundError, version as _pkg_version
25
+ from pathlib import Path
26
+ from typing import Any, Mapping
27
+
28
+ from .configuration import canonical_env_name, env_value
29
+ try:
30
+ import tomllib
31
+ except ModuleNotFoundError: # Python 3.10 runtime compatibility
32
+ import tomli as tomllib
33
+
34
+ from .tool_contract import (
35
+ MIN_AUTOMATION_VERSION,
36
+ MIN_MCP_VERSION,
37
+ MIN_PYTHON_HWPX,
38
+ MIN_SKILL_VERSION,
39
+ contract_hash,
40
+ )
41
+
42
+ # FastMCP's call_tool catches a tool's exception and returns an isError result in
43
+ # a copied context, so the structured gate/skew error can't be caught at the
44
+ # dispatch boundary nor handed back via a ContextVar. A plain module global is
45
+ # shared across that boundary (and across threads): the exceptions stash
46
+ # themselves here on construction; the dispatch handler reads it back to rebuild
47
+ # the structured payload (codes + suggestedRetry). Dispatch is serial per request
48
+ # (clear-then-read brackets each call), so this is not a concurrency hazard.
49
+ _LAST_GATE_ERROR: Any = None
50
+
51
+
52
+ def take_last_gate_error() -> Any:
53
+ """Pop the most recent gate/skew error recorded since the last clear."""
54
+
55
+ global _LAST_GATE_ERROR
56
+ err = _LAST_GATE_ERROR
57
+ _LAST_GATE_ERROR = None
58
+ return err
59
+
60
+
61
+ def clear_last_gate_error() -> None:
62
+ global _LAST_GATE_ERROR
63
+ _LAST_GATE_ERROR = None
64
+
65
+
66
+ def _record_gate_error(err: Any) -> None:
67
+ global _LAST_GATE_ERROR
68
+ _LAST_GATE_ERROR = err
69
+
70
+ _QUALITY_ENV = canonical_env_name("QUALITY")
71
+ _REQUIRE_CAPABILITY_ENV = canonical_env_name("REQUIRE_CAPABILITY")
72
+
73
+
74
+ # --------------------------------------------------------------------------- #
75
+ # python-hwpx quality stack (imported lazily so this module loads even on a skew).
76
+ # --------------------------------------------------------------------------- #
77
+ def _quality_available() -> bool:
78
+ return importlib.util.find_spec("hwpx.quality") is not None
79
+
80
+
81
+ def package_version(package: str) -> str:
82
+ module_name = {"python-hwpx": "hwpx", "python-hwpx-automation": "hwpx_automation",
83
+ "hwpx-mcp-server": "hwpx_automation"}.get(package)
84
+ if module_name:
85
+ spec = importlib.util.find_spec(module_name)
86
+ origin = Path(spec.origin).resolve() if spec and spec.origin else None
87
+ if origin is not None:
88
+ for parent in origin.parents:
89
+ pyproject = parent / "pyproject.toml"
90
+ if not pyproject.is_file():
91
+ continue
92
+ try:
93
+ data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
94
+ project = data.get("project", {})
95
+ if project.get("name") == package and isinstance(project.get("version"), str):
96
+ return project["version"]
97
+ except (OSError, tomllib.TOMLDecodeError):
98
+ break
99
+ try:
100
+ return _pkg_version(package)
101
+ except PackageNotFoundError:
102
+ return "unknown"
103
+
104
+
105
+ def _version_lt(value: str, minimum: str) -> bool:
106
+ """True if *value* is an older version than *minimum* (PEP 440 aware).
107
+
108
+ Uses ``packaging.version`` so that ``"2.12"`` == ``"2.12.0"`` and a
109
+ pre-release (``"2.12.0rc1"`` / ``".dev1"``) sorts BEFORE the final release —
110
+ otherwise a healthy install (or an rc of the boundary) would falsely skew and
111
+ fail closed.
112
+ """
113
+
114
+ try:
115
+ from packaging.version import InvalidVersion, Version
116
+
117
+ try:
118
+ return Version(value) < Version(minimum)
119
+ except InvalidVersion:
120
+ pass
121
+ except Exception: # pragma: no cover - packaging always present via pip
122
+ pass
123
+ # Stdlib fallback: zero-pad to equal length so "2.12" is not < "2.12.0".
124
+ a = [int("".join(c for c in p if c.isdigit()) or 0) for p in value.split(".")]
125
+ b = [int("".join(c for c in p if c.isdigit()) or 0) for p in minimum.split(".")]
126
+ width = max(len(a), len(b))
127
+ a += [0] * (width - len(a))
128
+ b += [0] * (width - len(b))
129
+ return a < b
130
+
131
+
132
+ # --------------------------------------------------------------------------- #
133
+ # Quality policy resolution.
134
+ # --------------------------------------------------------------------------- #
135
+ _POLICY_KEY_MAP = {
136
+ "requireOpenSafety": "require_open_safety",
137
+ "requireVisualComplete": "require_visual_complete",
138
+ "requireReferenceIntegrity": "require_reference_integrity",
139
+ "renderCheck": "render_check",
140
+ "xsdMode": "xsd_mode",
141
+ "overflowPolicy": "overflow_policy",
142
+ "layoutLint": "layout_lint",
143
+ "allowExpertUnsafe": "allow_expert_unsafe",
144
+ }
145
+
146
+
147
+ def resolve_policy(quality: Mapping[str, Any] | str | None) -> Any:
148
+ """Map a model-facing ``quality`` block to a ``QualityPolicy``.
149
+
150
+ ``None`` → the ``HWPX_AUTOMATION_QUALITY`` env default (with the supported
151
+ 6.x ``HWPX_MCP_QUALITY`` fallback) → transparent. A string picks a
152
+ named policy (``transparent`` / ``strict``). A dict elevates from transparent
153
+ with camelCase overrides (``renderCheck`` / ``overflowPolicy`` / ``layoutLint`` …).
154
+ """
155
+
156
+ from hwpx.quality import QualityPolicy
157
+
158
+ if quality is None:
159
+ quality = env_value("QUALITY", "transparent") or "transparent"
160
+
161
+ if isinstance(quality, str):
162
+ mode = quality.strip().lower()
163
+ if mode in ("strict", "docx", "full"):
164
+ return QualityPolicy.strict()
165
+ return QualityPolicy.transparent()
166
+
167
+ if isinstance(quality, Mapping):
168
+ mode = str(quality.get("mode", "transparent")).lower()
169
+ base = QualityPolicy.strict() if mode in ("strict", "docx", "full") else QualityPolicy.transparent()
170
+ changes: dict[str, Any] = {}
171
+ for key, attr in _POLICY_KEY_MAP.items():
172
+ if key in quality:
173
+ changes[attr] = quality[key]
174
+ return base.with_(**changes) if changes else base
175
+
176
+ return QualityPolicy.transparent()
177
+
178
+
179
+ # --------------------------------------------------------------------------- #
180
+ # Report → MCP payload.
181
+ # --------------------------------------------------------------------------- #
182
+ def visual_complete_block(report: Any) -> dict[str, Any]:
183
+ """The model-facing VisualComplete block (codes + suggestedRetry)."""
184
+
185
+ errors = [
186
+ {
187
+ "code": err.code,
188
+ "message": err.message,
189
+ "suggestedRetry": err.suggested_retry,
190
+ }
191
+ for err in report.errors
192
+ ]
193
+ return {
194
+ "ok": bool(report.ok),
195
+ "visualComplete": bool(report.visual_complete),
196
+ "status": report.visual_complete_status,
197
+ "renderChecked": bool(report.render_checked),
198
+ "errors": errors,
199
+ "errorCodes": [err.code for err in report.errors],
200
+ "warnings": list(report.warnings),
201
+ "suggestedRetry": _aggregate_retry(report),
202
+ "form": report.form.to_dict(),
203
+ "layout": report.layout.to_dict(),
204
+ }
205
+
206
+
207
+ def _aggregate_retry(report: Any) -> dict[str, Any] | None:
208
+ for err in report.errors:
209
+ if err.suggested_retry:
210
+ return {"code": err.code, **err.suggested_retry}
211
+ if report.errors:
212
+ return {"code": report.errors[0].code}
213
+ return None
214
+
215
+
216
+ class QualityGateError(RuntimeError):
217
+ """An elevated-policy gate failed; the write was withheld (fail-closed)."""
218
+
219
+ def __init__(self, report: Any) -> None:
220
+ block = visual_complete_block(report)
221
+ self.report = report
222
+ self.block = block
223
+ self.code = (block["errorCodes"] or ["VISUAL_COMPLETE_FAILED"])[0]
224
+ message = "; ".join(e["message"] for e in block["errors"]) or "visual_complete gate failed"
225
+ _record_gate_error(self)
226
+ super().__init__(message)
227
+
228
+
229
+ def save_through_pipeline(document: Any, output_path: Any, *, quality: Any = None) -> Any:
230
+ """Save *document* through the SavePipeline; return the ``VisualCompleteReport``.
231
+
232
+ Raises :class:`QualityGateError` when the gate fails (so the caller withholds
233
+ the output — fail-closed). Open-safety serialize failures still raise the
234
+ library's ``ValueError`` as before.
235
+ """
236
+
237
+ # Accept a ready QualityPolicy, or resolve None/str/dict into one.
238
+ if quality is None or isinstance(quality, (str, Mapping)):
239
+ policy = resolve_policy(quality)
240
+ else:
241
+ policy = quality
242
+ from .office.rendering import bind_document_rendering
243
+
244
+ with bind_document_rendering(document):
245
+ report = document.save_report(output_path, quality=policy)
246
+ if not report.ok:
247
+ raise QualityGateError(report)
248
+ return report
249
+
250
+
251
+ # --------------------------------------------------------------------------- #
252
+ # Capability handshake (fail-closed on skew).
253
+ # --------------------------------------------------------------------------- #
254
+ def capability_state() -> dict[str, Any]:
255
+ """Core/automation/plugin versions + a fingerprint hash + any version skew."""
256
+
257
+ core = package_version("python-hwpx")
258
+ automation = package_version("python-hwpx-automation")
259
+ plugin = os.environ.get("HWPX_SKILL_VERSION", "unknown")
260
+ has_pipeline = _quality_available()
261
+
262
+ skew: list[str] = []
263
+ if not has_pipeline:
264
+ skew.append("python-hwpx is missing the hwpx.quality SavePipeline gate")
265
+ elif _version_lt(core, MIN_PYTHON_HWPX):
266
+ skew.append(f"python-hwpx {core} < required {MIN_PYTHON_HWPX}")
267
+ if automation == "unknown":
268
+ skew.append("python-hwpx-automation version is unresolved")
269
+ elif _version_lt(automation, MIN_AUTOMATION_VERSION):
270
+ skew.append(
271
+ f"python-hwpx-automation {automation} < required {MIN_AUTOMATION_VERSION}"
272
+ )
273
+ if plugin != "unknown" and _version_lt(plugin, MIN_SKILL_VERSION):
274
+ skew.append(f"hwpx skill {plugin} < required {MIN_SKILL_VERSION}")
275
+
276
+ fingerprint = hashlib.sha256(
277
+ "|".join(
278
+ [
279
+ "core", core,
280
+ "automation", automation,
281
+ "plugin", plugin,
282
+ "pipeline", str(has_pipeline),
283
+ "toolContract", contract_hash(),
284
+ ]
285
+ ).encode()
286
+ ).hexdigest()[:16]
287
+
288
+ return {
289
+ "versions": {
290
+ "core": core,
291
+ "automation": automation,
292
+ # 6.x compatibility alias.
293
+ "mcp": automation,
294
+ "plugin": plugin,
295
+ },
296
+ "minPythonHwpx": MIN_PYTHON_HWPX,
297
+ "minAutomationVersion": MIN_AUTOMATION_VERSION,
298
+ # 6.x compatibility alias.
299
+ "minMcpVersion": MIN_MCP_VERSION,
300
+ "minSkillVersion": MIN_SKILL_VERSION,
301
+ "savePipelineAvailable": has_pipeline,
302
+ "toolContractHash": contract_hash(),
303
+ "hash": fingerprint,
304
+ "skew": skew,
305
+ "ok": not skew,
306
+ }
307
+
308
+
309
+ def fail_closed_enabled() -> bool:
310
+ return env_value("REQUIRE_CAPABILITY", "1") != "0"
311
+
312
+
313
+ def assert_write_capability() -> None:
314
+ """Raise :class:`QualityGateError`-style failure if capability is skewed.
315
+
316
+ Fail-closed: a write must not proceed when the installed quality stack can't
317
+ honour the gate (e.g. a stale python-hwpx). Disable with
318
+ ``HWPX_AUTOMATION_REQUIRE_CAPABILITY=0`` for an expert/debug bypass. The
319
+ old ``HWPX_MCP_REQUIRE_CAPABILITY`` spelling remains a 6.x fallback.
320
+ """
321
+
322
+ if not fail_closed_enabled():
323
+ return
324
+ state = capability_state()
325
+ if not state["ok"]:
326
+ raise CapabilitySkewError(state)
327
+
328
+
329
+ class CapabilitySkewError(RuntimeError):
330
+ """The core/automation/plugin handshake detected skew; writes fail closed."""
331
+
332
+ code = "CAPABILITY_SKEW"
333
+
334
+ def __init__(self, state: Mapping[str, Any]) -> None:
335
+ self.state = dict(state)
336
+ _record_gate_error(self)
337
+ super().__init__("; ".join(state.get("skew", [])) or "capability skew detected")
338
+
339
+
340
+ __all__ = [
341
+ "MIN_PYTHON_HWPX",
342
+ "resolve_policy",
343
+ "save_through_pipeline",
344
+ "visual_complete_block",
345
+ "QualityGateError",
346
+ "CapabilitySkewError",
347
+ "capability_state",
348
+ "assert_write_capability",
349
+ "fail_closed_enabled",
350
+ "package_version",
351
+ ]