asecli 0.8.4__tar.gz → 0.8.6__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.
- {asecli-0.8.4 → asecli-0.8.6}/PKG-INFO +27 -10
- {asecli-0.8.4 → asecli-0.8.6}/README.md +26 -9
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/change-register.md +1 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/timeline.md +3 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/traceability.csv +1 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/01-architecture/module-map.md +7 -3
- {asecli-0.8.4 → asecli-0.8.6}/docs/01-architecture/project-architecture-and-requirements.md +4 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/03-quality/regression-catalog.md +1 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/04-delivery/project-plan-task-charter.md +2 -0
- {asecli-0.8.4 → asecli-0.8.6}/pyproject.toml +1 -1
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/SKILL.md +3 -1
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/__init__.py +1 -1
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/export_sg_command.py +14 -5
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/decoder.py +3 -3
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/evidence.py +9 -1
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/reconciliation.py +34 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/report_semantics.py +2 -2
- asecli-0.8.6/src/asecli/sg_export/surface_precision.py +56 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/surface_semantics.py +8 -7
- asecli-0.8.6/tests/test_export_fidelity.py +45 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_export_precision_diagnostics.py +59 -29
- asecli-0.8.6/tests/test_export_property_visibility.py +60 -0
- asecli-0.8.6/tests/test_smoke.py +4 -0
- {asecli-0.8.4 → asecli-0.8.6}/uv.lock +1 -1
- asecli-0.8.4/src/asecli/sg_export/surface_precision.py +0 -66
- asecli-0.8.4/tests/test_export_property_visibility.py +0 -26
- asecli-0.8.4/tests/test_smoke.py +0 -4
- {asecli-0.8.4 → asecli-0.8.6}/.github/workflows/ci.yml +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/.github/workflows/publish.yml +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/.gitignore +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/.project-architect.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/AGENTS.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/LICENSE +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/SECURITY.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/audit-supplement.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/delivery-protocol.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/project-charter.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/00-governance/supply-chain-policy.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/01-architecture/assumption-experiments.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/01-architecture/technical-route.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/03-quality/bug-register.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/03-quality/test-strategy.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/04-delivery/roadmap.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-014104-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-014104-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-145343-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-145343-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-193521-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-193521-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-203438-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-01-203438-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-02-121155-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-02-121155-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-02-175509-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-02-175509-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-04-122304-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-04-122304-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-142617-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-142617-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-160945-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-160945-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-213523-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-05-213523-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-10-193631-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-10-193631-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-123640-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-123640-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-124947-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-124947-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-132814-audit-report.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/adversarial-audits/2026-09-14-132814-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/first-principles/2026-08-31-231401-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/first-principles/2026-09-01-190656-optimization-plan.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/docs/proposals/2026-09-07-shadergraph-to-ase-requirements.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/scripts/install.ps1 +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/scripts/install.sh +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/references/conversion-publication-receipt.v1.schema.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/references/conversion-workflow.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/references/layout-standard.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/references/master-output-settings-standard.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/skills/asecli/references/material-property-standard.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_editor_port_contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_editor_primitives.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_editor_spec_grammar.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_editor_spec_io.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_editor_spec_validation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_gui_handoff_store.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_gui_project.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_gui_resource_store.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/_gui_resource_upgrade.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/editor_create.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/editor_spec.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/graph_geometry.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/graph_geometry_parser.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/graph_inspect.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_handoff.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_presentation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_provider_detection.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_runtime_probe.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_support.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/gui_support_resource.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/mcp_client.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/recompile.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/render_settings.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resource_text.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.authoring.part00.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.authoring.part01.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.authoring.store.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.condition.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.hydration.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.part00.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.part01.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.reconciliation.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/asecli_material_gui.transaction.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/editor_create.part00.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/editor_create.part01.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/editor_create.part02.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/editor_create.part03.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/editor_create.part04.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/resources/wire_route.transaction.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/bridge/wire_route.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/checks/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/checks/checksum.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/checks/local_vars.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/checks/usage.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/checks/validate.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/commands.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/commentary_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/contract_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/conversion_output.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/create_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/custom_gui_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/graph_review_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/gui_provider.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/gui_support_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/io.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/layout_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/main.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/migrate_package_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/recompile_metadata.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/skill_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/cli/usage_command.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/contracts/editor-graph-spec.v3.schema.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/contracts/sgcli.native.v3.schema.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/contracts.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/comment_bounds.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/comment_layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/comment_metrics.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/comment_purpose.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/commentary.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/compiled_metadata.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/compiled_properties.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/custom_gui.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/custom_gui_versions.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/fishbone_placement.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/fishbone_topology.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/graph_ops.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/graph_review.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/island_layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/layout_audit.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/layout_audit_geometry.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/layout_audit_repeated.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/layout_graph.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/local_vars.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/material_gui_condition.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/material_gui_protocol.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/material_gui_spec.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/meticulous_layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/model.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/property_presentation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/reuse_plan.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/wire_geometry.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/core/wire_router.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/export_sg.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/schema/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/schema/data/observed.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/schema/data/schemas.json +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/schema_validation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/alpha_modulate.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/binding.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/conversion_report.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/custom_expression.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/model.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/nodes.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/pass_blend.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/report_presentation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/sources.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/src/asecli/sg_export/surface_matching.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/TEST.md +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/__init__.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/conftest.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/editor_create_v3_fixture.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/fixtures/HLIT.shader +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/fixtures/asecli_material_gui_v0_2_0.cs.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/fixtures/step-antialiasing.function.txt +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_adversarial_hardening.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_audit_fixes.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_bridge_contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_bridge_recompile.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_build_reproducibility.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_cli_contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_commentary.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_contract_schema.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_conversion_report_semantics.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_core_contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_create.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_create_constant_presentation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_cross_cli_workflow.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_custom_gui.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_custom_gui_cli.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_create_bridge.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_create_cli.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_create_e2e.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_create_spec.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_create_spec_v3.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_editor_render_settings.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_export_sg.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_governance.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_graph_review.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_graph_safety.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_gui_handoff.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_gui_native_extension.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_gui_support.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_gui_support_cli_contract.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_gui_upgrade.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_install_scripts.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_island_layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_layout.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_layout_governance.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_layout_local_var_policy.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_material_gui_e2e.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_mcp_security.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_migrate_package.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_mutate.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_pass_blend.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_perf.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_property_presentation.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_roundtrip.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_schema_add.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_schema_samples.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_sg_export_sources.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_skill_install.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_supply_chain.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_surface_semantics.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_surface_semantics_integration.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_usage_audit.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tests/test_wire_route_bridge.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/build_schema.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/check_ci_governance.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/check_document_governance.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/check_packed_executor_loc.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/check_regression_catalog.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/check_release_candidate.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/compare_build_artifacts.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/generate_sbom.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/independent_wheel_smoke.py +0 -0
- {asecli-0.8.4 → asecli-0.8.6}/tools/supply_chain_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: asecli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.6
|
|
4
4
|
Summary: Agent-native CLI for reading, modifying, validating and compiling Amplify Shader Editor assets
|
|
5
5
|
Project-URL: Homepage, https://github.com/seeseeczl/ASECLI
|
|
6
6
|
Project-URL: Repository, https://github.com/seeseeczl/ASECLI
|
|
@@ -28,9 +28,9 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
|
|
29
29
|
AseCLI 是面向 AI Agent 的本地 CLI:离线读取、编辑和校验 ASE 节点图;通过运行中的 Unity/团结引擎与 MCP,让真实 ASE 创建节点、提供精排几何并重新生成 HLSL。Skill 提供跨 Agent 的操作规则,CLI 提供可验证的执行结果。
|
|
30
30
|
|
|
31
|
-
当前正式版:**[0.8.
|
|
31
|
+
当前正式版:**[0.8.6](https://github.com/seeseeczl/ASECLI/releases/tag/v0.8.6)** · [PyPI](https://pypi.org/project/asecli/0.8.6/) · [Agent 操作手册](skills/asecli/SKILL.md) · [SG 转换后整理流程](skills/asecli/references/conversion-workflow.md)
|
|
32
32
|
|
|
33
|
-
ASECLI 接收 SGCLI 生成的裸 `EditorGraphSpec v3`,并可把受支持的 ASE Shader 直接导出为 SGCLI 的裸 `sgcli.native.v3`。两个方向都只有“生产者 spec 原文件→消费者 `--spec
|
|
33
|
+
ASECLI 接收 SGCLI 生成的裸 `EditorGraphSpec v3`,并可把受支持的 ASE Shader 直接导出为 SGCLI 的裸 `sgcli.native.v3`。两个方向都只有“生产者 spec 原文件→消费者 `--spec`”;spec 是唯一图规格;独立 report 与发布 receipt 通过各自参数提供转换认证证据,创建成功也不代表转换效果等价。
|
|
34
34
|
|
|
35
35
|
```
|
|
36
36
|
你:提需求("给这个 shader 加个可调描边")
|
|
@@ -132,7 +132,7 @@ curl -fsSL https://raw.githubusercontent.com/seeseeczl/ASECLI/main/scripts/insta
|
|
|
132
132
|
uv tool uninstall asecli
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
当前正式版本为 `0.8.
|
|
135
|
+
当前正式版本为 `0.8.6`(补齐 ASE→SG 三文件交接、时间后缀与验收边界说明;运行行为沿用 0.8.5),可从 [PyPI](https://pypi.org/project/asecli/0.8.6/) 或 [GitHub Release](https://github.com/seeseeczl/ASECLI/releases/tag/v0.8.6) 安装。历史版本见 [GitHub Releases](https://github.com/seeseeczl/ASECLI/releases),`v0.8.5` 保留为回滚点。
|
|
136
136
|
|
|
137
137
|
已知限制:真实 MCP 下,属性+纹理 v2 和 Reciprocal 降级 v2 的 create、manifest、validate、独立 recompile 已通过;SGCLI SphereMask v3 spec 在重载时仍可能返回 `node missing after reload: Radius` 并回滚。本次不承诺该 recipe 端到端可用,也不改变 SGCLI v2 默认值契约。
|
|
138
138
|
|
|
@@ -162,7 +162,7 @@ asecli --help
|
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
164
|
shasum -a 256 -c SHA256SUMS
|
|
165
|
-
uv tool install /path/to/asecli-0.8.
|
|
165
|
+
uv tool install /path/to/asecli-0.8.6-py3-none-any.whl
|
|
166
166
|
asecli --help
|
|
167
167
|
```
|
|
168
168
|
|
|
@@ -202,11 +202,28 @@ asecli recompile Assets/ConvertedNew.shader --mcp-url http://127.0.0.1:9080/mcp
|
|
|
202
202
|
```bash
|
|
203
203
|
asecli export-sg Assets/ConvertedNew.shader --out-dir ./out
|
|
204
204
|
sgcli sg create Assets/ConvertedNew.shadergraph \
|
|
205
|
-
--spec ./out/ConvertedNew.asecli-to-sgcli.spec.json
|
|
205
|
+
--spec ./out/ConvertedNew.asecli-to-sgcli.spec.json \
|
|
206
|
+
--conversion-report ./out/ConvertedNew.asecli-to-sgcli.report.json \
|
|
207
|
+
--publication-receipt ./out/ConvertedNew.asecli-to-sgcli.receipt.json \
|
|
208
|
+
--write
|
|
206
209
|
```
|
|
207
210
|
|
|
208
211
|
`export-sg` 自动从源 Shader 向上识别 Unity/Tuanjie 工程;跨工程资源解析时显式传 `--target-project`。它强制生成 `<stem>.asecli-to-sgcli.spec.json`、`.report.json` 与 `.receipt.json`,同名即失败;receipt 只证明 spec/report 两份文件的提交状态与 SHA,不是中间交接包。命令不调用 SGCLI,也不生成 ASE 自有中间 JSON。未知节点、Master/Pass、外部属性或纹理 Importer 语义时只写规范报告,不写半成品 spec。反方向 `.asecli-to-sgcli.spec.json` 不能交给 ASECLI `create --spec`。
|
|
209
212
|
|
|
213
|
+
需要保存在源文件同目录并添加时间后缀时:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
asecli export-sg /path/to/Shader.shader \
|
|
217
|
+
--out-dir /path/to \
|
|
218
|
+
--output-suffix "_$(date +%Y%m%d_%H%M%S)"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
三份文件共用同一后缀,例如 `Shader_20260914_163000.asecli-to-sgcli.spec.json`。`--name` 只修改图名称,不能用于文件命名。将实际生成的三份路径原样传给 SGCLI;不要合并、解包或改写 JSON。
|
|
222
|
+
|
|
223
|
+
导出检查算法连接或已识别的数学等价映射、变量名、属性类型、默认值、范围、资源和 Shader 设置。已匹配的 AlphaModulate 可折叠到目标管线,输出路径保持一次调制;局部精度差异在 CLI 的 `precision_warnings` 和报告的检查证据中说明,不把整个图改成 Half,也不因缺少浮点逐位证明而阻断。错误连接、混合变化及无法映射的运行时属性仍会阻断。
|
|
224
|
+
|
|
225
|
+
验收分三层:ASECLI 导出通过;SGCLI 契约/转换认证及真实创建通过;最终编译、画布与效果验收。前一层不代表后一层。最终视觉不是生成 JSON 的前置条件,未运行证据保持 `not_run`。消费者若返回 `SEM-BLEND-002` 等认证错误,应在 SGCLI 侧核对具体规则,不修改 JSON 或省略证据绕过认证。
|
|
226
|
+
|
|
210
227
|
ASECLI 随 wheel 发布自己的 EditorGraphSpec v3 Schema,以及源自 SGCLI `0.3.5` 的固定 `sgcli.native.v3` JSON 快照。快照 SHA-256 标识本包完整性与精确协议修订,不依赖对方当前分支或安装版本。构建、测试、发布与安装只使用 ASECLI,不拉取或执行 SGCLI 源码,不要求同步发布。`MultiplySourceAlpha` 等扩展仍要求实际消费者和目标 URP 支持,导出成功不代表旧消费者兼容。跨产品端到端验收是独立黑盒流程,不是本仓发布前置;本仓任务不自动跨仓修改。
|
|
211
228
|
|
|
212
229
|
可用 `asecli contract editor-graph --version 3 --spec FILE` 在不连接 Editor 时执行权威 Schema/loader 并返回原文件 SHA。报告分开记录来源快照、发布前复核、生产者 Schema 与真实消费者读取状态。旧 `{graph,report}` wrapper 只允许按已登记形状显式迁移,且内层必须已经是 `sgcli.native.v3`;无版本 discriminator 的旧输入只报告 `legacy_format`,不得伪称已识别版本化 Schema:
|
|
@@ -268,7 +285,7 @@ asecli recompile Assets/Example.shader
|
|
|
268
285
|
| `validate <file>` | 检查悬空连线、重复 ID、输入多来源、Local Var 一致性和 CHKSM。 | 只读;有 error 时返回退出码 2。 |
|
|
269
286
|
| `graph-review <file> [--baseline FILE] [--reuse-policy consumer-groups\\|fanout]` | 保守核对计算基线并列出复用计划。 | 只读;基线不一致返回 `SEMANTIC_MISMATCH` / 2,不自动创建 Local Var。 |
|
|
270
287
|
| `graph-audit <file>` | 从 Master 反向分析未参与输出的节点,区分 `unused_candidates` 与外部消费者。 | 只读;Property 的源码/HLSL/GUI 引用不会被误报为可删。 |
|
|
271
|
-
| `export-sg <file> --out-dir DIR [--target-project PROJECT]` | 直接输出裸 `sgcli.native.v3`、独立转换报告和发布回执。 | spec
|
|
288
|
+
| `export-sg <file> --out-dir DIR [--target-project PROJECT] [--output-suffix SUFFIX]` | 直接输出裸 `sgcli.native.v3`、独立转换报告和发布回执。 | spec 是唯一图规格;report/receipt 分别作为转换认证证据;receipt 证明 spec/report 提交状态;不调用 SGCLI;同名失败;转换失败只写 report。 |
|
|
272
289
|
| `contract editor-graph --version 3 [--spec FILE]` | 输出 wheel 内权威 EditorGraphSpec v3 JSON Schema;可离线校验并回执输入 SHA。 | 只读;loader 仍执行端口、中文属性和模板等更强语义校验。 |
|
|
273
290
|
| `migrate-package <file> --out-dir DIR --extract-sg-spec` | 显式提取登记的旧 `{graph,report}` wrapper。 | 只接受内层 `sgcli.native.v3`;未知/v2 wrapper 只留失败报告,不进入正常消费者。 |
|
|
274
291
|
| `set-field <file> --node N --field I --value V [--write]` | 修改一个已知节点的绝对序列化字段。 | 默认预演;`--write` 后写入。不要用它猜写 Master 或未知版本尾部。 |
|
|
@@ -340,9 +357,9 @@ asecli recompile Assets/Example.shader
|
|
|
340
357
|
除显式 `--help` 保留人类可读文本外,stdout 恒为单行严格 JSON,agent 可直接解析。`--version` 也返回 JSON:
|
|
341
358
|
|
|
342
359
|
```json
|
|
343
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
344
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
345
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
360
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"parse","ok":true,"data":{"node_count":7}}
|
|
361
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"parse","ok":false,"error":{"code":"NOT_FOUND","message":"..."}}
|
|
362
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"version","ok":true,"data":{"version":"0.8.6"}}
|
|
346
363
|
```
|
|
347
364
|
|
|
348
365
|
常见错误码:`PARSE_ERROR`、`NOT_FOUND`、`USAGE_ERROR`、`SCHEMA_UNAVAILABLE`、`SCHEMA_VERSION_MISMATCH`、`VALIDATION_ERROR`、`PROPERTY_PRESENTATION_ERROR`、`LAYOUT_ERROR`、`CHECKSUM_FORMAT_ERROR`、`GUI_SUPPORT_ERROR`、`CUSTOM_GUI_ERROR`、`COMMENT_GROUP_ERROR`、`GRAPH_REVIEW_ERROR`、`SEMANTIC_MISMATCH`、`SG_EXPORT_BLOCKED`、`EXTERNAL_REFERENCE`、`SKILL_INSTALL_CONFLICT`、`SKILL_INSTALL_ERROR`、`WRITE_CONFLICT`、`WRITE_PARTIAL`、`UNSAFE_PATH`、`WRITE_ERROR`、`BRIDGE_ERROR`、`INTERNAL`。
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
AseCLI 是面向 AI Agent 的本地 CLI:离线读取、编辑和校验 ASE 节点图;通过运行中的 Unity/团结引擎与 MCP,让真实 ASE 创建节点、提供精排几何并重新生成 HLSL。Skill 提供跨 Agent 的操作规则,CLI 提供可验证的执行结果。
|
|
6
6
|
|
|
7
|
-
当前正式版:**[0.8.
|
|
7
|
+
当前正式版:**[0.8.6](https://github.com/seeseeczl/ASECLI/releases/tag/v0.8.6)** · [PyPI](https://pypi.org/project/asecli/0.8.6/) · [Agent 操作手册](skills/asecli/SKILL.md) · [SG 转换后整理流程](skills/asecli/references/conversion-workflow.md)
|
|
8
8
|
|
|
9
|
-
ASECLI 接收 SGCLI 生成的裸 `EditorGraphSpec v3`,并可把受支持的 ASE Shader 直接导出为 SGCLI 的裸 `sgcli.native.v3`。两个方向都只有“生产者 spec 原文件→消费者 `--spec
|
|
9
|
+
ASECLI 接收 SGCLI 生成的裸 `EditorGraphSpec v3`,并可把受支持的 ASE Shader 直接导出为 SGCLI 的裸 `sgcli.native.v3`。两个方向都只有“生产者 spec 原文件→消费者 `--spec`”;spec 是唯一图规格;独立 report 与发布 receipt 通过各自参数提供转换认证证据,创建成功也不代表转换效果等价。
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
你:提需求("给这个 shader 加个可调描边")
|
|
@@ -108,7 +108,7 @@ curl -fsSL https://raw.githubusercontent.com/seeseeczl/ASECLI/main/scripts/insta
|
|
|
108
108
|
uv tool uninstall asecli
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
当前正式版本为 `0.8.
|
|
111
|
+
当前正式版本为 `0.8.6`(补齐 ASE→SG 三文件交接、时间后缀与验收边界说明;运行行为沿用 0.8.5),可从 [PyPI](https://pypi.org/project/asecli/0.8.6/) 或 [GitHub Release](https://github.com/seeseeczl/ASECLI/releases/tag/v0.8.6) 安装。历史版本见 [GitHub Releases](https://github.com/seeseeczl/ASECLI/releases),`v0.8.5` 保留为回滚点。
|
|
112
112
|
|
|
113
113
|
已知限制:真实 MCP 下,属性+纹理 v2 和 Reciprocal 降级 v2 的 create、manifest、validate、独立 recompile 已通过;SGCLI SphereMask v3 spec 在重载时仍可能返回 `node missing after reload: Radius` 并回滚。本次不承诺该 recipe 端到端可用,也不改变 SGCLI v2 默认值契约。
|
|
114
114
|
|
|
@@ -138,7 +138,7 @@ asecli --help
|
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
shasum -a 256 -c SHA256SUMS
|
|
141
|
-
uv tool install /path/to/asecli-0.8.
|
|
141
|
+
uv tool install /path/to/asecli-0.8.6-py3-none-any.whl
|
|
142
142
|
asecli --help
|
|
143
143
|
```
|
|
144
144
|
|
|
@@ -178,11 +178,28 @@ asecli recompile Assets/ConvertedNew.shader --mcp-url http://127.0.0.1:9080/mcp
|
|
|
178
178
|
```bash
|
|
179
179
|
asecli export-sg Assets/ConvertedNew.shader --out-dir ./out
|
|
180
180
|
sgcli sg create Assets/ConvertedNew.shadergraph \
|
|
181
|
-
--spec ./out/ConvertedNew.asecli-to-sgcli.spec.json
|
|
181
|
+
--spec ./out/ConvertedNew.asecli-to-sgcli.spec.json \
|
|
182
|
+
--conversion-report ./out/ConvertedNew.asecli-to-sgcli.report.json \
|
|
183
|
+
--publication-receipt ./out/ConvertedNew.asecli-to-sgcli.receipt.json \
|
|
184
|
+
--write
|
|
182
185
|
```
|
|
183
186
|
|
|
184
187
|
`export-sg` 自动从源 Shader 向上识别 Unity/Tuanjie 工程;跨工程资源解析时显式传 `--target-project`。它强制生成 `<stem>.asecli-to-sgcli.spec.json`、`.report.json` 与 `.receipt.json`,同名即失败;receipt 只证明 spec/report 两份文件的提交状态与 SHA,不是中间交接包。命令不调用 SGCLI,也不生成 ASE 自有中间 JSON。未知节点、Master/Pass、外部属性或纹理 Importer 语义时只写规范报告,不写半成品 spec。反方向 `.asecli-to-sgcli.spec.json` 不能交给 ASECLI `create --spec`。
|
|
185
188
|
|
|
189
|
+
需要保存在源文件同目录并添加时间后缀时:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
asecli export-sg /path/to/Shader.shader \
|
|
193
|
+
--out-dir /path/to \
|
|
194
|
+
--output-suffix "_$(date +%Y%m%d_%H%M%S)"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
三份文件共用同一后缀,例如 `Shader_20260914_163000.asecli-to-sgcli.spec.json`。`--name` 只修改图名称,不能用于文件命名。将实际生成的三份路径原样传给 SGCLI;不要合并、解包或改写 JSON。
|
|
198
|
+
|
|
199
|
+
导出检查算法连接或已识别的数学等价映射、变量名、属性类型、默认值、范围、资源和 Shader 设置。已匹配的 AlphaModulate 可折叠到目标管线,输出路径保持一次调制;局部精度差异在 CLI 的 `precision_warnings` 和报告的检查证据中说明,不把整个图改成 Half,也不因缺少浮点逐位证明而阻断。错误连接、混合变化及无法映射的运行时属性仍会阻断。
|
|
200
|
+
|
|
201
|
+
验收分三层:ASECLI 导出通过;SGCLI 契约/转换认证及真实创建通过;最终编译、画布与效果验收。前一层不代表后一层。最终视觉不是生成 JSON 的前置条件,未运行证据保持 `not_run`。消费者若返回 `SEM-BLEND-002` 等认证错误,应在 SGCLI 侧核对具体规则,不修改 JSON 或省略证据绕过认证。
|
|
202
|
+
|
|
186
203
|
ASECLI 随 wheel 发布自己的 EditorGraphSpec v3 Schema,以及源自 SGCLI `0.3.5` 的固定 `sgcli.native.v3` JSON 快照。快照 SHA-256 标识本包完整性与精确协议修订,不依赖对方当前分支或安装版本。构建、测试、发布与安装只使用 ASECLI,不拉取或执行 SGCLI 源码,不要求同步发布。`MultiplySourceAlpha` 等扩展仍要求实际消费者和目标 URP 支持,导出成功不代表旧消费者兼容。跨产品端到端验收是独立黑盒流程,不是本仓发布前置;本仓任务不自动跨仓修改。
|
|
187
204
|
|
|
188
205
|
可用 `asecli contract editor-graph --version 3 --spec FILE` 在不连接 Editor 时执行权威 Schema/loader 并返回原文件 SHA。报告分开记录来源快照、发布前复核、生产者 Schema 与真实消费者读取状态。旧 `{graph,report}` wrapper 只允许按已登记形状显式迁移,且内层必须已经是 `sgcli.native.v3`;无版本 discriminator 的旧输入只报告 `legacy_format`,不得伪称已识别版本化 Schema:
|
|
@@ -244,7 +261,7 @@ asecli recompile Assets/Example.shader
|
|
|
244
261
|
| `validate <file>` | 检查悬空连线、重复 ID、输入多来源、Local Var 一致性和 CHKSM。 | 只读;有 error 时返回退出码 2。 |
|
|
245
262
|
| `graph-review <file> [--baseline FILE] [--reuse-policy consumer-groups\\|fanout]` | 保守核对计算基线并列出复用计划。 | 只读;基线不一致返回 `SEMANTIC_MISMATCH` / 2,不自动创建 Local Var。 |
|
|
246
263
|
| `graph-audit <file>` | 从 Master 反向分析未参与输出的节点,区分 `unused_candidates` 与外部消费者。 | 只读;Property 的源码/HLSL/GUI 引用不会被误报为可删。 |
|
|
247
|
-
| `export-sg <file> --out-dir DIR [--target-project PROJECT]` | 直接输出裸 `sgcli.native.v3`、独立转换报告和发布回执。 | spec
|
|
264
|
+
| `export-sg <file> --out-dir DIR [--target-project PROJECT] [--output-suffix SUFFIX]` | 直接输出裸 `sgcli.native.v3`、独立转换报告和发布回执。 | spec 是唯一图规格;report/receipt 分别作为转换认证证据;receipt 证明 spec/report 提交状态;不调用 SGCLI;同名失败;转换失败只写 report。 |
|
|
248
265
|
| `contract editor-graph --version 3 [--spec FILE]` | 输出 wheel 内权威 EditorGraphSpec v3 JSON Schema;可离线校验并回执输入 SHA。 | 只读;loader 仍执行端口、中文属性和模板等更强语义校验。 |
|
|
249
266
|
| `migrate-package <file> --out-dir DIR --extract-sg-spec` | 显式提取登记的旧 `{graph,report}` wrapper。 | 只接受内层 `sgcli.native.v3`;未知/v2 wrapper 只留失败报告,不进入正常消费者。 |
|
|
250
267
|
| `set-field <file> --node N --field I --value V [--write]` | 修改一个已知节点的绝对序列化字段。 | 默认预演;`--write` 后写入。不要用它猜写 Master 或未知版本尾部。 |
|
|
@@ -316,9 +333,9 @@ asecli recompile Assets/Example.shader
|
|
|
316
333
|
除显式 `--help` 保留人类可读文本外,stdout 恒为单行严格 JSON,agent 可直接解析。`--version` 也返回 JSON:
|
|
317
334
|
|
|
318
335
|
```json
|
|
319
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
320
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
321
|
-
{"contract_version":1,"cli_version":"0.8.
|
|
336
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"parse","ok":true,"data":{"node_count":7}}
|
|
337
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"parse","ok":false,"error":{"code":"NOT_FOUND","message":"..."}}
|
|
338
|
+
{"contract_version":1,"cli_version":"0.8.6","command":"version","ok":true,"data":{"version":"0.8.6"}}
|
|
322
339
|
```
|
|
323
340
|
|
|
324
341
|
常见错误码:`PARSE_ERROR`、`NOT_FOUND`、`USAGE_ERROR`、`SCHEMA_UNAVAILABLE`、`SCHEMA_VERSION_MISMATCH`、`VALIDATION_ERROR`、`PROPERTY_PRESENTATION_ERROR`、`LAYOUT_ERROR`、`CHECKSUM_FORMAT_ERROR`、`GUI_SUPPORT_ERROR`、`CUSTOM_GUI_ERROR`、`COMMENT_GROUP_ERROR`、`GRAPH_REVIEW_ERROR`、`SEMANTIC_MISMATCH`、`SG_EXPORT_BLOCKED`、`EXTERNAL_REFERENCE`、`SKILL_INSTALL_CONFLICT`、`SKILL_INSTALL_ERROR`、`WRITE_CONFLICT`、`WRITE_PARTIAL`、`UNSAFE_PATH`、`WRITE_ERROR`、`BRIDGE_ERROR`、`INTERNAL`。
|
|
@@ -46,3 +46,4 @@ evidence: [docs/05-audits/2026-09-01-122217-optimization-tasks.md]
|
|
|
46
46
|
| CR-0030 | 两 CLI 取消外部中间包:ASECLI 直接输出 SGCLI 原生裸 `sgcli.native.v3`,并以方向化 spec/report 文件名与 SGCLI 的 EditorGraphSpec 输出对称 | MOD-CLI MOD-BRIDGE MOD-SG-EXPORT MOD-CONTRACT MOD-SKILL | 新增 `export-sg`、`contract`;`create --spec` 拒绝 wrapper/report/反方向后缀;旧历史 JSON 不进入正式流程;候选 wheel Schema/篡改负例、发布 receipt 与跨仓 required workflow 失败关闭;不调用或依赖 SGCLI 运行时 | REG-0063 | 禁用新入口或回滚 wheel;不得恢复消费者隐式解包/正式 translator,不批量改名历史文件 | `v0.8.0@58ccf10` 已发布:publish run 34592028675、GitHub/PyPI 同源资产、本机 CLI/Skill 和 WaveNoise 双向原文件 SHA 全部复核通过;全量 `428 passed, 3 skipped`(Python 3.10 同结果)。最终 wheel Editor/画布/渲染仍开放,不声明视觉等价 |
|
|
47
47
|
|
|
48
48
|
授权来源:用户于 2026-09-01 明确要求“执行优化任务,全部完成”,并于同日批准吸收 ASE Editor API 方案后要求“执行”;随后明确要求先推送并执行对抗性审计优化计划。2026-09-02 用户要求推送并进一步明确“以正式的 CLI 形式发布”,据此创建私有正式 GitHub Release `v0.1.0`;同日进一步明确说明条样式一致性必须成为 CLI 的规范能力,据此登记 CR-0011/BUG-0015,并明确所有通过 CLI 构建的 ASE 文件都必须使用中文属性显示名、自动变量名与默认值 Tooltip 和中文使用说明,据此登记 CR-0012。同日用户要求执行 `2026-09-02-211218` 优化计划,据此登记 CR-0013;随后书面授权打 tag 并发布 `v0.2.0`。2026-09-03 用户要求执行最新优化任务书并把剩余门槛全部完成,据此登记 CR-0014 并授权完成必要提交、直接推送与远程 CI 验证;随后明确要求“推送并发布”,据此授权创建私有正式版本 `v0.3.0`。2026-09-04 用户要求将 ASE 精排与 Inspector 编排规范作为可安装 Skill 并授权发布 `v0.3.1`。2026-09-05 用户要求执行 MZGUI 对接与效率优化,随后分别授权私有版本 `v0.4.0`、`v0.4.1` 和审计补丁 `v0.4.2`。2026-09-06 用户明确 Tooltip 必填、HelpBox 可选、条件置灰并授权 `v0.5.0`;随后要求脑图式 DAG 精排并授权 `v0.6.0`;又将 Local Var 门槛改为两个及以上不同消费组,据此登记 CR-0020;最后以多组人工示范明确递归局部鱼骨、Comment 保留和显式 WireNode 路由并要求执行,据此登记 CR-0021。2026-09-07 用户明确授权提交、推送、私有 Release `v0.6.1` 和本机安装。同日进一步明确要求开源该项目并提供同事安装命令,据此登记 CR-0022:采用 MIT 许可证并将 GitHub 仓库转为 public。随后要求做成最终、最常见的安装形态,据此登记 CR-0023:发布 PyPI 项目 `asecli`,用户命令为 `uv tool install asecli`;仍未授权 CLI Hub。2026-09-08 用户进一步明确要求推送、发布新版本并安装本机,据此授权 `v0.6.2` 的 main 推送、tag、GitHub Release、PyPI Trusted Publishing 与本机正式产物安装;CLI Hub 仍不在授权范围。首次 PyPI OIDC 因没有对应账号和 Trusted Publisher 失败后,用户说明没有 PyPI 账号并明确要求继续 GitHub Release 发布,据此以 CR-0025 将 PyPI 延后并完成 GitHub-only 交付。随后用户取得 PyPI 账号并明确要求继续配置,据此登记 CR-0026,启用精确匹配的 Pending Publisher 并通过 run 34192454152 attempt 3 完成首次 PyPI 发布。同日用户要求将现有 Skill 改为主流 Agent 通用,据此登记 CR-0027;本次不包含推送、tag 或发布。2026-09-10 用户要求对 JSON 输出能力执行对抗审计与优化,随后明确要求推送、发布并安装本机,据此登记 CR-0029 并授权 `v0.7.0` GitHub Release、PyPI Trusted Publishing 与本机 CLI/Skill 安装;CLI Hub 仍不在范围。
|
|
49
|
+
| CR-0031 | ASE→SG 已知算法等价与精度证据分层;属性保真复核和输出后缀 | MOD-CLI MOD-SG-EXPORT MOD-SKILL | 加性 precision_warnings、surface_semantics、custom_function_manifest 和 --output-suffix;sgcli.native.v3 与公共报告 Schema 不变;不声明视觉等价 | REG-0064 | 安装 asecli==0.8.4;保留用户 Shader 和导出文件 | 485 passed/3 skipped;实文件导出及 SHA 对账通过;发布候选 v0.8.5 |
|
|
@@ -98,3 +98,6 @@
|
|
|
98
98
|
| 2026-09-11 | v0.8.0 双渠道发布与本机安装完成 | tag `v0.8.0` 解引用到 `58ccf10`;[publish run 34592028675](https://github.com/seeseeczl/ASECLI/actions/runs/34592028675) 的双 Python、package、public contract、Deploy Key cross-CLI 和 PyPI OIDC 全绿。GitHub Release 五项资产与 PyPI wheel/sdist 摘要一致且未 yanked;本机 CLI 为 0.8.0,`.agents`/`.claude` Skill 与 wheel 一致,旧三处 Skill 已备份。WaveNoise 双向生产/消费 SHA 一致;最终 wheel 的 Editor/画布/render 保持未验证披露。 | REL-0016 CR-0030 TASK-0065 REG-0063 |
|
|
99
99
|
| 2026-09-14 | v0.8.1 发布候选 | matcher-v4 识别并折叠原生 `Lerp(white,color,alpha)`,保留 Wave Noise 不可表示 Alpha Blend 的失败关闭;SGCLI 普通 authoring 与转换认证分离。发布前全量 `461 passed, 3 skipped`,CI governance、供应链与 diff 通过;远端 publish/PyPI、正式资产回读和本机安装待执行,Editor/画布/render 保持开放披露。 | REL-0017 CR-0030 TASK-0066 REG-0063 |
|
|
100
100
|
| 2026-09-14 | v0.8.1 双渠道发布与本机安装完成 | tag `v0.8.1` 解引用到 `610a7a3`;[publish run 34796442345](https://github.com/seeseeczl/ASECLI/actions/runs/34796442345) 的双 Python、可复现构建、供应链、锁定 SGCLI `b4f8310` 的跨 CLI 门禁与 PyPI OIDC 全绿。[GitHub Release](https://github.com/seeseeczl/ASECLI/releases/tag/v0.8.1) wheel/sdist 与 PyPI 摘要一致,本机 CLI 为 `0.8.1`,用户级 Skill 已同步;Editor/画布/render 保持开放披露。 | REL-0017 CR-0030 TASK-0066 REG-0063 |
|
|
101
|
+
| 2026-09-14 | v0.8.5 发布准备 | 用户授权推送发布;本地 485 passed/3 skipped,实文件导出成功;算法/属性/设置门禁保留,精度边界提示;远端与双渠道校验待执行 | CR-0031 TASK-0067 REG-0064 REL-0018 |
|
|
102
|
+
| 2026-09-14 | v0.8.5 双渠道发布完成 | tag cb80828;主线 CI 34823345703 与 publish 34823348963 全成功;GitHub 五资产回读与 PyPI SHA 一致,本机 0.8.5 和 Skill 校验通过;隔离回滚通过,Editor/视觉未运行 | CR-0031 TASK-0067 REG-0064 REL-0018 |
|
|
103
|
+
| 2026-09-14 | v0.8.6 文档补丁准备 | 已按用户要求删除仓库内三份未跟踪实机副本;README 补齐三文件认证、--write、时间后缀和分层验收;运行行为不变 | CR-0031 TASK-0068 REG-0064 REL-0019 |
|
|
@@ -63,3 +63,4 @@ BUG-0023,缺陷,已修复,ADR-0020,MOD-BRIDGE,TASK-0060,REG-0059,2026-09-08 两
|
|
|
63
63
|
CR-0028,变更,已发布(视觉与自动LocalVar仍待验),ADR-0021,MOD-CORE MOD-LAYOUT MOD-CLI MOD-SKILL,TASK-0061 TASK-0062 TASK-0063,REG-0060 REG-0061,端口级基线与复用计划及岛内刚性多列布局;未自动创建LocalVar;未做实机验收,REL-0014,long,保留并行创建器改动;不修改SGCLI
|
|
64
64
|
CR-0029,变更,已发布,ADR-0001 ADR-0009,MOD-CORE MOD-LAYOUT MOD-BRIDGE MOD-CLI MOD-SKILL,TASK-0064,REG-0062,2026-09-10 v0.7.0@029fea4;run 34475832000 全成功;GitHub/PyPI 摘要一致;本机 CLI/Skill 安装幂等,REL-0015,long,严格原子 JSON;非有限数拒绝;version JSON;22 错误码;17 子命令动态覆盖
|
|
65
65
|
CR-0030,变更,已发布(视觉门禁开放),ADR-0022,MOD-CLI MOD-BRIDGE MOD-SG-EXPORT MOD-CONTRACT MOD-SKILL,TASK-0065,REG-0063,2026-09-11 v0.8.0 publish run 34592028675 全绿;GitHub/PyPI 资产、本机 CLI/Skill 和 WaveNoise 双向原文件 SHA 通过,REL-0016,long,消费者原生裸规格与方向命名;最终 wheel Editor/画布/渲染仍开放
|
|
66
|
+
CR-0031,变更,已发布,,MOD-CLI MOD-SG-EXPORT MOD-SKILL,TASK-0067,REG-0064,v0.8.5@cb80828;run 34823348963;双渠道 SHA 与安装回滚通过,REL-0018,long,数学映射与精度证据分层;视觉不作前置
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
| MOD-SCHEMA | src/asecli/schema | FR-0002 CR-0002 BUG-0001 | 节点 schema、版本兼容与 mutation allowlist | `schema_for`;`schema_version`;`is_version_compatible` | 允许依赖 MOD-CORE 类型;禁止依赖 bridge/cli |
|
|
7
7
|
| MOD-CHECK | src/asecli/checks | FR-0003 CR-0002 CR-0003 BUG-0003 BUG-0006 | 图结构校验与 CHKSM 重算 | `validate_file`;`verify_checksum`;`fix_checksum` | 允许依赖 MOD-CORE;禁止依赖 bridge/cli |
|
|
8
8
|
| MOD-BRIDGE | src/asecli/bridge | FR-0004 FR-0008 FR-0009 FR-0011 CR-0001 CR-0004 CR-0008 CR-0009 CR-0010 CR-0011 CR-0012 CR-0013 CR-0014 CR-0016 CR-0017 CR-0018 CR-0019 CR-0021 CR-0024 CR-0029 CR-0030 BUG-0005 BUG-0012 BUG-0013 BUG-0016 BUG-0021 BUG-0023 | MCP 客户端、loopback 信任边界、tool result/envelope、重编译、受控 Editor 图创建、EditorGraphSpec 权威 Schema、WireNode 路由事务、确定性资源拼装与 GUI 支持升级 | `recompile_via_mcp`;`create_shader_via_mcp`;`editor_graph_schema`;`apply_wire_routes_via_mcp`;`inspect_gui_support`;`install_gui_support`;`McpClient` | 仅标准库;禁止依赖 cli;远程需显式授权 |
|
|
9
|
-
| MOD-CLI | src/asecli/cli | FR-0003 FR-0005 FR-0006 FR-0007 FR-0009 FR-0010 FR-0011 CR-0002 CR-0003 CR-0004 CR-0005 CR-0006 CR-0008 CR-0009 CR-0010 CR-0011 CR-0012 CR-0013 CR-0015 CR-0016 CR-0017 CR-0018 CR-0019 CR-0021 CR-0022 CR-0023 CR-0024 CR-0025 CR-0026 CR-0027 CR-0028 CR-0029 CR-0030 BUG-0004 BUG-0006 BUG-0008 BUG-0009 BUG-0010 BUG-0013 BUG-0017 BUG-0018 | 20 个命令、单行严格 JSON、原子 ASCII-safe 写出、写入/信任组合根、create 后端路由、双向 contract/export/migration 入口、属性呈现门禁、跨主流 Agent 的受控 Skill 安装与版本化可校验 CI 打包 | `asecli <command>`;`asecli export-sg`;`asecli contract`;`asecli migrate-package`;`asecli install-skill` | 允许依赖 core/schema/check/bridge/export;只能使用公开 API |
|
|
10
|
-
| MOD-SKILL | skills/asecli | FR-0006 FR-0008 FR-0009 FR-0010 FR-0011 CR-0007 CR-0008 CR-0010 CR-0013 CR-0015 CR-0016 CR-0018 CR-0019 CR-0020 CR-0021 CR-0027 CR-0028 CR-0029 CR-0030 | 通用 Agent Skill:ASE 格式说明、递归鱼骨精排、Inspector 分组/命名/说明规范、图/GUI/Comment/Local Var/编译操作手册、错误处理与跨 Agent 执行边界;随 wheel 打包并由 CLI 安装 | `SKILL.md`;`references/layout-standard.md`;`references/material-property-standard.md`(文档资产) | 无代码依赖;只要求 shell 与单行 JSON,不依赖某家 Agent 专属 API |
|
|
9
|
+
| MOD-CLI | src/asecli/cli | FR-0003 FR-0005 FR-0006 FR-0007 FR-0009 FR-0010 FR-0011 CR-0002 CR-0003 CR-0004 CR-0005 CR-0006 CR-0008 CR-0009 CR-0010 CR-0011 CR-0012 CR-0013 CR-0015 CR-0016 CR-0017 CR-0018 CR-0019 CR-0021 CR-0022 CR-0023 CR-0024 CR-0025 CR-0026 CR-0027 CR-0028 CR-0029 CR-0030 BUG-0004 BUG-0006 BUG-0008 BUG-0009 BUG-0010 BUG-0013 BUG-0017 BUG-0018 CR-0031 | 20 个命令、单行严格 JSON、原子 ASCII-safe 写出、写入/信任组合根、create 后端路由、双向 contract/export/migration 入口、属性呈现门禁、跨主流 Agent 的受控 Skill 安装与版本化可校验 CI 打包 | `asecli <command>`;`asecli export-sg`;`asecli contract`;`asecli migrate-package`;`asecli install-skill` | 允许依赖 core/schema/check/bridge/export;只能使用公开 API |
|
|
10
|
+
| MOD-SKILL | skills/asecli | FR-0006 FR-0008 FR-0009 FR-0010 FR-0011 CR-0007 CR-0008 CR-0010 CR-0013 CR-0015 CR-0016 CR-0018 CR-0019 CR-0020 CR-0021 CR-0027 CR-0028 CR-0029 CR-0030 CR-0031 | 通用 Agent Skill:ASE 格式说明、递归鱼骨精排、Inspector 分组/命名/说明规范、图/GUI/Comment/Local Var/编译操作手册、错误处理与跨 Agent 执行边界;随 wheel 打包并由 CLI 安装 | `SKILL.md`;`references/layout-standard.md`;`references/material-property-standard.md`(文档资产) | 无代码依赖;只要求 shell 与单行 JSON,不依赖某家 Agent 专属 API |
|
|
11
11
|
| MOD-LAYOUT | src/asecli/core/layout.py; meticulous_layout.py; layout_audit.py; comment_layout.py; wire_geometry.py; wire_router.py | FR-0008 FR-0010 CR-0019 CR-0020 CR-0021 CR-0028 CR-0029 | 兼容分层布局;基于真实端口和直属来源局部输出线的递归鱼骨、Local Var 跨组审计、Comment 保留/收框/作用标题、显式 WireNode 路由计划 | `layout_positions`;`meticulous_layout_positions`;`audit_meticulous_layout`;`plan_wire_routes` | 允许依赖 core 模型;禁止依赖 schema/bridge/cli |
|
|
12
12
|
| MOD-CUSTOM-GUI | src/asecli/core/custom_gui.py; custom_gui_versions.py; material_gui_spec.py; material_gui_condition.py; property_presentation.py | FR-0009 FR-0010 CR-0009 CR-0010 CR-0012 CR-0016 CR-0018 BUG-0011 | 真实版本能力矩阵;主 Master/ShaderLab CustomEditor 同步;PropertyNode MZGUI 元数据尾部、中文显示名、UTF-16 文案、旧标记兼容、条件置灰、批量治理与 `asecli.property-presentation.v2` 检查 | `inspect_custom_gui`;`resolve_property_node`;`apply_material_gui_spec`;`require_property_presentation` | 仅依赖 MOD-CORE model;禁止依赖 schema/check/bridge/cli |
|
|
13
13
|
| MOD-GUI-SUPPORT | src/asecli/bridge/gui_support.py; gui_provider_detection.py; `_gui_project.py`; `_gui_resource_store.py`; `_gui_resource_upgrade.py`; gui_presentation.py; bridge/resources/asecli_material_gui*.cs.txt | FR-0009 CR-0009 CR-0010 CR-0011 CR-0014 CR-0016 CR-0018 BUG-0014 BUG-0015 BUG-0019 BUG-0020 BUG-0022 | 原生 MZGUI 优先选择;fallback 安全安装/已知哈希升级;以同一个 `MZGUI.MZGUI` 公共入口渲染 Inspector;ASE Editor 可视化编辑三类标准属性;打开图时恢复元数据;未知版本能力失败关闭 | `inspect_gui_support`;`install_gui_support`;`MZGUI.MZGUI`;`ASECLIGUIAttributesWindow` | Python 仅标准库;C# 仅 UnityEditor/UnityEngine,通过字符串反射适配 ASE,禁止源码补丁和编译期 ASE 引用 |
|
|
14
14
|
| MOD-COMMENTARY | src/asecli/core/commentary.py | FR-0010 | CommentaryNode 可变长序列化、成员树检查与自动包围框 | `inspect_comment_groups`;`create_comment_group` | 仅依赖 MOD-CORE model/graph_ops;禁止依赖 schema/check/bridge/cli |
|
|
15
|
-
| MOD-SG-EXPORT | src/asecli/export_sg.py; src/asecli/sg_export | CR-0030 | 从 ASE 图与生成 ShaderLab 建立源 manifest,映射属性、节点、连接、Register/Get、Comment、资源和 Target,输出裸 `sgcli.native.v3` 与独立转换报告 | `export_sg`;`build_native_spec`;`build_conversion_report` | 允许依赖 MOD-CORE 与公开 contracts;禁止调用 SGCLI、依赖 SGCLI Python 包或输出 source-native wrapper |
|
|
15
|
+
| MOD-SG-EXPORT | src/asecli/export_sg.py; src/asecli/sg_export | CR-0030 CR-0031 | 从 ASE 图与生成 ShaderLab 建立源 manifest,映射属性、节点、连接、Register/Get、Comment、资源和 Target,输出裸 `sgcli.native.v3` 与独立转换报告 | `export_sg`;`build_native_spec`;`build_conversion_report` | 允许依赖 MOD-CORE 与公开 contracts;禁止调用 SGCLI、依赖 SGCLI Python 包或输出 source-native wrapper |
|
|
16
16
|
| MOD-CONTRACT | src/asecli/contracts.py; src/asecli/contracts | CR-0030 | 随 wheel 发布 EditorGraphSpec v3 权威 Schema,并固定 SGCLI native v3 消费快照版本/SHA | `editor_graph_schema`;`native_v3_snapshot` | 仅静态 package resource;不得放宽运行时 loader 或建立跨仓运行时依赖 |
|
|
17
17
|
|
|
18
18
|
## 依赖规则
|
|
@@ -31,3 +31,7 @@
|
|
|
31
31
|
12. MaterialGUI 的长中文标签在窄宽度下自动换行,字段独占下一行;技术 Tooltip 默认值使用最多六位小数的 invariant 格式。REG-0042 是主题、宽度、缩放和交互状态回归基线。
|
|
32
32
|
13. `asecli install-skill` 只安装随 wheel 打包的 `asecli` Skill。无参数保持原 Codex 用户目录;显式路由支持开放 `.agents` 以及 Codex、Claude Code、Cursor、Gemini CLI、GitHub Copilot 的用户级/项目级目录。`all` 只写 `.agents` 与 `.claude` 两个非重复根并在写入前检查全部内容冲突;同内容幂等,不同内容失败关闭,不覆盖用户自定义 Skill。wheel 必须包含 Skill 与所有引用规范。
|
|
33
33
|
14. 双向转换的外部交接只允许消费者原生裸规格:ASECLI 只消费 `EditorGraphSpec v3`,只生产 `sgcli.native.v3`;spec/report 分文件,方向后缀固定,同名不覆盖。内部 manifest/IR 不得成为用户必须传递的第三份图 JSON。
|
|
34
|
+
|
|
35
|
+
### MOD-CLI / MOD-SG-EXPORT:CR-0031
|
|
36
|
+
|
|
37
|
+
`export-sg --output-suffix` 只为 spec/report/receipt 文件名追加 ASCII 字母、数字、下划线或连字符,不改变图名称,默认空串且禁止覆盖。CLI 成功返回新增 `precision_warnings`、`surface_semantics`、`custom_function_manifest`;失败返回也携带精度提示。公共 spec/report Schema 保持不变,报告既有 evidence 字段保存精度边界,不将其标记为视觉已验证。
|
|
@@ -135,3 +135,7 @@ kickoff_completion: complete
|
|
|
135
135
|
- [x] 技术路径与需求基线已经用户确认(本会话对话确认)
|
|
136
136
|
- [x] 模块边界与依赖方向已定义并写入模块地图
|
|
137
137
|
- [x] 首批 14 张任务卡与追溯矩阵已建立且双向链接
|
|
138
|
+
|
|
139
|
+
## CR-0031 — 转换保真与精度边界
|
|
140
|
+
|
|
141
|
+
导出必须保留算法或采用已认证数学映射,并对账变量名、类型、默认值、范围、资源和 Shader 设置。已识别 AlphaModulate 的局部浮点精度边界单独提示;浮点逐位或视觉未验证不阻断 JSON。错误连接、混合和无法表示的运行时属性继续失败关闭。关联 TASK-0067、REG-0064。
|
|
@@ -65,3 +65,4 @@
|
|
|
65
65
|
| REG-0061 | CR-0028 | island-packing:保持岛内鱼骨相对位置、逻辑依赖顺序、主输出锚定、二次幂等、非法几何与列数失败关闭、保留默认布局契约 | `uv run --frozen pytest tests/test_island_layout.py tests/test_layout_governance.py tests/test_layout.py tests/test_cli_contract.py` | 定向 94 passed;自动环节已验证;本次未写 Unity 工程,实机画布待验 |
|
|
66
66
|
| REG-0062 | CR-0029 AA-DATA-001 AA-DATA-002 AA-CONTRACT-001 AA-CONTRACT-002 AA-TEST-001 | cli-json-contract-v1:先序列化后原子 ASCII-safe 写出;拒绝 NaN/Infinity 与非有限几何;顶层契约/版本/命令字段;version JSON/help 唯一文本例外;22 错误码与 17 子命令动态对账 | `uv run --frozen pytest tests/test_cli_contract.py tests/test_bridge_contract.py tests/test_commentary.py tests/test_smoke.py tests/test_install_scripts.py` + 全量 pytest + 隔离 wheel console-script smoke | 定向 76 passed;全量 388 passed/3 skipped;ASCII stdout+中文错误路径、wheel 安装、lock/CI/供应链/文档治理/diff 通过;Editor/Windows 未本地运行,Windows 交由发布 CI 验证 |
|
|
67
67
|
| REG-0063 | CR-0030 ADR-0022 AUD-FLOW-001 AUD-CONTRACT-002 AUD-CONTRACT-003 AA-CONTRACT-201 AA-CI-202 AA-REL-203 AA-TEST-204 AA-EVIDENCE-205 AA-DATA-206 AA-MIGRATE-207 AA-CI-301 AA-CI-302 AA-TEST-303 AA-EVIDENCE-304 AA-REL-305 AA-EVIDENCE-306 AA-CONTRACT-307 AA-PROV-308 AA-GOV-309 | direct-cross-cli-json-v3:`export-sg` 规范命名与失败仅报告;裸 native v3 顶层;反方向/report/wrapper/未知字段拒绝;Draft 2020-12 数值 parity;三态 receipt 交叉绑定;build-once 候选 wheel;固定 WaveNoise 双向语义 fixture;fixture-set 完整性;clean provenance;生产者输出与消费者输入 SHA-256 完全一致 | `uv run --frozen pytest tests/test_export_sg.py tests/test_contract_schema.py tests/test_editor_create_cli.py tests/test_cli_contract.py tests/test_build_reproducibility.py tests/test_cross_cli_workflow.py` + SGCLI `tests/test_cross_cli_semantics.py`、双 wheel 黑盒 matrix/verifier + bridge 3 分层 E2E | 第三轮全量 `428 passed, 3 skipped`,Python 3.10 同结果;临时干净快照 release-mode matrix 两仓 `dirty=false`、WaveNoise configured、离线 verifier 通过。远端 required checks/ruleset、最终 wheel Editor/画布/render 未关闭,不得声明发布或视觉等价。 |
|
|
68
|
+
| REG-0064 | CR-0031 | export-fidelity:已知算法折叠、精度提示、属性篡改拒绝、设置负例与后缀 receipt | `uv run --frozen pytest tests/test_export_precision_diagnostics.py tests/test_export_property_visibility.py tests/test_export_fidelity.py tests/test_surface_semantics.py` | 自动通过;私有真实 Shader 仅显式 opt-in,不作为公开 CI 必需输入 |
|
|
@@ -121,3 +121,5 @@ kickoff_completion: complete
|
|
|
121
121
|
- [x] 64 张原子任务卡已定义;本次新增 CR/REG 双向链接完整(实机项保持待验)
|
|
122
122
|
- [x] 里程碑、验收命令、停止条件与回滚已定义
|
|
123
123
|
- [x] 门禁与审计计划已建立
|
|
124
|
+
| TASK-0067 | CR-0031 REL-0018 | 发布 ASE→SG 精度提示与保真修复 v0.8.5 | 用户明确授权推送并发布 | 导出、报告、测试、Skill 与发布元数据 | SGCLI、源 Shader、Editor 与视觉验收 | long/2026-09-14 | REG-0064;pytest、治理、双构建、远端 CI、双渠道 SHA、隔离安装回滚 | 任一发布检查失败则停止 | 本地 485 passed/3 skipped;正式候选 484 passed/4 skipped;run 34823348963、GitHub/PyPI SHA、本机安装与回滚通过 | released |
|
|
125
|
+
| TASK-0068 | CR-0031 REL-0019 | 清理本地实机副本并发布 README 说明补丁 0.8.6 | 用户授权丢弃三文件、更新 README、推送发布和本机安装 | 三个未跟踪文件、README 与版本发布记录 | 源 Tuanjie 资产、SGCLI 与运行逻辑 | long/2026-09-14 | REG-0064;文档 diff、发布治理、测试、双构建、双渠道 SHA 与安装回滚 | 发布检查失败则停止,保留 0.8.5 | 清理及 README 更新完成,发布验证中 | verified |
|
|
@@ -26,7 +26,9 @@ description: Create, modify, validate, and strictly lay out Amplify Shader Edito
|
|
|
26
26
|
|
|
27
27
|
- 先核对 CLI 路径/版本和源 SHA;当前 `.shader`、历史 `.bak`、旧 report 不可混为同一次转换证据。
|
|
28
28
|
- 新版失败返回的顶层 `data` 包含 `blockers`、`blocker_count`、`unverified_checks`、源快照与 `surface_semantics`。它是本次检测清单,不保证穷尽所有潜在问题;旧版没有这些字段时读取 `report_json`,不要猜测只有一个阻断。
|
|
29
|
-
-
|
|
29
|
+
- AlphaModulate 仅在表达式、Alpha 来源及 RGB/Alpha 混合方程匹配后折叠到目标管线,输出路径只调制一次。局部精度差异通过 `precision_warnings` / `ALPHA_MODULATE_PRECISION_BOUNDARY` 报告,不阻断导出;不得全局改为 Half,也不得把 `MultiplySourceAlpha` 用于需要保留背景 Alpha 的源 Shader。旧版 `ALPHA_MODULATE_TARGET_CAPABILITY_REQUIRED` 不是 SG 不支持 float 的证据。
|
|
30
|
+
- 默认门禁检查算法映射、变量名、默认值、范围、类型、资源和 Shader 设置;最终视觉及浮点逐位一致不作为 JSON 发布前置,未运行的 Editor/效果证据保持 `not_run`。
|
|
31
|
+
- 同目录时间后缀使用 `export-sg FILE --out-dir DIR --output-suffix _YYYYMMDD_HHMMSS`,同时命名 spec/report/receipt;`--name` 只修改图名称,不能替代文件名后缀。
|
|
30
32
|
- 上游 Custom Function 作为目标 Custom Function 原样交接;用 `custom_function_manifest` 核对节点、精度和规范化函数载荷 SHA,不因 Agent 无法解释函数数学意义而拒绝。
|
|
31
33
|
- 已确认的 `MZGUI.MZGUI`、Tooltip/Foldout/HelpBox 只影响 Inspector 呈现,列在 `presentation_warnings`,不阻断渲染语义交接。其他未知 Custom ShaderGUI 仍可能有材质副作用并失败关闭。
|
|
32
34
|
- `retry_unchanged_input=false` 时不要重复相同导出、猜命令或找强制开关。报告缺失能力并停止;SGCLI 的新增能力必须通过公开 JSON 契约另行交接,不跨仓修补。
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import hashlib
|
|
6
6
|
import json
|
|
7
|
+
import re
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
from ..contracts import validate_sgcli_native_spec
|
|
@@ -35,6 +36,7 @@ def configure_export_sg_parser(sub) -> None:
|
|
|
35
36
|
help="target Unity project; defaults to the project containing the source Shader",
|
|
36
37
|
)
|
|
37
38
|
parser.add_argument("--name")
|
|
39
|
+
parser.add_argument("--output-suffix", help="filename suffix, e.g. _20260914_163000; does not change graph name")
|
|
38
40
|
parser.add_argument("--asset-map")
|
|
39
41
|
parser.set_defaults(func=cmd_export_sg)
|
|
40
42
|
|
|
@@ -42,7 +44,10 @@ def configure_export_sg_parser(sub) -> None:
|
|
|
42
44
|
def cmd_export_sg(args) -> dict:
|
|
43
45
|
source = Path(args.file).resolve()
|
|
44
46
|
out = Path(args.out_dir).resolve()
|
|
45
|
-
|
|
47
|
+
suffix = getattr(args, "output_suffix", None) or ""
|
|
48
|
+
if suffix and not re.fullmatch(r"[A-Za-z0-9_-]+", suffix):
|
|
49
|
+
raise CliError("USAGE_ERROR", "output suffix must contain only letters, digits, underscores or hyphens")
|
|
50
|
+
spec_path, report_path = _conversion_paths(source, out, suffix)
|
|
46
51
|
receipt_path = _receipt_path(spec_path)
|
|
47
52
|
if not source.is_file():
|
|
48
53
|
raise CliError("NOT_FOUND", f"file not found: {source}")
|
|
@@ -128,6 +133,8 @@ def cmd_export_sg(args) -> dict:
|
|
|
128
133
|
write_result = _write_pair(spec_path, spec, report_path, report)
|
|
129
134
|
return {
|
|
130
135
|
"written": True,
|
|
136
|
+
"precision_warnings": internal.get("precision_warnings", []),
|
|
137
|
+
"surface_semantics": internal.get("surface_semantics"),
|
|
131
138
|
"spec_json": str(spec_path),
|
|
132
139
|
"report_json": str(report_path),
|
|
133
140
|
"receipt_json": str(receipt_path),
|
|
@@ -135,13 +142,14 @@ def cmd_export_sg(args) -> dict:
|
|
|
135
142
|
"connection_count": len(spec["connections"]),
|
|
136
143
|
"source_sha256": internal["source"]["sha256"],
|
|
137
144
|
"write": write_result,
|
|
145
|
+
"custom_function_manifest": internal.get("custom_function_manifest", []),
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
|
|
141
|
-
def _conversion_paths(source: Path, out: Path) -> tuple[Path, Path]:
|
|
149
|
+
def _conversion_paths(source: Path, out: Path, suffix: str = "") -> tuple[Path, Path]:
|
|
142
150
|
return (
|
|
143
|
-
out / f"{source.stem}{SPEC_SUFFIX}",
|
|
144
|
-
out / f"{source.stem}{REPORT_SUFFIX}",
|
|
151
|
+
out / f"{source.stem}{suffix}{SPEC_SUFFIX}",
|
|
152
|
+
out / f"{source.stem}{suffix}{REPORT_SUFFIX}",
|
|
145
153
|
)
|
|
146
154
|
|
|
147
155
|
|
|
@@ -207,7 +215,8 @@ def _failure_details(report_path: Path, internal: dict | None, report: dict) ->
|
|
|
207
215
|
"blocker_count": len(blockers),
|
|
208
216
|
"blocker_scope": "detected_in_this_run_not_exhaustive",
|
|
209
217
|
"presentation_warnings": warnings,
|
|
210
|
-
"
|
|
218
|
+
"precision_warnings": internal.get("precision_warnings", []),
|
|
219
|
+
"warning_count": len(warnings) + len(internal.get("precision_warnings", [])),
|
|
211
220
|
"custom_function_manifest": internal.get("custom_function_manifest", []),
|
|
212
221
|
"required_target_capabilities": (internal.get("surface_semantics") or {}).get(
|
|
213
222
|
"required_target_capabilities"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Build an unbound SGCLI candidate from certified ASE semantics."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
|
|
7
6
|
from ..core import (AseFile, COMMENTARY_TYPE, GET_LOCAL_VAR_TYPE,
|
|
@@ -13,7 +12,7 @@ from .model import (
|
|
|
13
12
|
)
|
|
14
13
|
from .nodes import convert_node
|
|
15
14
|
from .sources import compiled_properties, load_asset_map
|
|
16
|
-
from .evidence import inspector_degradations, record_custom_functions, record_port, validate_template_passes
|
|
15
|
+
from .evidence import mark_folded_functions, inspector_degradations, record_custom_functions, record_port, validate_template_passes
|
|
17
16
|
from .surface_semantics import normalize_surface_outputs
|
|
18
17
|
from .reconciliation import (
|
|
19
18
|
groups, reconcile_shaderlab_properties, unique_properties, verify_texture_dependencies,
|
|
@@ -123,8 +122,9 @@ def build_candidate(
|
|
|
123
122
|
for node in nodes:
|
|
124
123
|
for target_id in node.source_ids:
|
|
125
124
|
edges.append(SemanticEdge(node.target_id, 0, target_id, -1))
|
|
126
|
-
record_custom_functions(nodes, report)
|
|
125
|
+
record_custom_functions(nodes, report, _graph_precision(master))
|
|
127
126
|
nodes, edges = normalize_surface_outputs(nodes, edges, target_spec, mappings, report, text)
|
|
127
|
+
mark_folded_functions(nodes, report)
|
|
128
128
|
groups_spec = groups(ase, mappings, diagnostics)
|
|
129
129
|
report["output_bindings"] = [
|
|
130
130
|
{"block": edge.target_id, "port": edge.target_port}
|
|
@@ -10,7 +10,8 @@ from .alpha_modulate import _strip_comments
|
|
|
10
10
|
from .model import MASTER_TYPE, URP_UNLIT_GUID, URP_UNLIT_PASSES, diagnostic
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def record_custom_functions(nodes, report):
|
|
13
|
+
def record_custom_functions(nodes, report, graph_precision=None):
|
|
14
|
+
report["source_graph_precision"] = graph_precision
|
|
14
15
|
manifest = []
|
|
15
16
|
for node in nodes:
|
|
16
17
|
if node.target_type != "custom-function" or node.function is None:
|
|
@@ -102,3 +103,10 @@ def record_port(report, source_id, source_port, source_end, target_id, target_po
|
|
|
102
103
|
row["ports"].append({"source": [source_id, source_port], "target": list(source_end)})
|
|
103
104
|
if target_id in row["source_nodes"]:
|
|
104
105
|
row["ports"].append({"source": [target_id, target_port], "target": list(target_end)})
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def mark_folded_functions(nodes, report):
|
|
109
|
+
remaining_ids = {node.target_id for node in nodes}
|
|
110
|
+
for item in report["custom_function_manifest"]:
|
|
111
|
+
if item["target_node_id"] not in remaining_ids:
|
|
112
|
+
item["mapping"] = "folded_into_target_pipeline"
|
|
@@ -22,6 +22,40 @@ _TEMPLATE_PROPERTIES = {
|
|
|
22
22
|
|
|
23
23
|
def reconcile_shaderlab_properties(compiled, properties, report, diagnostics):
|
|
24
24
|
mapped = {row["name"] for row in properties}
|
|
25
|
+
for prop in properties:
|
|
26
|
+
name = prop["name"]
|
|
27
|
+
source = compiled.get(name)
|
|
28
|
+
if source is None:
|
|
29
|
+
diagnostics.append(diagnostic(None, "PROPERTY_FIDELITY_MISMATCH",
|
|
30
|
+
{"property": name, "field": "name"}, "Target property has no source declaration"))
|
|
31
|
+
continue
|
|
32
|
+
for attribute in source.get("attributes", []):
|
|
33
|
+
tag = attribute.split("(", 1)[0].strip()
|
|
34
|
+
if tag in {"Toggle", "ToggleOff", "KeywordEnum", "Gamma", "PerRendererData",
|
|
35
|
+
"Enum", "IntRange", "Normal", "NoScaleOffset", "MainTexture", "MainColor"}:
|
|
36
|
+
diagnostics.append(diagnostic(None, "PROPERTY_ATTRIBUTE_UNSUPPORTED",
|
|
37
|
+
{"property": name, "field": "attributes", "attribute": attribute},
|
|
38
|
+
"Runtime property attribute has no certified target mapping"))
|
|
39
|
+
kind = prop["type"]
|
|
40
|
+
expected = {"type": source["type"], "default": source.get("default"),
|
|
41
|
+
"range": source.get("range"), "hdr": source.get("hdr", False),
|
|
42
|
+
"hidden": not source["exposed"], "exposed": True}
|
|
43
|
+
actual = {"type": kind, "default": prop.get("default"), "range": prop.get("range"),
|
|
44
|
+
"hdr": prop.get("hdr", False),
|
|
45
|
+
"hidden": prop.get("settings", {}).get("hidden", False),
|
|
46
|
+
"exposed": prop.get("exposed", True)}
|
|
47
|
+
if kind in {"vector2", "vector3"} and source["type"] == "vector4":
|
|
48
|
+
expected["type"] = kind
|
|
49
|
+
expected["default"] = source["default"][:int(kind[-1])]
|
|
50
|
+
# Texture bindings are checked against GUID/importer snapshots separately.
|
|
51
|
+
if kind == "texture2d":
|
|
52
|
+
expected.pop("default")
|
|
53
|
+
actual.pop("default")
|
|
54
|
+
for field, value in expected.items():
|
|
55
|
+
if actual[field] != value:
|
|
56
|
+
diagnostics.append(diagnostic(None, "PROPERTY_FIDELITY_MISMATCH",
|
|
57
|
+
{"property": name, "field": field, "source": value, "target": actual[field]},
|
|
58
|
+
"Property runtime data changed during conversion"))
|
|
25
59
|
for name, row in sorted(compiled.items()):
|
|
26
60
|
if name in mapped:
|
|
27
61
|
continue
|
|
@@ -18,7 +18,6 @@ _VERIFIED_EVIDENCE = {
|
|
|
18
18
|
_SEMANTIC_CODES = {
|
|
19
19
|
"ALPHA_BLEND_UNREPRESENTABLE", "PASS_BLEND_UNPROVEN",
|
|
20
20
|
"DUPLICATE_ALPHA_MODULATE_UNRESOLVED", "ALPHA_MODULATE_UNPROVEN",
|
|
21
|
-
"ALPHA_MODULATE_TARGET_CAPABILITY_REQUIRED",
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
|
|
@@ -51,7 +50,6 @@ def _blend_details(name: str, internal: dict[str, Any] | None) -> str:
|
|
|
51
50
|
rewrites = semantics.get("rewrites") or []
|
|
52
51
|
matcher = (
|
|
53
52
|
"unresolved" if semantics.get("unresolved")
|
|
54
|
-
or semantics.get("fold_precision", {}).get("status") == "unproven"
|
|
55
53
|
else "folded" if rewrites
|
|
56
54
|
else "preserved_graph_float_expression"
|
|
57
55
|
if semantics.get("alpha_modulate_strategy") == "preserve_graph_float_expression"
|
|
@@ -63,4 +61,6 @@ def _blend_details(name: str, internal: dict[str, Any] | None) -> str:
|
|
|
63
61
|
f" source={semantics.get('source_pass_blend')}"
|
|
64
62
|
f" target={semantics.get('target_pass_blend')}"
|
|
65
63
|
f" alpha_modulate=matcher-v4/{matcher}"
|
|
64
|
+
+ "; precision_evidence=" + json.dumps(semantics.get("fold_precision"), ensure_ascii=False, sort_keys=True)
|
|
65
|
+
+ "; algorithm verification excludes bitwise and visual equivalence"
|
|
66
66
|
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Record precision boundaries separately from certified algorithm rewrites."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from .alpha_modulate import _strip_comments
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def record_fold_precision(node, nodes, edges, report, semantics):
|
|
9
|
+
"""Called only after expression, inputs and blend equations match.
|
|
10
|
+
|
|
11
|
+
A precision boundary is not a proof of bitwise or visual equivalence.
|
|
12
|
+
Explicit body types are evidence, not the effective type of a whole function.
|
|
13
|
+
"""
|
|
14
|
+
declared = node.settings.get("precision", "Inherit")
|
|
15
|
+
graph = report.get("source_graph_precision")
|
|
16
|
+
inherited = declared in {"Inherit", "Graph"}
|
|
17
|
+
resolved = graph if inherited else declared
|
|
18
|
+
body = (_strip_comments((node.function or {}).get("body", ""))
|
|
19
|
+
if node.target_type == "custom-function" else None)
|
|
20
|
+
explicit = sorted(set(re.findall(r"\b(?:float|half)(?:[1-4])?\b", body or "")))
|
|
21
|
+
by_id = {item.target_id: item for item in nodes}
|
|
22
|
+
operands = [by_id.get(edge.source_id) for edge in edges if edge.target_id == node.target_id]
|
|
23
|
+
operand_precisions = [item.settings.get("precision", "Inherit") if item else "Unknown"
|
|
24
|
+
for item in operands]
|
|
25
|
+
half_boundary = resolved == "Half" and (
|
|
26
|
+
(bool(explicit) and all(t.startswith("half") for t in explicit))
|
|
27
|
+
if body is not None else
|
|
28
|
+
(bool(operands) and all((graph if p in {"Inherit", "Graph"} else p) == "Half"
|
|
29
|
+
for p in operand_precisions))
|
|
30
|
+
)
|
|
31
|
+
proof = {
|
|
32
|
+
"source_node_id": node.source_id,
|
|
33
|
+
"source_node_precision": declared,
|
|
34
|
+
"source_graph_precision": graph,
|
|
35
|
+
"inheritance_source": "graph" if inherited else "node",
|
|
36
|
+
"source_resolved_precision": resolved or "Unknown",
|
|
37
|
+
"source_explicit_types": explicit,
|
|
38
|
+
"source_operand_precisions": operand_precisions,
|
|
39
|
+
"source_expression": body,
|
|
40
|
+
"target_precision": "Half",
|
|
41
|
+
"target_function": "half3 AlphaModulate(half3 albedo, half alpha)",
|
|
42
|
+
"status": "matched_half_boundary" if half_boundary else "precision_difference_or_unknown",
|
|
43
|
+
"bitwise_equivalence": "not_proven",
|
|
44
|
+
"transformation": "fold_explicit_alpha_modulate_into_pipeline",
|
|
45
|
+
}
|
|
46
|
+
semantics["fold_precision"] = proof
|
|
47
|
+
if not half_boundary:
|
|
48
|
+
report.setdefault("precision_warnings", []).append({
|
|
49
|
+
"code": "ALPHA_MODULATE_PRECISION_BOUNDARY",
|
|
50
|
+
"source_node_id": node.source_id,
|
|
51
|
+
"classification": "precision",
|
|
52
|
+
"evidence": proof,
|
|
53
|
+
"impact": "Certified mathematical mapping preserves one modulation and blend factors; "
|
|
54
|
+
"the pipeline half boundary may change rounding or representable range. "
|
|
55
|
+
"Bitwise and visual equivalence have not been verified.",
|
|
56
|
+
})
|
|
@@ -12,7 +12,7 @@ from __future__ import annotations
|
|
|
12
12
|
from .alpha_modulate import inputs as alpha_modulate_inputs
|
|
13
13
|
from .model import SemanticEdge, SemanticNode, diagnostic
|
|
14
14
|
from .pass_blend import record_pass_blend
|
|
15
|
-
from .surface_precision import
|
|
15
|
+
from .surface_precision import record_fold_precision
|
|
16
16
|
from .surface_matching import (
|
|
17
17
|
_input_port,
|
|
18
18
|
_native_alpha_modulate,
|
|
@@ -81,6 +81,11 @@ def normalize_surface_outputs(
|
|
|
81
81
|
semantics.get("pass_blend_parser", {}),
|
|
82
82
|
"The source Forward-pass RGB and alpha blend factors were not uniquely proved",
|
|
83
83
|
))
|
|
84
|
+
if (target.get("surface") == "Transparent" and (
|
|
85
|
+
semantics.get("rgb_blend_equivalent") is not True
|
|
86
|
+
or semantics.get("alpha_blend_equivalent") is not True
|
|
87
|
+
)):
|
|
88
|
+
return nodes, edges
|
|
84
89
|
if not semantics["target_pipeline"]["implicit_alpha_modulate"]:
|
|
85
90
|
return nodes, edges
|
|
86
91
|
|
|
@@ -95,9 +100,7 @@ def normalize_surface_outputs(
|
|
|
95
100
|
native = _native_alpha_modulate(nodes, edges, color_edge, alpha_edge)
|
|
96
101
|
if native is not None:
|
|
97
102
|
modulate, color_input, alpha_input, route_nodes, white_node = native
|
|
98
|
-
|
|
99
|
-
if not precision_ok:
|
|
100
|
-
return nodes, edges
|
|
103
|
+
record_fold_precision(modulate, nodes, edges, report, semantics)
|
|
101
104
|
replacement = SemanticEdge(
|
|
102
105
|
color_input.source_id,
|
|
103
106
|
color_input.source_port,
|
|
@@ -185,9 +188,7 @@ def normalize_surface_outputs(
|
|
|
185
188
|
"AlphaModulate alpha input differs from Surface Alpha",
|
|
186
189
|
)
|
|
187
190
|
return nodes, edges
|
|
188
|
-
|
|
189
|
-
if not precision_ok:
|
|
190
|
-
return nodes, edges
|
|
191
|
+
record_fold_precision(node, nodes, edges, report, semantics)
|
|
191
192
|
replacement = SemanticEdge(
|
|
192
193
|
color_input.source_id,
|
|
193
194
|
color_input.source_port,
|