python-hwpx-automation 7.0.4__tar.gz → 7.2.0__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.
- {python_hwpx_automation-7.0.4/src/python_hwpx_automation.egg-info → python_hwpx_automation-7.2.0}/PKG-INFO +7 -7
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/README.md +5 -5
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/pyproject.toml +2 -2
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/content_edit.py +48 -3
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/read_export.py +3 -1
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/identity.json +18 -10
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/mixed_form.py +3 -3
- python_hwpx_automation-7.2.0/src/hwpx_automation/office/agent/_batch_publication.py +185 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/_batch_verification.py +10 -4
- python_hwpx_automation-7.2.0/src/hwpx_automation/office/agent/_text_scope.py +379 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/dump.py +62 -6
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/cli.py +20 -9
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/commands.py +16 -2
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/document.py +30 -2
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/__init__.py +61 -38
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/_render_hwpx_mac.applescript +47 -35
- python_hwpx_automation-7.2.0/src/hwpx_automation/office/rendering/mac_session.py +87 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/oracle.py +33 -42
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/worker.py +55 -17
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/content_layout.py +1 -1
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/memo_style.py +1 -1
- python_hwpx_automation-7.2.0/src/hwpx_automation/public-modules.json +215 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/runtime.py +28 -4
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/tool_contract.py +5 -4
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/upstream.py +14 -3
- python_hwpx_automation-7.2.0/src/hwpx_automation/utils/read_budget.py +128 -0
- python_hwpx_automation-7.2.0/src/hwpx_automation/workflow/evidence_lineage.py +131 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/render_queue.py +17 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/service.py +14 -4
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0/src/python_hwpx_automation.egg-info}/PKG-INFO +7 -7
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/python_hwpx_automation.egg-info/SOURCES.txt +5 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/python_hwpx_automation.egg-info/requires.txt +1 -1
- python_hwpx_automation-7.0.4/src/hwpx_automation/public-modules.json +0 -210
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/LICENSE +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/MANIFEST.in +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/NOTICE +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/setup.cfg +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/__init__.pyi +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/__main__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/agent_document.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/api.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/blind_eval.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/capabilities.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/compat.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/configuration.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/content.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/context.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/diff.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/document.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/formatting.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/handles.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/locations.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/locator.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/plan.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/resources.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/search.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/transactions.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/core/txn.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/document_state.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/errors.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/execution_lock.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/fastmcp_adapter.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/form_fill.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/form_output_models.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/_shared.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/agent_document.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/authoring.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/form_fill.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/layout_style.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/quality_render.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/specialized.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/tracked_changes.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/handlers/workflow.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/hwp_converter.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/hwp_support.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/hwpx_ops.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/identity.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ingest_adapters.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/markdown_plan.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/mcp_cli.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/metadata/tools_meta.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/mutation_models.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/network_policy.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/bundle.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/catalog.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/mapping.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/model.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/native.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/blueprint/replay.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/catalog.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/form_plan.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/model.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/path.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/query.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/agent/story.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/advanced_generators.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/builder/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/builder/core.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/builder/report.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/_support.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/composer.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/harvest.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/plan.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profile.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/profile.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/profile.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/design/validator.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/presets/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/presets/proposal.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/report_parser.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/style_profile.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/authoring/template_analyzer.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/charting/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/compliance/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/compliance/official_lint.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/compliance/pii.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/document_ops/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/document_ops/comparison.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/document_ops/mail_merge.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/document_ops/redline.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/evalplan/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/evalplan/runtime.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/compose.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/ir.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/measure.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/parser.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/exam/profile.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/classification.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fill_residue.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/apply.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/engine.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/measure.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/policy.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/report.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/seal.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/fit/wordbox.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/guidance.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/quality.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/split_run.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/form_fill/template_formfit.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/composition.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/data/bank.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/data/genres.json +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/gianmun.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/house_style/org_chart.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/quality/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/quality/page_guard.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/_hancom_open_rate.ps1 +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/block_splits.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/detectors.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/diff.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/fixture_corpus.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/page_qa.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/qa_contracts.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/rendering/qa_metrics.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/utilities/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/office/utilities/table_compute.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/_border_fill.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/composition.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/context.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/form_fields.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/media.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/package_validation.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/planning.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/preview_export.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/read_query.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/save_policy.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/tables.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/ops_services/transactions.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/preview_output_models.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/py.typed +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/quality.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/quality_generation.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/resources.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/runtime_services.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/server.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/storage.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/tool_bindings.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/utils/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/utils/helpers.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/visual_qa.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/__init__.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/adapters.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/dispatcher.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/models.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/policy.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/render_contracts.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/render_metrics.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/render_security.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/render_transport.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/rendering.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/state_machine.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workflow/store.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/workspace.py +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/python_hwpx_automation.egg-info/dependency_links.txt +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/python_hwpx_automation.egg-info/entry_points.txt +0 -0
- {python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/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.0
|
|
3
|
+
Version: 7.2.0
|
|
4
4
|
Summary: Task-oriented HWPX document automation for Python, with an optional MCP adapter.
|
|
5
5
|
Author: Kohkyuhyun
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
|
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
License-File: NOTICE
|
|
23
|
-
Requires-Dist: python-hwpx<7,>=6.
|
|
23
|
+
Requires-Dist: python-hwpx<7,>=6.5.0
|
|
24
24
|
Requires-Dist: pydantic<3,>=2.11
|
|
25
25
|
Requires-Dist: cryptography>=42.0
|
|
26
26
|
Requires-Dist: anyio>=4.0
|
|
@@ -74,10 +74,8 @@ Dynamic: license-file
|
|
|
74
74
|
|
|
75
75
|
<!-- release-state: release-approved -->
|
|
76
76
|
> [!NOTE]
|
|
77
|
-
>
|
|
78
|
-
>
|
|
79
|
-
> 공개 트레인: `python-hwpx 6.3.0 → python-hwpx-automation 7.0.3 → hwpx-plugin 2.0.3`.
|
|
80
|
-
> 계약은 `8c278ebd5becba08`이며 도구 표면과 최소 호환 버전은 유지합니다.
|
|
77
|
+
> 발행이 승인된 7.2.0 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.5.0 → python-hwpx-automation 7.2.0 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
|
|
78
|
+
> 공개 트레인: `python-hwpx 6.4.0 → python-hwpx-automation 7.1.0 → hwpx-plugin 2.2.0` (`ba0211fc854a0a97`).
|
|
81
79
|
> 공개 좌표는 core·automation PyPI와 plugin GitHub
|
|
82
80
|
> Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
|
|
83
81
|
> [릴리스 runbook](docs/release-runbook.md)
|
|
@@ -134,7 +132,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
134
132
|
"command": "uvx",
|
|
135
133
|
"args": [
|
|
136
134
|
"--from",
|
|
137
|
-
"python-hwpx-automation[mcp]==7.0
|
|
135
|
+
"python-hwpx-automation[mcp]==7.1.0",
|
|
138
136
|
"hwpx-automation-mcp"
|
|
139
137
|
],
|
|
140
138
|
"env": {
|
|
@@ -241,3 +239,5 @@ python scripts/run_conformance.py run \
|
|
|
241
239
|
## License · Maintainer
|
|
242
240
|
|
|
243
241
|
Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
242
|
+
|
|
243
|
+
기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를 먼저 확인하세요. 새 문서는 document-plan, 에이전트 연결은 선택 MCP와 호스트 플러그인을 사용합니다.
|
|
@@ -14,10 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
<!-- release-state: release-approved -->
|
|
16
16
|
> [!NOTE]
|
|
17
|
-
>
|
|
18
|
-
>
|
|
19
|
-
> 공개 트레인: `python-hwpx 6.3.0 → python-hwpx-automation 7.0.3 → hwpx-plugin 2.0.3`.
|
|
20
|
-
> 계약은 `8c278ebd5becba08`이며 도구 표면과 최소 호환 버전은 유지합니다.
|
|
17
|
+
> 발행이 승인된 7.2.0 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.5.0 → python-hwpx-automation 7.2.0 → hwpx-plugin 2.3.0` (`5e5c23651f92785a`).
|
|
18
|
+
> 공개 트레인: `python-hwpx 6.4.0 → python-hwpx-automation 7.1.0 → hwpx-plugin 2.2.0` (`ba0211fc854a0a97`).
|
|
21
19
|
> 공개 좌표는 core·automation PyPI와 plugin GitHub
|
|
22
20
|
> Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
|
|
23
21
|
> [릴리스 runbook](docs/release-runbook.md)
|
|
@@ -74,7 +72,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
74
72
|
"command": "uvx",
|
|
75
73
|
"args": [
|
|
76
74
|
"--from",
|
|
77
|
-
"python-hwpx-automation[mcp]==7.0
|
|
75
|
+
"python-hwpx-automation[mcp]==7.1.0",
|
|
78
76
|
"hwpx-automation-mcp"
|
|
79
77
|
],
|
|
80
78
|
"env": {
|
|
@@ -181,3 +179,5 @@ python scripts/run_conformance.py run \
|
|
|
181
179
|
## License · Maintainer
|
|
182
180
|
|
|
183
181
|
Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
182
|
+
|
|
183
|
+
기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](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.0
|
|
7
|
+
version = "7.2.0"
|
|
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" }]
|
|
@@ -31,7 +31,7 @@ dependencies = [
|
|
|
31
31
|
# breaking an already-published automation line. WP-F (engine surface 6.0):
|
|
32
32
|
# this line adapted to the new namespace surface (design §9 WP-F) — the dev0
|
|
33
33
|
# pre-release qualifier tracks core's own not-yet-tagged 6.0 identity.
|
|
34
|
-
"python-hwpx>=6.
|
|
34
|
+
"python-hwpx>=6.5.0,<7", # HWPX object model, OXML/OPC, format-native primitives
|
|
35
35
|
|
|
36
36
|
"pydantic>=2.11,<3",
|
|
37
37
|
"cryptography>=42.0",
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
from typing import Any
|
|
8
|
+
import zlib
|
|
7
9
|
|
|
8
10
|
from .. import quality as quality_contract
|
|
9
11
|
from ..core.content import (
|
|
@@ -805,9 +807,40 @@ def insert_picture(
|
|
|
805
807
|
return _with_save_verification(result, verification)
|
|
806
808
|
|
|
807
809
|
|
|
810
|
+
def _validate_workspace_image(data: bytes, image_format: str) -> None:
|
|
811
|
+
"""Check bounded file input before inserting its bytes into a package."""
|
|
812
|
+
fmt = image_format.casefold().lstrip(".")
|
|
813
|
+
if fmt == "png":
|
|
814
|
+
if not data.startswith(b"\x89PNG\r\n\x1a\n"):
|
|
815
|
+
raise ValueError("image_filename content does not match image_format")
|
|
816
|
+
offset = 8
|
|
817
|
+
chunks: list[bytes] = []
|
|
818
|
+
while offset + 12 <= len(data):
|
|
819
|
+
length = int.from_bytes(data[offset:offset + 4], "big")
|
|
820
|
+
end = offset + 12 + length
|
|
821
|
+
if end > len(data):
|
|
822
|
+
break
|
|
823
|
+
kind = data[offset + 4:offset + 8]
|
|
824
|
+
payload = data[offset + 8:offset + 8 + length]
|
|
825
|
+
crc = int.from_bytes(data[end - 4:end], "big")
|
|
826
|
+
if zlib.crc32(kind + payload) != crc:
|
|
827
|
+
break
|
|
828
|
+
chunks.append(kind)
|
|
829
|
+
offset = end
|
|
830
|
+
if kind == b"IEND":
|
|
831
|
+
if length == 0 and offset == len(data) and chunks[0] == b"IHDR" and b"IDAT" in chunks:
|
|
832
|
+
return
|
|
833
|
+
break
|
|
834
|
+
elif fmt in {"jpg", "jpeg"} and data.startswith(b"\xff\xd8\xff") and data.endswith(b"\xff\xd9"):
|
|
835
|
+
return
|
|
836
|
+
elif fmt == "gif" and data.startswith((b"GIF87a", b"GIF89a")) and data.endswith(b";"):
|
|
837
|
+
return
|
|
838
|
+
raise ValueError("image_filename content does not match image_format or is incomplete")
|
|
839
|
+
|
|
840
|
+
|
|
808
841
|
def replace_picture(
|
|
809
842
|
filename: str,
|
|
810
|
-
image_base64: str,
|
|
843
|
+
image_base64: str | None = None,
|
|
811
844
|
image_format: str = "png",
|
|
812
845
|
picture_index: int = 0,
|
|
813
846
|
binary_item_id_ref: str | None = None,
|
|
@@ -815,15 +848,27 @@ def replace_picture(
|
|
|
815
848
|
output: str | None = None,
|
|
816
849
|
dry_run: bool = False,
|
|
817
850
|
expected_revision: str = None,
|
|
851
|
+
image_filename: str | None = None,
|
|
818
852
|
) -> dict:
|
|
819
|
-
"""그림
|
|
853
|
+
"""그림 geometry를 유지하고 base64 또는 workspace 이미지 파일로 교체합니다."""
|
|
854
|
+
if (image_base64 is None) == (image_filename is None):
|
|
855
|
+
raise ValueError("provide exactly one of image_base64 or image_filename")
|
|
820
856
|
path = resolve_path(filename)
|
|
821
857
|
guard = _revision_guard(path, expected_revision)
|
|
822
858
|
if guard is not None:
|
|
823
859
|
return guard
|
|
824
860
|
target_path = resolve_path(output) if output else path
|
|
861
|
+
if image_filename is not None:
|
|
862
|
+
image_path = Path(resolve_path(image_filename))
|
|
863
|
+
with image_path.open("rb") as image_file:
|
|
864
|
+
image_data = image_file.read(20 * 1024 * 1024 + 1)
|
|
865
|
+
if len(image_data) > 20 * 1024 * 1024:
|
|
866
|
+
raise ValueError("image_filename must be at most 20 MiB")
|
|
867
|
+
_validate_workspace_image(image_data, image_format)
|
|
868
|
+
else:
|
|
869
|
+
assert image_base64 is not None
|
|
870
|
+
image_data = _decode_image_base64(image_base64)
|
|
825
871
|
doc = open_doc(path)
|
|
826
|
-
image_data = _decode_image_base64(image_base64)
|
|
827
872
|
# media.replace_picture now returns a frozen PictureReplacement (design
|
|
828
873
|
# §2.4) whose own .to_dict() uses different field names than this op's
|
|
829
874
|
# established response contract (old_binaryItemIDRef/new_binaryItemIDRef/
|
|
@@ -38,6 +38,7 @@ from ..upstream import (
|
|
|
38
38
|
open_document,
|
|
39
39
|
)
|
|
40
40
|
from ..utils.helpers import default_max_chars, resolve_path, truncate_response
|
|
41
|
+
from ..utils.read_budget import bound_document_summary
|
|
41
42
|
from ._shared import _with_document_state
|
|
42
43
|
|
|
43
44
|
_OUTPUT_MODES = {"full", "chunks"}
|
|
@@ -920,7 +921,8 @@ def get_document_map(
|
|
|
920
921
|
"hwpx_extract_json",
|
|
921
922
|
],
|
|
922
923
|
}
|
|
923
|
-
|
|
924
|
+
result = _with_document_state(result, path)
|
|
925
|
+
return bound_document_summary(result) if summary_mode else result
|
|
924
926
|
|
|
925
927
|
|
|
926
928
|
def hwpx_to_markdown(
|
{python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/identity.json
RENAMED
|
@@ -5,22 +5,30 @@
|
|
|
5
5
|
"releaseState": {
|
|
6
6
|
"status": "release-approved",
|
|
7
7
|
"candidate": {
|
|
8
|
-
"pythonHwpx": "6.
|
|
8
|
+
"pythonHwpx": "6.5.0",
|
|
9
9
|
"canonicalDistribution": "python-hwpx-automation",
|
|
10
|
-
"canonicalAutomation": "7.0
|
|
10
|
+
"canonicalAutomation": "7.2.0",
|
|
11
11
|
"compatibilityDistribution": "hwpx-mcp-server",
|
|
12
|
-
"compatibility": "7.0
|
|
13
|
-
"plugin": "2.
|
|
14
|
-
"contractHash": "
|
|
12
|
+
"compatibility": "7.2.0",
|
|
13
|
+
"plugin": "2.3.0",
|
|
14
|
+
"contractHash": "5e5c23651f92785a"
|
|
15
15
|
},
|
|
16
16
|
"currentPublic": {
|
|
17
|
-
"pythonHwpx": "6.
|
|
17
|
+
"pythonHwpx": "6.4.0",
|
|
18
18
|
"primaryDistribution": "python-hwpx-automation",
|
|
19
|
-
"primaryApplication": "7.0
|
|
20
|
-
"plugin": "2.0
|
|
21
|
-
"contractHash": "
|
|
19
|
+
"primaryApplication": "7.1.0",
|
|
20
|
+
"plugin": "2.2.0",
|
|
21
|
+
"contractHash": "ba0211fc854a0a97"
|
|
22
22
|
},
|
|
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."
|
|
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
|
+
"previousPublic": {
|
|
25
|
+
"pythonHwpx": "6.4.0",
|
|
26
|
+
"primaryDistribution": "python-hwpx-automation",
|
|
27
|
+
"primaryApplication": "7.1.0",
|
|
28
|
+
"plugin": "2.2.0",
|
|
29
|
+
"contractHash": "ba0211fc854a0a97"
|
|
30
|
+
},
|
|
31
|
+
"publicationEvidence": null
|
|
24
32
|
},
|
|
25
33
|
"releaseFloors": {
|
|
26
34
|
"description": "Frozen historical coordinates. Unlike releaseState these do not advance train by train; they pin the pre-6.0 legacy compatibility cap that every core 5 resolution must be observed against. They live here so the release path has no version literal that is not declared data.",
|
{python_hwpx_automation-7.0.4 → python_hwpx_automation-7.2.0}/src/hwpx_automation/mixed_form.py
RENAMED
|
@@ -29,7 +29,6 @@ from hwpx_automation.office.agent import (
|
|
|
29
29
|
plan_mixed_form_fill,
|
|
30
30
|
validate_mixed_form_plan,
|
|
31
31
|
)
|
|
32
|
-
from hwpx.quality import SavePipeline
|
|
33
32
|
from pydantic import (
|
|
34
33
|
BaseModel,
|
|
35
34
|
ConfigDict,
|
|
@@ -40,6 +39,7 @@ from pydantic import (
|
|
|
40
39
|
)
|
|
41
40
|
|
|
42
41
|
from .execution_lock import PUBLIC_MUTATION_LOCK
|
|
42
|
+
from .office.agent._batch_publication import GuardedSavePipeline
|
|
43
43
|
from .office.rendering import resolve_hancom_backend
|
|
44
44
|
from .storage import build_hwpx_open_safety_report
|
|
45
45
|
from .utils.helpers import resolve_path
|
|
@@ -584,7 +584,7 @@ class _FailurePreimagePreserver:
|
|
|
584
584
|
return True
|
|
585
585
|
|
|
586
586
|
|
|
587
|
-
class _WorkspaceSavePipeline(
|
|
587
|
+
class _WorkspaceSavePipeline(GuardedSavePipeline):
|
|
588
588
|
"""Run the core quality gate but publish through an identity-bound path."""
|
|
589
589
|
|
|
590
590
|
def __init__(
|
|
@@ -1652,7 +1652,7 @@ def _finalize_canonical_apply(
|
|
|
1652
1652
|
verification = copy.deepcopy(core_verification)
|
|
1653
1653
|
response_ok = bool(response.get("ok")) and bool(source_report["ok"])
|
|
1654
1654
|
missing_fresh_publication = bool(
|
|
1655
|
-
response_ok
|
|
1655
|
+
(response_ok or core_verification.get("publication", {}).get("ownershipMissing"))
|
|
1656
1656
|
and not dry_run
|
|
1657
1657
|
and not replayed
|
|
1658
1658
|
and publication is None
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Revision-bound publication for the existing agent command executor.
|
|
3
|
+
|
|
4
|
+
Quality remains in core SavePipeline; identity/CAS and rollback reuse the
|
|
5
|
+
application workspace writer. Explicit Python paths do not acquire a cwd policy.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from hwpx.quality import SavePipeline
|
|
14
|
+
|
|
15
|
+
from ...workspace import WorkspaceOutputGuard, WorkspaceResolver
|
|
16
|
+
from .model import AgentContractError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class GuardedSavePipeline(SavePipeline):
|
|
20
|
+
"""Application publisher carrying the identity of its own publication.
|
|
21
|
+
|
|
22
|
+
Existing domain publishers subclass this seam so the batch can retain their
|
|
23
|
+
guarded publication and recovery receipts after running their quality gate.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
publication: WorkspaceOutputGuard | None = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class _BatchSavePipeline(GuardedSavePipeline):
|
|
30
|
+
def __init__(self, binding: BatchPublication) -> None:
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.binding = binding
|
|
33
|
+
self.publication = None
|
|
34
|
+
|
|
35
|
+
def _publish(self, data: bytes, output_path: Any, output_stream: Any) -> str:
|
|
36
|
+
if (
|
|
37
|
+
output_stream is not None
|
|
38
|
+
or Path(output_path).resolve() != self.binding.output
|
|
39
|
+
):
|
|
40
|
+
raise AgentContractError(
|
|
41
|
+
"verification_failed", "unexpected batch publication destination"
|
|
42
|
+
)
|
|
43
|
+
guard = self.binding.workspace.materialize_output_guard(
|
|
44
|
+
self.binding.output_guard
|
|
45
|
+
)
|
|
46
|
+
try:
|
|
47
|
+
self.publication = self.binding.workspace.atomic_publish_bytes(guard, data)
|
|
48
|
+
except BaseException:
|
|
49
|
+
self.binding.workspace.cleanup_owned_parent_directories(guard)
|
|
50
|
+
raise
|
|
51
|
+
return str(self.publication.path)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _existing_parent(path: Path) -> Path:
|
|
55
|
+
parent = path.parent
|
|
56
|
+
while not parent.exists() and parent != parent.parent:
|
|
57
|
+
parent = parent.parent
|
|
58
|
+
return parent
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class BatchPublication:
|
|
62
|
+
"""One disposable request's input snapshot and destination precondition."""
|
|
63
|
+
|
|
64
|
+
def __init__(self, source: Path, output: Path) -> None:
|
|
65
|
+
self.source_argument = source.absolute()
|
|
66
|
+
self.source = source.resolve()
|
|
67
|
+
self.output = output.resolve()
|
|
68
|
+
self.workspace = WorkspaceResolver.from_roots(
|
|
69
|
+
[self.source.parent, _existing_parent(self.output)],
|
|
70
|
+
source="agent-explicit-paths",
|
|
71
|
+
)
|
|
72
|
+
self.source_guard = self.workspace.capture_output(self.source)
|
|
73
|
+
self.input_data = self.workspace.read_guarded_bytes(self.source_guard)
|
|
74
|
+
self.output_guard = self.workspace.capture_output_precondition(self.output)
|
|
75
|
+
self.output_data = (
|
|
76
|
+
self.workspace.read_guarded_bytes(self.output_guard)
|
|
77
|
+
if isinstance(self.output_guard, WorkspaceOutputGuard)
|
|
78
|
+
and self.output_guard.target_existed
|
|
79
|
+
else None
|
|
80
|
+
)
|
|
81
|
+
self.publisher: GuardedSavePipeline | None = None
|
|
82
|
+
self.publication_attempted = False
|
|
83
|
+
|
|
84
|
+
def assert_current_source(self) -> None:
|
|
85
|
+
try:
|
|
86
|
+
if self.source_argument.resolve() != self.source:
|
|
87
|
+
raise OSError("source path was rebound")
|
|
88
|
+
current = self.workspace.read_guarded_bytes(self.source_guard)
|
|
89
|
+
if current != self.input_data:
|
|
90
|
+
raise OSError("source bytes changed")
|
|
91
|
+
except OSError as exc:
|
|
92
|
+
raise AgentContractError(
|
|
93
|
+
"stale_revision",
|
|
94
|
+
"input changed during editing; read its current revision before retrying",
|
|
95
|
+
target="batch.input.filename",
|
|
96
|
+
) from exc
|
|
97
|
+
|
|
98
|
+
def publish(
|
|
99
|
+
self, data: bytes, pipeline: SavePipeline, verification: dict[str, Any]
|
|
100
|
+
) -> str:
|
|
101
|
+
self.assert_current_source()
|
|
102
|
+
if not isinstance(pipeline, GuardedSavePipeline) and type(pipeline)._publish is not SavePipeline._publish:
|
|
103
|
+
raise AgentContractError(
|
|
104
|
+
"unsupported_operation",
|
|
105
|
+
"custom publishers must provide an identity-bound publication receipt",
|
|
106
|
+
target="savePipeline",
|
|
107
|
+
)
|
|
108
|
+
self.publisher = (
|
|
109
|
+
pipeline
|
|
110
|
+
if isinstance(pipeline, GuardedSavePipeline)
|
|
111
|
+
else _BatchSavePipeline(self)
|
|
112
|
+
)
|
|
113
|
+
self.publisher.publication = None
|
|
114
|
+
self.publication_attempted = True
|
|
115
|
+
written = self.publisher._publish(data, self.output, None)
|
|
116
|
+
publication = self.publisher.publication
|
|
117
|
+
if publication is None:
|
|
118
|
+
verification["publication"] = {
|
|
119
|
+
"ok": False,
|
|
120
|
+
"ownershipMissing": True,
|
|
121
|
+
"rolledBack": False,
|
|
122
|
+
}
|
|
123
|
+
raise AgentContractError(
|
|
124
|
+
"verification_failed",
|
|
125
|
+
"publisher did not provide an owned output receipt",
|
|
126
|
+
)
|
|
127
|
+
if self.source != self.output:
|
|
128
|
+
self.assert_current_source()
|
|
129
|
+
if self.workspace.read_guarded_bytes(publication) != data:
|
|
130
|
+
raise AgentContractError(
|
|
131
|
+
"verification_failed",
|
|
132
|
+
"published bytes differ from the verified candidate",
|
|
133
|
+
)
|
|
134
|
+
verification["publication"] = {
|
|
135
|
+
"ok": True,
|
|
136
|
+
"inputRechecked": True,
|
|
137
|
+
"outputPreconditionChecked": True,
|
|
138
|
+
}
|
|
139
|
+
return str(written)
|
|
140
|
+
|
|
141
|
+
def rollback(self, verification: dict[str, Any]) -> None:
|
|
142
|
+
publication = self.publisher.publication if self.publisher is not None else None
|
|
143
|
+
if publication is None:
|
|
144
|
+
unchanged = not self.publication_attempted
|
|
145
|
+
if not unchanged:
|
|
146
|
+
try:
|
|
147
|
+
unchanged = (
|
|
148
|
+
self.workspace.capture_output_precondition(self.output)
|
|
149
|
+
== self.output_guard
|
|
150
|
+
)
|
|
151
|
+
except OSError:
|
|
152
|
+
unchanged = False
|
|
153
|
+
verification.setdefault(
|
|
154
|
+
"publication",
|
|
155
|
+
{
|
|
156
|
+
"ok": False,
|
|
157
|
+
"candidatePublished": None if self.publication_attempted else False,
|
|
158
|
+
"rolledBack": unchanged,
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
return
|
|
162
|
+
restored = False
|
|
163
|
+
try:
|
|
164
|
+
if self.output_data is None:
|
|
165
|
+
self.workspace.remove_output(publication)
|
|
166
|
+
restored = self.workspace.cleanup_owned_parent_directories(publication)
|
|
167
|
+
else:
|
|
168
|
+
mode = (
|
|
169
|
+
self.output_guard.target_mode
|
|
170
|
+
if isinstance(self.output_guard, WorkspaceOutputGuard)
|
|
171
|
+
else None
|
|
172
|
+
)
|
|
173
|
+
self.workspace.atomic_publish_bytes(
|
|
174
|
+
publication, self.output_data, mode=mode
|
|
175
|
+
)
|
|
176
|
+
restored = True
|
|
177
|
+
except (OSError, RuntimeError):
|
|
178
|
+
# The publication capability never authorizes replacing another
|
|
179
|
+
# writer's newer file. Do not claim that this request rolled it back.
|
|
180
|
+
pass
|
|
181
|
+
verification["publication"] = {
|
|
182
|
+
"ok": False,
|
|
183
|
+
"candidatePublished": True,
|
|
184
|
+
"rolledBack": restored,
|
|
185
|
+
}
|
|
@@ -22,6 +22,7 @@ from hwpx.mutation_report import member_diff_bytes
|
|
|
22
22
|
from hwpx.quality import QualityPolicy, SavePipeline
|
|
23
23
|
from hwpx.tools.package_validator import validate_editor_open_safety
|
|
24
24
|
|
|
25
|
+
from ._batch_publication import BatchPublication
|
|
25
26
|
from .document import HwpxAgentDocument
|
|
26
27
|
from .model import AgentBatchResult, AgentContractError, AgentError
|
|
27
28
|
|
|
@@ -82,7 +83,7 @@ def _failure_result(
|
|
|
82
83
|
output_filename = str(output.get("filename") or "")
|
|
83
84
|
return AgentBatchResult(
|
|
84
85
|
ok=False,
|
|
85
|
-
rolled_back=True,
|
|
86
|
+
rolled_back=bool((verification or {}).get("publication", {}).get("rolledBack", True)),
|
|
86
87
|
dry_run=bool(raw.get("dryRun", False)),
|
|
87
88
|
input_revision=input_revision,
|
|
88
89
|
document_revision=input_revision,
|
|
@@ -291,7 +292,7 @@ def _apply_commands_build_candidate_report(
|
|
|
291
292
|
"package": safety_dict["validatePackage"],
|
|
292
293
|
"reopen": safety_dict["reopen"],
|
|
293
294
|
"openSafety": safety_dict,
|
|
294
|
-
"semanticDiff": {"ok":
|
|
295
|
+
"semanticDiff": {"ok": None, "changeCount": len(semantic_changes), "basis": "declared-command-log"},
|
|
295
296
|
"bytePreservation": byte_report,
|
|
296
297
|
}
|
|
297
298
|
)
|
|
@@ -343,6 +344,7 @@ def _apply_commands_run_save_pipeline(
|
|
|
343
344
|
requirements: set[str],
|
|
344
345
|
save_pipeline: SavePipeline | None,
|
|
345
346
|
verification: dict[str, Any],
|
|
347
|
+
publication: BatchPublication,
|
|
346
348
|
) -> Any:
|
|
347
349
|
pipeline = save_pipeline or SavePipeline()
|
|
348
350
|
quality_policy = _quality_policy(normalized["quality"])
|
|
@@ -356,11 +358,11 @@ def _apply_commands_run_save_pipeline(
|
|
|
356
358
|
)
|
|
357
359
|
quality_report = pipeline.run(
|
|
358
360
|
candidate_data,
|
|
359
|
-
output_path=None
|
|
361
|
+
output_path=None,
|
|
360
362
|
quality=quality_policy,
|
|
361
363
|
before=input_path,
|
|
362
364
|
reference_document=document,
|
|
363
|
-
publish="never"
|
|
365
|
+
publish="never",
|
|
364
366
|
source_label="agent.apply_document_commands",
|
|
365
367
|
)
|
|
366
368
|
verification["savePipeline"] = quality_report.to_dict()
|
|
@@ -380,4 +382,8 @@ def _apply_commands_run_save_pipeline(
|
|
|
380
382
|
raise AgentContractError(
|
|
381
383
|
"verification_failed", "SavePipeline rejected the candidate", target="savePipeline"
|
|
382
384
|
)
|
|
385
|
+
publication.assert_current_source()
|
|
386
|
+
if not normalized["dryRun"]:
|
|
387
|
+
quality_report.output_path = publication.publish(candidate_data, pipeline, verification)
|
|
388
|
+
verification["savePipeline"] = quality_report.to_dict()
|
|
383
389
|
return quality_report
|