asecli 0.6.3__tar.gz → 0.6.4__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.6.3 → asecli-0.6.4}/PKG-INFO +4 -2
- {asecli-0.6.3 → asecli-0.6.4}/README.md +3 -1
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/change-register.md +1 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/timeline.md +3 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/traceability.csv +2 -1
- {asecli-0.6.3 → asecli-0.6.4}/docs/01-architecture/module-map.md +4 -4
- {asecli-0.6.3 → asecli-0.6.4}/docs/01-architecture/technical-route.md +1 -1
- {asecli-0.6.3 → asecli-0.6.4}/docs/03-quality/regression-catalog.md +2 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/04-delivery/project-plan-task-charter.md +5 -2
- {asecli-0.6.3 → asecli-0.6.4}/pyproject.toml +1 -1
- {asecli-0.6.3 → asecli-0.6.4}/scripts/install.ps1 +1 -1
- {asecli-0.6.3 → asecli-0.6.4}/scripts/install.sh +1 -1
- {asecli-0.6.3 → asecli-0.6.4}/skills/asecli/SKILL.md +2 -0
- asecli-0.6.4/skills/asecli/references/conversion-workflow.md +41 -0
- {asecli-0.6.3 → asecli-0.6.4}/skills/asecli/references/layout-standard.md +5 -1
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/__init__.py +1 -1
- asecli-0.6.4/src/asecli/cli/graph_review_command.py +25 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/layout_command.py +27 -1
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/main.py +8 -16
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/__init__.py +5 -0
- asecli-0.6.4/src/asecli/core/graph_review.py +104 -0
- asecli-0.6.4/src/asecli/core/island_layout.py +109 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/layout_audit.py +3 -3
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/meticulous_layout.py +11 -0
- asecli-0.6.4/src/asecli/core/reuse_plan.py +46 -0
- asecli-0.6.4/tests/test_graph_review.py +100 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_install_scripts.py +2 -2
- asecli-0.6.4/tests/test_island_layout.py +60 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_layout_local_var_policy.py +14 -0
- asecli-0.6.4/tests/test_smoke.py +4 -0
- {asecli-0.6.3 → asecli-0.6.4}/uv.lock +1 -1
- asecli-0.6.3/tests/test_smoke.py +0 -4
- {asecli-0.6.3 → asecli-0.6.4}/.github/workflows/ci.yml +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/.github/workflows/publish.yml +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/.gitignore +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/.project-architect.json +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/AGENTS.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/LICENSE +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/SECURITY.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/audit-supplement.json +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/delivery-protocol.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/project-charter.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/00-governance/supply-chain-policy.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/01-architecture/assumption-experiments.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/01-architecture/project-architecture-and-requirements.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/03-quality/bug-register.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/03-quality/test-strategy.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/04-delivery/roadmap.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-014104-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-014104-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-145343-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-145343-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-193521-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-193521-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-203438-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-01-203438-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-02-121155-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-02-121155-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-02-175509-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-02-175509-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-142617-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-142617-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-160945-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-160945-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-213523-audit-report.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/adversarial-audits/2026-09-05-213523-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/first-principles/2026-08-31-231401-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/docs/first-principles/2026-09-01-190656-optimization-plan.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/skills/asecli/references/master-output-settings-standard.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/skills/asecli/references/material-property-standard.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/__init__.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_editor_port_contract.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_editor_primitives.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_editor_spec_grammar.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_editor_spec_io.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_editor_spec_validation.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_gui_handoff_store.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_gui_project.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_gui_resource_store.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/_gui_resource_upgrade.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/editor_create.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/editor_spec.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/graph_geometry.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/graph_geometry_parser.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/graph_inspect.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_handoff.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_presentation.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_provider_detection.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_runtime_probe.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_support.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/gui_support_resource.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/mcp_client.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/recompile.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resource_text.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.authoring.part00.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.authoring.part01.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.authoring.store.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.condition.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.hydration.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.part00.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.part01.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.reconciliation.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/asecli_material_gui.transaction.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/editor_create.part00.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/editor_create.part01.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/editor_create.part02.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/editor_create.part03.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/editor_create.part04.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/resources/wire_route.transaction.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/bridge/wire_route.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/checks/__init__.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/checks/checksum.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/checks/local_vars.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/checks/usage.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/checks/validate.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/__init__.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/commands.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/commentary_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/create_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/custom_gui_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/gui_provider.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/gui_support_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/io.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/recompile_metadata.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/skill_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/cli/usage_command.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/comment_bounds.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/comment_layout.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/comment_metrics.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/comment_purpose.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/commentary.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/compiled_metadata.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/compiled_properties.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/custom_gui.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/custom_gui_versions.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/fishbone_placement.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/fishbone_topology.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/graph_ops.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/layout.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/layout_audit_geometry.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/layout_audit_repeated.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/layout_graph.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/local_vars.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/material_gui_condition.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/material_gui_protocol.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/material_gui_spec.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/model.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/property_presentation.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/wire_geometry.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/core/wire_router.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/schema/__init__.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/schema/data/observed.json +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/src/asecli/schema/data/schemas.json +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/TEST.md +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/__init__.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/conftest.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/editor_create_v3_fixture.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/fixtures/HLIT.shader +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/fixtures/asecli_material_gui_v0_2_0.cs.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/fixtures/step-antialiasing.function.txt +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_adversarial_hardening.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_audit_fixes.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_bridge_contract.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_bridge_recompile.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_build_reproducibility.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_cli_contract.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_commentary.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_core_contract.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_create.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_custom_gui.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_custom_gui_cli.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_editor_create_bridge.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_editor_create_cli.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_editor_create_e2e.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_editor_create_spec.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_editor_create_spec_v3.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_governance.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_graph_safety.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_gui_handoff.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_gui_native_extension.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_gui_support.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_gui_support_cli_contract.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_gui_upgrade.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_layout.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_layout_governance.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_material_gui_e2e.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_mcp_security.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_mutate.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_perf.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_property_presentation.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_roundtrip.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_schema_add.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_schema_samples.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_skill_install.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_supply_chain.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_usage_audit.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tests/test_wire_route_bridge.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/build_schema.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/check_ci_governance.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/check_document_governance.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/check_packed_executor_loc.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/check_regression_catalog.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/check_release_candidate.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/compare_build_artifacts.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/generate_sbom.py +0 -0
- {asecli-0.6.3 → asecli-0.6.4}/tools/supply_chain_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: asecli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.4
|
|
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
|
|
@@ -124,12 +124,14 @@ curl -fsSL https://raw.githubusercontent.com/seeseeczl/ASECLI/main/scripts/insta
|
|
|
124
124
|
uv tool uninstall asecli
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
当前正式版本为 `0.6.3`(跨 Agent Skill 安装与 MCP 方法体编译兼容修复),可从 [PyPI](https://pypi.org/project/asecli/0.6.3/) 或 [GitHub Release](https://github.com/seeseeczl/ASECLI/releases/tag/v0.6.3) 安装。历史版本见 [GitHub Releases](https://github.com/seeseeczl/ASECLI/releases),`v0.6.2` 保留为回滚点。
|
|
128
128
|
|
|
129
129
|
已知限制:真实 MCP 下,属性+纹理 v2 和 Reciprocal 降级 v2 的 create、manifest、validate、独立 recompile 已通过;SGCLI SphereMask v3 spec 在重载时仍可能返回 `node missing after reload: Radius` 并回滚。本次不承诺该 recipe 端到端可用,也不改变 SGCLI v2 默认值契约。
|
|
130
130
|
|
|
131
131
|
### 源码开发运行
|
|
132
132
|
|
|
133
|
+
工作区新增(尚未发布):转换后的现有 Shader 可用 `asecli graph-review <file> --baseline <backup.shader>` 保守核对计算基线;`--reuse-policy fanout` 显式选择按输出端口两次消费注册的只读计划,默认仍按消费组。`layout --mode meticulous --island-columns 3` 在鱼骨后整体摆放物理独立计算岛。该流程不从旧 JSON 重建图,也不自动创建 Register/Get;详见 [转换后交付流程](skills/asecli/references/conversion-workflow.md)。
|
|
134
|
+
|
|
133
135
|
```bash
|
|
134
136
|
git clone https://github.com/seeseeczl/ASECLI.git
|
|
135
137
|
cd ASECLI
|
|
@@ -100,12 +100,14 @@ curl -fsSL https://raw.githubusercontent.com/seeseeczl/ASECLI/main/scripts/insta
|
|
|
100
100
|
uv tool uninstall asecli
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
当前正式版本为 `0.6.3`(跨 Agent Skill 安装与 MCP 方法体编译兼容修复),可从 [PyPI](https://pypi.org/project/asecli/0.6.3/) 或 [GitHub Release](https://github.com/seeseeczl/ASECLI/releases/tag/v0.6.3) 安装。历史版本见 [GitHub Releases](https://github.com/seeseeczl/ASECLI/releases),`v0.6.2` 保留为回滚点。
|
|
104
104
|
|
|
105
105
|
已知限制:真实 MCP 下,属性+纹理 v2 和 Reciprocal 降级 v2 的 create、manifest、validate、独立 recompile 已通过;SGCLI SphereMask v3 spec 在重载时仍可能返回 `node missing after reload: Radius` 并回滚。本次不承诺该 recipe 端到端可用,也不改变 SGCLI v2 默认值契约。
|
|
106
106
|
|
|
107
107
|
### 源码开发运行
|
|
108
108
|
|
|
109
|
+
工作区新增(尚未发布):转换后的现有 Shader 可用 `asecli graph-review <file> --baseline <backup.shader>` 保守核对计算基线;`--reuse-policy fanout` 显式选择按输出端口两次消费注册的只读计划,默认仍按消费组。`layout --mode meticulous --island-columns 3` 在鱼骨后整体摆放物理独立计算岛。该流程不从旧 JSON 重建图,也不自动创建 Register/Get;详见 [转换后交付流程](skills/asecli/references/conversion-workflow.md)。
|
|
110
|
+
|
|
109
111
|
```bash
|
|
110
112
|
git clone https://github.com/seeseeczl/ASECLI.git
|
|
111
113
|
cd ASECLI
|
|
@@ -41,5 +41,6 @@ evidence: [docs/05-audits/2026-09-01-122217-optimization-tasks.md]
|
|
|
41
41
|
| CR-0025 | 将当前规范分发入口确定为公开 GitHub Release,并把 PyPI 发布延后到具备账号且再次明确授权时 | 交付链 README scripts CI | 一键安装继续解析最新 GitHub Release wheel;PyPI job 默认关闭;不移动既有 tag,不改 CLI 行为,不上 CLI Hub | REG-0021 REG-0057 | 恢复 PyPI 前先配置匹配仓库/workflow/environment 的 Trusted Publisher,再显式启用 job | 用户说明没有 PyPI 账号并明确要求继续 GitHub Release 发布;`v0.6.2` 公开资产、本机安装和回滚已验证 |
|
|
42
42
|
| CR-0026 | 恢复 PyPI 为规范包安装入口,并以 GitHub OIDC Trusted Publishing 上传与 GitHub Release 相同的 `v0.6.2` wheel/sdist | 交付链 README CI PyPI | 设置 `ASECLI_PYPI_ENABLED=true`;Publisher 精确绑定 `seeseeczl/ASECLI`、`publish.yml`、environment `pypi`;不保存或使用 API Token;GitHub Release 入口保持有效 | REG-0021 REG-0052 REG-0057 | 关闭仓库变量并在 PyPI yank 受影响版本;保留 GitHub Release 回滚入口 | 用户取得 PyPI 账号并完成 GitHub 连接后明确要求继续配置;run 34192454152 attempt 3 发布成功,PyPI 匿名摘要与隔离安装通过 |
|
|
43
43
|
| CR-0027 | 将随 wheel 分发的 ASECLI Skill 从 Codex 默认安装扩展为主流 Agent Skills 通用安装 | MOD-CLI MOD-SKILL | 新增 `--agent`、`--scope`、`--project-root`;开放 `.agents/skills` 覆盖 Codex/Cursor/Gemini CLI/GitHub Copilot,Claude Code 使用 `.claude/skills`;无参数与 `--skill-root` 保持兼容;`all` 先检查所有内容冲突 | REG-0058 | 禁用新路由参数即可退回 CR-0015 的 Codex 默认目录;不删除或覆盖已安装 Skill | 定向 46 passed、Skill validator、Project Architect strict 与隔离 wheel 安装通过;BUG-0023 已修复固定片段编译与 SHA 回归;全量 358 passed/3 skipped;发布追溯 REL-0013 |
|
|
44
|
+
| CR-0028 | 补齐 SG JSON 创建后的 ASE 图整理工作流:端口级复用计划、折叠接口计算基线、刚性计算岛排布与分层验收 | MOD-CORE MOD-LAYOUT MOD-CLI MOD-SKILL | 只读 graph-review;fanout 必须显式选择,默认消费组规则不变;island-columns 默认 1;不重建现有 Shader,不修改 SGCLI,不猜动态节点字段 | REG-0060 REG-0061 | 不用新增参数即保留原布局;回退本任务文件增量,不覆盖并行创建器改动;不发布 | 自动验证中;Local Var 自动 Editor 创建未实现,画布/GUI/渲染验收待具体目标,不以只读计划冒充写入 |
|
|
44
45
|
|
|
45
46
|
授权来源:用户于 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 或发布。
|
|
@@ -86,3 +86,6 @@
|
|
|
86
86
|
| 2026-09-08 | v0.6.2 PyPI 发布 | 用户取得 PyPI 账号并授权继续配置;仓库变量 `ASECLI_PYPI_ENABLED=true`,PyPI Pending Publisher 精确绑定 `seeseeczl/ASECLI`、`publish.yml`、environment `pypi`。run 34192454152 attempt 3 全部 job 成功,Pending Publisher 自动转为 Active;PyPI wheel/sdist 摘要与 GitHub Release 一致且 `yanked=false`,官方索引 `uvx` 版本与 parse 通过 | REL-0012 TASK-0058 CR-0023 CR-0026 REG-0021 REG-0052 REG-0057 |
|
|
87
87
|
| 2026-09-08 | 主流 Agent Skill 通用化 | 用户要求将现有 Codex 默认 Skill 改为主流 Agent 通用;新增开放 `.agents` 与 Codex/Claude Code/Cursor/Gemini CLI/GitHub Copilot 原生目录矩阵、用户/项目作用域、`all` 最小覆盖和冲突预检;旧无参数与 `--skill-root` 保持兼容。定向 46 passed、Skill/治理/隔离 wheel 安装通过;当前全量 357 passed/3 skipped/1 failed,唯一失败来自本任务外 C# payload SHA 漂移;未推送或发布 | CR-0027 ADR-0021 TASK-0059 REG-0058 |
|
|
88
88
|
| 2026-09-08 | v0.6.3 发布准备 | 用户授权推送发布;跨 Agent Skill 与 MCP 编译修复纳入补丁版本,SphereMask Radius 重载作为已知限制;保留既有实机证据,运行发布门禁 | REL-0013 CR-0027 BUG-0023 TASK-0060 REG-0058 REG-0059 |
|
|
89
|
+
| 2026-09-08 | v0.6.3 双渠道发布完成 | long 授权;verified → released;tag a758d0f,run 34205409407 双 verify/package/OIDC 全成功;GitHub 五项资产匿名下载摘要与 PyPI 双资产一致;本机官方包 0.6.3、执行片段 SHA、隔离安装/回滚通过。SphereMask Radius 重载限制公开保留,未修改 SGCLI | REL-0013 CR-0027 BUG-0023 TASK-0060 REG-0058 REG-0059 |
|
|
90
|
+
| 2026-09-08 | 转换图交付流程能力补齐 | long 授权补齐 JSON→ASE 后整理缺口;新增 graph-review 计算基线/显式端口复用计划、island-columns 刚性多列排布与 Skill 流程。自动验证通过,未自动创建 Register/Get,未运行真实画布/GUI/渲染验收;全量 380 passed/3 skipped/1 failed(并行 editor_spec.py 行数门禁),未发布 | CR-0028 TASK-0061 TASK-0062 TASK-0063 REG-0060 REG-0061 |
|
|
91
|
+
| 2026-09-08 | v0.6.4 发布授权 | long 要求推送、发布、安装 CLI 与全局 Skill;仅发布 CR-0028 图核对/计算岛布局/Skill,独立暂存快照隔离并行创建器改动;未完成的自动 Local Var 创建和实机验收保持披露 | REL-0014 CR-0028 TASK-0061 TASK-0062 TASK-0063 REG-0060 REG-0061 |
|
|
@@ -58,5 +58,6 @@ CR-0023,变更,已发布,ADR-0019,MOD-CLI,TASK-0052 TASK-0053 TASK-0058,REG-0021
|
|
|
58
58
|
CR-0024,变更,已发布,ADR-0020,MOD-BRIDGE MOD-CLI,TASK-0054 TASK-0058,REG-0053 REG-0057,2026-09-08 自动回归、隔离团结双进程、v0.6.2 GitHub Release 五项资产、本机安装和回滚恢复通过,REL-0012,long,EditorGraphSpec v3 primitive/recipe 与 precision/default/min/max;SGCLI 保持独立
|
|
59
59
|
CR-0025,变更,已被 CR-0026 取代(GitHub 入口保持),ADR-0019,MOD-CLI,TASK-0058,REG-0021 REG-0057,2026-09-08 v0.6.2@7f98356 的公开 GitHub Release、五项资产匿名摘要、本机 CLI/Skill 与隔离回滚恢复通过,REL-0012,long,GitHub Release 入口继续有效;PyPI 临时延后已结束;CLI Hub 不在范围
|
|
60
60
|
CR-0026,变更,已发布,ADR-0019,MOD-CLI,TASK-0058,REG-0021 REG-0052 REG-0057,2026-09-08 Publisher 从 Pending 自动转为 Active;run 34192454152 attempt 3 全成功;PyPI 双资产摘要和官方索引 `uvx` 版本/parse 通过,REL-0012,long,仓库变量启用 OIDC;不保存 API Token;PyPI 为规范包入口且 GitHub Release 保持有效
|
|
61
|
-
CR-0027
|
|
61
|
+
CR-0027,变更,已发布,ADR-0021,MOD-CLI MOD-SKILL,TASK-0059 TASK-0060,REG-0058,2026-09-08 v0.6.3@a758d0f;run 34205409407;双 Python 358 passed/3 skipped;双渠道摘要与安装回滚通过,REL-0013,long,主流 Agent Skill;旧安装兼容
|
|
62
62
|
BUG-0023,缺陷,已修复,ADR-0020,MOD-BRIDGE,TASK-0060,REG-0059,2026-09-08 两类真实 v2 CLI create/manifest/validate/recompile 通过;358 passed/3 skipped,REL-0013,long,方法体兼容 KeyValuePair;SphereMask Radius 重载仍为已知限制
|
|
63
|
+
CR-0028,变更,自动验证完成实机待验,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
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
| 模块 ID | 模块/路径 | 关联 FR/CR | 职责 | 公开 API/事件 | 依赖方向 |
|
|
4
4
|
| --- | --- | --- | --- | --- | --- |
|
|
5
|
-
| MOD-CORE | src/asecli/core | FR-0001 FR-0002 FR-0005 CR-0002 CR-0005 BUG-0002 BUG-0007 BUG-0009 | 行式模型、图块替换、最小差异写回 | `AseFile.from_path`;`parse_graph_text`;`parse_node_line`;`replace_graph` | 仅标准库;禁止依赖 schema/bridge/cli |
|
|
5
|
+
| MOD-CORE | src/asecli/core | FR-0001 FR-0002 FR-0005 CR-0002 CR-0005 BUG-0002 BUG-0007 BUG-0009 CR-0028 | 行式模型、图块替换、最小差异写回 | `AseFile.from_path`;`parse_graph_text`;`parse_node_line`;`replace_graph` | 仅标准库;禁止依赖 schema/bridge/cli |
|
|
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 BUG-0005 BUG-0012 BUG-0013 BUG-0016 BUG-0021 BUG-0023 | MCP 客户端、loopback 信任边界、tool result/envelope、重编译、受控 Editor 图创建、WireNode 路由事务、确定性资源拼装与 GUI 支持升级 | `recompile_via_mcp`;`create_shader_via_mcp`;`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 BUG-0004 BUG-0006 BUG-0008 BUG-0009 BUG-0010 BUG-0013 BUG-0017 BUG-0018 | 16 个命令、单行 JSON、写入/信任组合根、create 后端路由、属性呈现门禁、跨主流 Agent 的受控 Skill 安装与版本化可校验 CI 打包 | `asecli <command>`;`asecli install-skill` | 允许依赖 core/schema/check/bridge;只能使用公开 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 | 通用 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
|
-
| 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 | 兼容分层布局;基于真实端口和直属来源局部输出线的递归鱼骨、Local Var 跨组审计、Comment 保留/收框/作用标题、显式 WireNode 路由计划 | `layout_positions`;`meticulous_layout_positions`;`audit_meticulous_layout`;`plan_wire_routes` | 允许依赖 core 模型;禁止依赖 schema/bridge/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 BUG-0004 BUG-0006 BUG-0008 BUG-0009 BUG-0010 BUG-0013 BUG-0017 BUG-0018 CR-0028 | 16 个命令、单行 JSON、写入/信任组合根、create 后端路由、属性呈现门禁、跨主流 Agent 的受控 Skill 安装与版本化可校验 CI 打包 | `asecli <command>`;`asecli install-skill` | 允许依赖 core/schema/check/bridge;只能使用公开 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 | 通用 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
|
+
| 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 | 兼容分层布局;基于真实端口和直属来源局部输出线的递归鱼骨、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 |
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
|
|
188
188
|
### ADR-0021 使用开放 Agent Skills 目录加 Claude 原生目录覆盖主流 Agent
|
|
189
189
|
|
|
190
|
-
-
|
|
190
|
+
- 状态:已发布,自动与治理验证通过(2026-09-08,CR-0027,REL-0013)
|
|
191
191
|
- 背景:CR-0015 的 Skill 内容本身是标准 Markdown,但安装命令和帮助只默认 Codex 路径,不能让 Claude Code、Cursor、Gemini CLI 与 GitHub Copilot 用户直接选择其原生用户级或项目级目录。
|
|
192
192
|
- 决策:新增 `--agent agents|codex|claude|cursor|gemini|copilot|all`、`--scope user|project` 和 `--project-root`。`.agents/skills` 是 Codex、Cursor、Gemini CLI 与 GitHub Copilot 共同识别的开放目录;Claude Code 另用 `.claude/skills`。因此 `all` 只安装这两个根,避免向每个兼容别名重复复制同名 Skill。单一 Agent 仍可选择其原生目录。
|
|
193
193
|
- 兼容与安全:无参数继续解析 `$CODEX_HOME/skills` 或 `~/.codex/skills`,`--skill-root` 保持显式覆盖。所有目标沿用完整树 digest、幂等、符号链接保护与不同内容拒绝覆盖;`all` 在创建任一目标前预检全部已有 Skill 内容冲突。
|
|
@@ -61,3 +61,5 @@
|
|
|
61
61
|
| REG-0057 | CR-0023 CR-0024 CR-0025 CR-0026 | public-release-install-rollback:`v0.6.2` tag 与版本一致;双 Python、完整治理、可复现构建、摘要、SBOM、供应链、GitHub/PyPI 匿名回读、本机 CLI/Skill、官方 PyPI 隔离安装及 `v0.6.1` 回滚恢复全部闭环 | `python tools/check_release_candidate.py --tag v0.6.2` + tag run 34192454152 attempt 3 + GitHub Release 五项资产与 PyPI JSON 摘要 + `uvx --refresh --index-url https://pypi.org/simple --from asecli==0.6.2` + 正式 wheel 安装/回滚 | 双 Python各 `341 passed, 3 skipped`;`59 parsed / 6 conditional / 0 missed`;GitHub 五项资产一致;PyPI wheel/sdist 摘要与 GitHub 相同、`yanked=false`;本机 `asecli 0.6.2`、Skill 安装/幂等、PyPI 版本/parse 与隔离 `0.6.2 → 0.6.1 → 0.6.2` 通过 |
|
|
62
62
|
| REG-0058 | CR-0027 | mainstream-agent-skill-installation:开放 `.agents` 与 Codex/Claude/Cursor/Gemini/Copilot 用户级和项目级目录矩阵;`all` 以 `.agents` + `.claude` 最小覆盖五类 Agent;无参数/`--skill-root` 向后兼容;同内容幂等、不同内容在任何写入前拒绝 | `uv run --frozen pytest tests/test_skill_install.py tests/test_cli_contract.py tests/test_install_scripts.py` + `skill-creator/scripts/quick_validate.py skills/asecli` + Project Architect strict + `git diff --check` | 定向 46 passed;Skill validator、Project Architect strict 与隔离 wheel 的项目级 `all` 安装/幂等通过;BUG-0023 已修复编译与 SHA 回归;全量 358 passed/3 skipped;真实 MCP 结果见 REG-0059,发布见 REL-0013 |
|
|
63
63
|
| REG-0059 | BUG-0023 | mcp-method-body-compilation:固定片段可用于 MCP Execute 方法体;不使用 System.Tuple/局部类型声明;保留 values;SHA 与行为修复一致 | `uv run --frozen pytest tests/test_editor_create_bridge.py tests/test_editor_create_cli.py` + 真实 MCP 三类 spec create/validate/recompile | 全量 358 passed/3 skipped;两个 v2 spec 实机通过;sphere_mask 编译通过但 Radius 重载失败并回滚,未称为端到端通过 |
|
|
64
|
+
| REG-0060 | CR-0028 | conversion-baseline:来源输出分量、目标端口、Register/Get 等价折叠、错误引用/环/重复输入失败关闭、常量变化拒绝、显式 fanout 与默认消费组策略、既有 Register 幂等复用 | `uv run --frozen pytest tests/test_graph_review.py tests/test_layout_local_var_policy.py` | 定向 94 passed;自动环节已验证;真实历史 Wave Noise 文件只读识别 12 个候选;不声明源 SG 默认值或画面等价 |
|
|
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 工程,实机画布待验 |
|
|
@@ -100,7 +100,10 @@ kickoff_completion: complete
|
|
|
100
100
|
| TASK-0057 | AUD-SIZE-002 | 阻止 C# 预警片段增长并拆分 Editor 资源族 | TASK-0054;确定性资源拼装 | project-architect config;LOC checker;Editor 资源分片;治理测试 | 改单 payload/nonce/rollback;新增永久例外 | TASK-0056/long/2026-09-08 | REG-0056;LOC 负例、拼装 SHA、bridge pytest、隔离 Editor E2E | 拼装字节或真实事务行为变化时回滚分片 | Editor 资源 5 段均低于 250;MaterialGUI 300/290 冻结基线 | 已完成(Editor 实机随 REG-0053) |
|
|
101
101
|
| TASK-0058 | CR-0023 CR-0024 CR-0025 CR-0026 | 发布并安装公开版本 `v0.6.2` | 用户明确要求推送、发布新版本并安装本机,先收敛为 GitHub Release,取得 PyPI 账号后授权继续配置;TASK-0053 TASK-0054 TASK-0057 | `main`、REL-0012、GitHub/PyPI 正式资产、本机 CLI/Skill | CLI Hub;修改生产 Shader;覆盖不同内容 Skill;绕过失败门禁;保存 API Token | TASK-0057/long/2026-09-08 | REG-0057;双 Python全量、完整治理、双构建、远端 verify/package/OIDC publish、双渠道匿名摘要、官方 PyPI 隔离安装、本机安装与 `v0.6.1` 回滚恢复 | 冲突、门禁、OIDC、摘要、匿名回读、安装或回滚任一失败即停止 | `v0.6.2@7f98356`;run 34192454152 attempt 3 全成功;GitHub 五项资产与 PyPI wheel/sdist 摘要一致;本机 CLI/Skill、PyPI `uvx` 与隔离回滚恢复通过;REL-0012 | 已发布 |
|
|
102
102
|
| TASK-0059 | CR-0027 | 将 ASECLI Skill 与安装入口扩展为 Codex、Claude Code、Cursor、Gemini CLI、GitHub Copilot 通用 | 用户要求改成主流 Agent 通用;CR-0015 安全安装基线 | `skill_command.py`、CLI 参数、Skill/README、一键安装脚本、测试与治理追溯 | 覆盖不同内容 Skill;删除旧 Codex 默认;修改 Shader/Editor;推送、tag 或发布 | TASK-0058/long/2026-09-08 | REG-0058;目标矩阵、旧行为、幂等/冲突预检、wheel、Skill validator、完整治理 | 路径未经官方支持、旧调用破坏、冲突后部分内容写入或 Skill 校验失败即回滚 | 定向 46 passed;Skill validator、Project Architect strict、隔离 wheel 安装通过;BUG-0023 已解除编译与 SHA 阻塞,全量 358 passed/3 skipped | 已完成(发布见 TASK-0060/REL-0013) |
|
|
103
|
-
| TASK-0060 | CR-0027 BUG-0023 | 发布 v0.6.3 主流 Agent Skill 与 MCP 编译补丁 | 用户推送发布授权、真实 MCP 证据 | 版本/安装脚本、CLI/Skill、C# 分片、测试、REL-0013 | 修改 SGCLI、覆盖用户 Skill、移动旧 tag | TASK-0059/long/2026-09-08 | REG-0058 REG-0059;双 Python 全量、治理、双构建、远端 CI、双渠道摘要和安装回滚 | CI、摘要或安装失败停止 |
|
|
103
|
+
| TASK-0060 | CR-0027 BUG-0023 | 发布 v0.6.3 主流 Agent Skill 与 MCP 编译补丁 | 用户推送发布授权、真实 MCP 证据 | 版本/安装脚本、CLI/Skill、C# 分片、测试、REL-0013 | 修改 SGCLI、覆盖用户 Skill、移动旧 tag | TASK-0059/long/2026-09-08 | REG-0058 REG-0059;双 Python 全量、治理、双构建、远端 CI、双渠道摘要和安装回滚 | CI、摘要或安装失败停止 | v0.6.3@a758d0f;run 34205409407 全成功;双渠道摘要、正式安装/回滚通过;SphereMask 已知限制;REL-0013 | 已发布 |
|
|
104
|
+
| TASK-0061 | CR-0028 | 核对转换图计算基线及端口级复用计划 | 用户缺口补齐授权 | graph_review.py/reuse_plan.py/core 公共导出/layout_audit.py 与相关测试 | SGCLI、生成 HLSL、猜写 Local Var | long/2026-09-08 | REG-0060;错误端口和常量变化必须失败,默认策略保持 | 折叠丢分量或误吞默认值即停止 | 定向 94 passed;自动环节已验证;只读,不宣称自动创建接口 | 自动验证完成,实机待验 |
|
|
105
|
+
| TASK-0062 | CR-0028 | 独立计算岛刚性多列摆放 | TASK-0061;已有鱼骨与真实几何契约 | island_layout.py/meticulous_layout.py 与测试 | 拆改岛内连接、自动 WireNode 路由、虚构几何 | long/2026-09-08 | REG-0061;相对位置、依赖与二次幂等 | 几何缺失/布局硬失败时零写入 | 定向 94 passed;自动环节已验证;实机待验 | 自动验证完成,实机待验 |
|
|
106
|
+
| TASK-0063 | CR-0028 | 将转换后交付流程接入 CLI 与 Skill | TASK-0061 TASK-0062;用户完整过程 | graph_review_command.py/main.py/layout_command.py;Skill/README/治理 | 发布、覆盖用户 Skill、改并行创建器、生产 Shader | long/2026-09-08 | REG-0060 REG-0061;CLI JSON/只读/失败码、Skill validator | 计划冒充创建或结构冒充视觉时停止 | 定向 94 passed;自动环节已验证;未接入自动 Local Var Editor 创建 | 自动验证完成,实机待验 |
|
|
104
107
|
|
|
105
108
|
## 验证、风险与回滚
|
|
106
109
|
|
|
@@ -112,6 +115,6 @@ kickoff_completion: complete
|
|
|
112
115
|
## 启动完成确认
|
|
113
116
|
|
|
114
117
|
- [x] 上游架构文档已确认且本计划仅从其派生
|
|
115
|
-
- [x]
|
|
118
|
+
- [x] 63 张原子任务卡已定义;本次新增 CR/REG 双向链接完整(实机项保持待验)
|
|
116
119
|
- [x] 里程碑、验收命令、停止条件与回滚已定义
|
|
117
120
|
- [x] 门禁与审计计划已建立
|
|
@@ -32,7 +32,7 @@ else
|
|
|
32
32
|
TAG=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n 1)
|
|
33
33
|
fi
|
|
34
34
|
if [ -z "$TAG" ]; then
|
|
35
|
-
TAG="v0.6.
|
|
35
|
+
TAG="v0.6.4"
|
|
36
36
|
fi
|
|
37
37
|
VERSION=${TAG#v}
|
|
38
38
|
WHEEL="https://github.com/${REPO}/releases/download/${TAG}/asecli-${VERSION}-py3-none-any.whl"
|
|
@@ -7,6 +7,8 @@ description: Create, modify, validate, and strictly lay out Amplify Shader Edito
|
|
|
7
7
|
|
|
8
8
|
当任务涉及节点图新建、转换、整理或验收时,先读取本文引用的“ASE 节点图精排规范”;它是 ASECLI 交付物的一部分,不是临时 Agent 记忆。离线结构检查和真实 ASE 画布视觉验收必须分开报告。
|
|
9
9
|
|
|
10
|
+
从 SG JSON/EditorGraphSpec 创建或整理转换图时,还必须读取 [转换后图交付流程](references/conversion-workflow.md)。以当前 Shader 为基线,先 `graph-review` 锁定计算连接/常量,再处理复用、递归鱼骨与计算岛;不得把 JSON 初排或创建成功当作完成。`graph-review` 是只读计划与对照,不是自动 Local Var 创建器。用户明确指定按输出端口两次消费注册时,用 `--reuse-policy fanout` 覆盖本任务默认门槛,不修改其他任务的消费组策略。
|
|
11
|
+
|
|
10
12
|
## Agent 兼容性
|
|
11
13
|
|
|
12
14
|
本 Skill 遵循通用 Agent Skills 目录结构:标准 YAML frontmatter、`SKILL.md` 正文和相对路径引用。它只要求 Agent 能运行本地 shell 命令并读取 ASECLI 的单行 JSON,不依赖 Codex、Claude Code、Cursor、Gemini CLI 或 GitHub Copilot 的专属工具名、权限模型或消息格式。
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# SG 转换后 ASE 图交付流程
|
|
2
|
+
|
|
3
|
+
适用:从 SG 导出的 JSON 经 EditorGraphSpec 创建 ASE 图,或整理这类现有 Shader。源 JSON、创建规格和当前 `.shader` 是三层不同资产。创建规格中的拓扑分列只是初排;以最新已确认效果正确的 Shader 为基线,不能用旧规格覆盖它。
|
|
4
|
+
|
|
5
|
+
## 先锁定语义,再整理
|
|
6
|
+
|
|
7
|
+
- 将当前 Shader 复制为唯一备份,记录 SHA-256;不复用会被后续命令覆盖的 `.bak` 作为整个任务的永久基线。
|
|
8
|
+
- 运行 `asecli graph-review <shader> --reuse-policy consumer-groups`,保留单行 JSON 结果。它保留非布局节点原始字段、精度/常量/纹理引用/不透明 Master 数据,并按来源输出端口折叠 Register/Get/WireNode。输出可达节点、无连接 Master 与输出外保留支路分别列出,输出外节点不是删除许可。
|
|
9
|
+
- SG 转换时还必须检查未连输入的真实默认值、向量宽度、子图绑定、空间变换、噪声算法、混合状态,以及当前 SG Editor 生成的 HLSL。ASE 快照不知道源 SG 默认值,不能代替这项对照。未知默认值格式应回到转换端报错,禁止补零;不要通过改生成 HLSL、为 pow 加 abs/clamp/Saturate 来掩盖差异。
|
|
10
|
+
- 编辑完运行 `asecli graph-review <shader> --baseline <唯一备份.shader>`。`computation_equal=false` 必须解释并修复;`generated_source_equal` 是生成源码整体摘要,不是语义等价证明。GUI 元数据和真实再生成造成的源码变化应单独审查,不能删除比较门禁或声称摘要相等就是画面相同。
|
|
11
|
+
|
|
12
|
+
## 明确复用策略,保留真实接口
|
|
13
|
+
|
|
14
|
+
默认 `consumer-groups` 仍按不同消费组判断。仅当用户明确要求“同一输出使用两次就注册”时,使用 `--reuse-policy fanout`。门槛按 `(来源节点 ID, 输出端口)`,不是节点 ID;例如 RGB、R、A 不能混计。
|
|
15
|
+
|
|
16
|
+
`graph-review` 是只读计划,不会创建 Register/Get。计划列出使用次数、真实目标端口、消费组、现有 Register 与需替换的直接消费者。已有正确接口保持不动;部分接入时复用已有 Register,不再新建同名注册。复杂 WireNode/嵌套接口计划需要人工核对,不把它直接当成写入规格。
|
|
17
|
+
|
|
18
|
+
落实计划时通过当前 ASE Editor API 创建动态节点,或使用本版本、本类型已核验的真实样本;不能猜序列化。先给结果确定稳定语义名,生产者右侧注册、每个消费者左侧就近 Get,保留精度/数据类型和源输出分量。操作后立即用 `graph-review --baseline` 核对折叠后的计算连接,多一条、少一条或端口变化均不放行。无法获得安全创建能力时明确报告未完成,不只输出计划就宣称已治理。
|
|
19
|
+
|
|
20
|
+
## 递归鱼骨,然后摆放独立岛
|
|
21
|
+
|
|
22
|
+
- 复用已运行 Editor,一次获取节点矩形、标题和已连接端口真实几何。从实际连接的 Output 端口反查各直接来源,每个消费者都是一个局部终点。全局深度与创建顺序不能决定所有节点的列、行。
|
|
23
|
+
- 使用 `layout --mode meticulous`:主要输入沿水平主骨,余下完整子树按输入端口顺序分配上下空间;按端口 y 对齐。父子边界目标 96px,通常 64–160px;兄弟至少 32px、跨模块至少 96px。调整完整子树包围盒,不整体倍增所有 y。
|
|
24
|
+
- 如果本地变量已断开大量长线,使用 `asecli layout <shader> --mode meticulous --island-columns 3 --audit --mcp-url <URL>` 预演;无硬失败后同参数改 `--write`。列数可为 2–8,默认 1 保持旧行为。计算岛内部只做整体平移,按 Register/Get 逻辑依赖及语义标题排序,输出在右;不按最小节点 ID 排版。
|
|
25
|
+
- 包装保留 Comment 归属和跨物理岛的框;不会拆开一个已有框的成员。含固定 WireNode 的多列摆放目前失败关闭,不自动搬动锚点,也不自动开启 `--route-wires`。需要独立路由授权和验收。
|
|
26
|
+
- 几何只可在同一未变化的图、相同显示名/节点类型/端口集合下复用。新增接口或改名导致尺寸改变后重新测量;不得拿旧缓存冒充新节点的真实尺寸。先完成全部候选修改,再集中 Editor 验证,不反复重启 Editor。
|
|
27
|
+
|
|
28
|
+
## 说明与 GUI 放在布局之后
|
|
29
|
+
|
|
30
|
+
先稳定节点,再以原生 `comment-group` 添加紧密算法单元的中文标题、短说明;不为凑组数框全部上游。保留支路注明是否影响当前输出。按最终标题与节点真实尺寸收框,左右/底部通常 30px、顶部至少 48px;同级重叠必须拆分或缩小语义范围,不能忽略错误。
|
|
31
|
+
|
|
32
|
+
`gui-support` 确认唯一 provider 后,用一份 `custom-gui --spec` 批量配置:每组首项 Foldout,中文显示名、功能排序与 Tooltip;保留英文变量名、类型、默认值、范围、HDR、纹理绑定和材质兼容性。名字和用途来自真实消费者,向量注明 XY/ZW、颜色注明 Alpha,未启用/未接入参数说明当前无效。变量名与默认值由 GUI 自动追加;默认不添加 HelpBox。
|
|
33
|
+
|
|
34
|
+
## 分层验收,不能互相代替
|
|
35
|
+
|
|
36
|
+
1. **结构**:折叠接口后的计算端口/连接、常量、精度、属性、Master 保持;Comment 无越界/同级重叠;属性契约 `valid=true, violations=[]`;Checksum 正确。新命令的基线比较故意保守,修改 GUI 后会报告节点字段变化,需结合原有属性契约核对。
|
|
37
|
+
2. **Editor**:经真实 ASE 生成、导入并独立重载;MCP 超时先核对目标与暂存状态,禁止盲目重试。
|
|
38
|
+
3. **画布/GUI**:正常阅读缩放下看代表鱼骨、重复分支、长线、所有分组;连线只在明确空白通道交叉,不穿无关节点/标题;展开、收起并真实悬停提示。
|
|
39
|
+
4. **效果**:新转换图在相同材质参数、模型、镜头、光照和时间下对照 SG 与 ASE。公开属性相同、编译成功、151 条计算连接一致等结构证据不能代替画面对比。
|
|
40
|
+
|
|
41
|
+
分别报告通过、失败、未执行。历史 Wave Noise 的说明框阶段仅有尺寸及 GUI 静态契约证据,不能沿用为悬浮交互和完整正常缩放验收。数字如 12 Register、27 Get、19 框和 14 属性只属于历史样本,不是通用目标。
|
|
@@ -52,6 +52,8 @@ ASE 节点图必须呈现出“经过人工精心排列”的秩序感:严格
|
|
|
52
52
|
|
|
53
53
|
Local Var 的强制门槛是“不同消费组数量”,不是 Wire 数量。治理时记录以下三个维度:
|
|
54
54
|
|
|
55
|
+
这是默认策略。用户显式要求按同一输出端口两次消费注册时,本任务使用 `graph-review --reuse-policy fanout`,按 `(node_id, out_port)` 计数,覆盖下述默认门槛;该只读计划不自动创建节点。
|
|
56
|
+
|
|
55
57
|
1. **语义边界**:生产者与消费者是否属于不同算法模块或不同 Comment 组。坐标相隔较远但仍属于同一局部算法,不算跨模块。
|
|
56
58
|
2. **消费组数量**:按去重后的 Comment/算法组计数;同组内一个或多个消费者都只算一个消费组。达到两个及以上消费组时必须注册。
|
|
57
59
|
3. **走线证据**:记录跨阶段、左右回折和穿越无关节点、Comment 内容区、标题栏或端口密集区的情况,用于优化布局和放置 Get,不得用像素长度替代消费组判断。
|
|
@@ -69,13 +71,15 @@ Local Var 的强制门槛是“不同消费组数量”,不是 Wire 数量。
|
|
|
69
71
|
## 执行顺序
|
|
70
72
|
|
|
71
73
|
1. 找出 Master Output、主数据链和所有双扇出/长线候选;记录来源、消费者、模块归属和跨阶段数。
|
|
72
|
-
2.
|
|
74
|
+
2. 从每个实际连接的 Output 反向建立局部主链,再递归摆放完整上游子树;不以全图深度统一横坐标,不以创建顺序决定纵向顺序。
|
|
73
75
|
3. 套用重复分支模板,再把辅助输入贴近消费者排列。
|
|
74
76
|
4. 调整行距、列距和组间留白,先用自然直连解决局部复用;只有显式 `--route-wires` 才移动已有 WireNode,并在确有改进时增加最少锚点,使线线交叉尽量为零且不出现线路重叠。
|
|
75
77
|
5. 按 Local Var 决策门槛复核候选:两个及以上消费组必须注册,同组内多次使用保持直连;已有 Register 的模块外直连必须收口到就近 Get。
|
|
76
78
|
6. 检查改造前后消费者端口、数据类型和计算语义完全一致,再减少不必要的线与线交叉。
|
|
77
79
|
7. 最后创建或校正 Comment,检查组间不重叠和父子组完整包含。
|
|
78
80
|
|
|
81
|
+
复用接口稳定且局部鱼骨完成后,可用 `--island-columns 3` 对物理独立岛整体摆放,保留岛内相对坐标,按逻辑依赖及语义标签排序。Register/Get 无物理线但仍有逻辑关系。不要把岛重新塞回全局深度列。完整转换流程与验收见 [转换后图交付流程](conversion-workflow.md)。
|
|
82
|
+
|
|
79
83
|
## 验收边界
|
|
80
84
|
|
|
81
85
|
离线测试可以证明:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Read-only baseline and explicit reuse-policy review of an existing Shader."""
|
|
2
|
+
|
|
3
|
+
from ..core import graph_baseline, compare_graph_baselines, plan_local_var_reuse
|
|
4
|
+
from .commands import CliError, _load
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def cmd_graph_review(args):
|
|
8
|
+
shader = _load(args.file)
|
|
9
|
+
try:
|
|
10
|
+
baseline = graph_baseline(shader)
|
|
11
|
+
comparison = None
|
|
12
|
+
if args.baseline:
|
|
13
|
+
comparison = compare_graph_baselines(graph_baseline(_load(args.baseline)), baseline)
|
|
14
|
+
if not comparison['computation_equal']:
|
|
15
|
+
raise CliError('SEMANTIC_MISMATCH', 'graph differs from the baseline; review required',
|
|
16
|
+
{'comparison': comparison, 'written': False})
|
|
17
|
+
return {
|
|
18
|
+
'file': args.file, 'written': False, 'baseline': baseline,
|
|
19
|
+
'reuse_plan': plan_local_var_reuse(shader.graph, policy=args.reuse_policy),
|
|
20
|
+
'comparison': comparison,
|
|
21
|
+
'acceptance': {'structure': 'reviewed', 'editor_compile': 'not_run',
|
|
22
|
+
'canvas_gui': 'not_run', 'render_equivalence': 'not_verified'},
|
|
23
|
+
}
|
|
24
|
+
except ValueError as exc:
|
|
25
|
+
raise CliError('GRAPH_REVIEW_ERROR', str(exc)) from exc
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import hashlib
|
|
6
|
+
import argparse
|
|
6
7
|
import json
|
|
7
8
|
import os
|
|
8
9
|
|
|
@@ -25,8 +26,29 @@ from .commands import CliError, _commit_text, _load, _save
|
|
|
25
26
|
from .io import restore_from_backup
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
def configure_layout_parser(sub):
|
|
30
|
+
s = sub.add_parser("layout", help="auto-arrange nodes using legacy or meticulous DAG layout")
|
|
31
|
+
s.add_argument("file")
|
|
32
|
+
s.add_argument("--mode", choices=("legacy", "meticulous"), default="legacy")
|
|
33
|
+
s.add_argument("--audit", action="store_true", help="report meticulous layout quality without writing")
|
|
34
|
+
s.add_argument("--island-columns", type=int, choices=range(1, 9), default=1,
|
|
35
|
+
help="pack physical calculation islands into columns after recursive fishbone layout")
|
|
36
|
+
s.add_argument("--route-wires", action="store_true",
|
|
37
|
+
help="explicitly allow meticulous mode to move or add WireNode routing anchors")
|
|
38
|
+
s.add_argument("--gap-x", type=float, default=280.0)
|
|
39
|
+
s.add_argument("--gap-y", type=float, default=120.0)
|
|
40
|
+
s.add_argument("--mcp-url", default="http://127.0.0.1:8080/mcp")
|
|
41
|
+
s.add_argument("--unity-instance", help="target Name@hash when multiple Unity/Tuanjie instances are connected")
|
|
42
|
+
s.add_argument("--allow-remote-mcp", action="store_true")
|
|
43
|
+
s.add_argument("--instance-token", dest="instance_token_argv", help=argparse.SUPPRESS)
|
|
44
|
+
s.add_argument("--write", action="store_true")
|
|
45
|
+
s.set_defaults(func=cmd_layout)
|
|
46
|
+
|
|
47
|
+
|
|
28
48
|
def cmd_layout(args) -> dict:
|
|
29
49
|
if args.mode == "legacy":
|
|
50
|
+
if getattr(args, "island_columns", 1) != 1:
|
|
51
|
+
raise CliError("USAGE_ERROR", "--island-columns requires --mode meticulous")
|
|
30
52
|
if args.route_wires:
|
|
31
53
|
raise CliError("USAGE_ERROR", "--route-wires requires --mode meticulous")
|
|
32
54
|
if args.audit:
|
|
@@ -61,7 +83,10 @@ def _meticulous(args) -> dict:
|
|
|
61
83
|
unity_instance=args.unity_instance,
|
|
62
84
|
allow_remote_mcp=args.allow_remote_mcp,
|
|
63
85
|
)
|
|
64
|
-
plan = meticulous_layout_positions(
|
|
86
|
+
plan = meticulous_layout_positions(
|
|
87
|
+
f.graph, geometry, route_wires=args.route_wires,
|
|
88
|
+
island_columns=getattr(args, "island_columns", 1),
|
|
89
|
+
)
|
|
65
90
|
moved = apply_meticulous_layout(f.graph, plan)
|
|
66
91
|
# Audit/dry-run reports a proposed title without mutating the in-memory
|
|
67
92
|
# graph. Only an explicitly authorized write may persist the title.
|
|
@@ -155,6 +180,7 @@ def _meticulous(args) -> dict:
|
|
|
155
180
|
"comment_changed_count": len(comment_changes),
|
|
156
181
|
"comment_purpose": comment_purpose,
|
|
157
182
|
"route_wires": bool(args.route_wires),
|
|
183
|
+
"islands": list(plan.islands),
|
|
158
184
|
"wire_route_transaction": route_transaction,
|
|
159
185
|
"audit_only": bool(args.audit),
|
|
160
186
|
"audit": report,
|
|
@@ -26,7 +26,8 @@ from .gui_support_command import cmd_gui_support
|
|
|
26
26
|
from .commentary_command import cmd_comment_group
|
|
27
27
|
from .skill_command import AGENT_CHOICES, SCOPE_CHOICES, cmd_install_skill
|
|
28
28
|
from .usage_command import cmd_graph_audit, cmd_remove_node
|
|
29
|
-
from .layout_command import
|
|
29
|
+
from .layout_command import configure_layout_parser
|
|
30
|
+
from .graph_review_command import cmd_graph_review
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class JsonArgumentParser(argparse.ArgumentParser):
|
|
@@ -97,22 +98,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
97
98
|
s.add_argument("--write", action="store_true")
|
|
98
99
|
s.set_defaults(func=cmd_fix_checksum)
|
|
99
100
|
|
|
100
|
-
s = sub.add_parser("
|
|
101
|
+
s = sub.add_parser("graph-review", help="read-only computation baseline and Local Var reuse plan")
|
|
101
102
|
s.add_argument("file")
|
|
102
|
-
s.add_argument("--
|
|
103
|
-
s.add_argument("--
|
|
104
|
-
s.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
)
|
|
108
|
-
s.add_argument("--gap-x", type=float, default=280.0)
|
|
109
|
-
s.add_argument("--gap-y", type=float, default=120.0)
|
|
110
|
-
s.add_argument("--mcp-url", default="http://127.0.0.1:8080/mcp")
|
|
111
|
-
s.add_argument("--unity-instance", help="target Name@hash when multiple Unity/Tuanjie instances are connected")
|
|
112
|
-
s.add_argument("--allow-remote-mcp", action="store_true")
|
|
113
|
-
s.add_argument("--instance-token", dest="instance_token_argv", help=argparse.SUPPRESS)
|
|
114
|
-
s.add_argument("--write", action="store_true")
|
|
115
|
-
s.set_defaults(func=cmd_layout)
|
|
103
|
+
s.add_argument("--baseline", help="original Shader backup for conservative semantic comparison")
|
|
104
|
+
s.add_argument("--reuse-policy", choices=("consumer-groups", "fanout"), default="consumer-groups")
|
|
105
|
+
s.set_defaults(func=cmd_graph_review)
|
|
106
|
+
|
|
107
|
+
configure_layout_parser(sub)
|
|
116
108
|
|
|
117
109
|
s = sub.add_parser("custom-gui", help="inspect or edit CustomEditor and MZGUI-compatible property metadata")
|
|
118
110
|
s.add_argument("file")
|
|
@@ -49,6 +49,9 @@ from .local_vars import (
|
|
|
49
49
|
parse_register_local_var,
|
|
50
50
|
)
|
|
51
51
|
from .wire_router import WIRE_NODE_TYPE, logical_wire_manifest
|
|
52
|
+
from .graph_review import computation_wires, graph_baseline, compare_graph_baselines
|
|
53
|
+
from .reuse_plan import plan_local_var_reuse
|
|
54
|
+
from .island_layout import pack_calculation_islands
|
|
52
55
|
from .material_gui_spec import apply_material_gui_spec, material_property_nodes, resolve_property_node
|
|
53
56
|
from .material_gui_condition import (
|
|
54
57
|
ENABLE_IF_ATTRIBUTE,
|
|
@@ -81,4 +84,6 @@ __all__ = [
|
|
|
81
84
|
"GET_LOCAL_VAR_TYPE", "REGISTER_LOCAL_VAR_TYPE", "local_var_edges",
|
|
82
85
|
"parse_get_local_var", "parse_register_local_var",
|
|
83
86
|
"WIRE_NODE_TYPE", "logical_wire_manifest",
|
|
87
|
+
"computation_wires", "graph_baseline", "compare_graph_baselines",
|
|
88
|
+
"plan_local_var_reuse", "pack_calculation_islands",
|
|
84
89
|
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Conservative, port-exact baselines for post-conversion graph editing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
|
|
8
|
+
from .commentary import COMMENTARY_TYPE
|
|
9
|
+
from .layout import MASTER_TYPES
|
|
10
|
+
from .local_vars import (
|
|
11
|
+
GET_LOCAL_VAR_TYPE, REGISTER_LOCAL_VAR_TYPE,
|
|
12
|
+
parse_get_local_var, parse_register_local_var,
|
|
13
|
+
)
|
|
14
|
+
from .wire_router import WIRE_NODE_TYPE
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def computation_wires(graph):
|
|
18
|
+
"""Collapse interfaces, never discard an output component or infer a default."""
|
|
19
|
+
nodes = {n.node_id: n for n in graph.nodes}
|
|
20
|
+
if len(nodes) != len(graph.nodes):
|
|
21
|
+
raise ValueError("duplicate node IDs")
|
|
22
|
+
incoming = {}
|
|
23
|
+
for w in graph.wires:
|
|
24
|
+
if w.in_node not in nodes or w.out_node not in nodes:
|
|
25
|
+
raise ValueError("dangling wire endpoint")
|
|
26
|
+
key = (w.in_node, w.in_port)
|
|
27
|
+
if key in incoming:
|
|
28
|
+
raise ValueError(f"multiple connections to input {key}")
|
|
29
|
+
incoming[key] = (w.out_node, w.out_port)
|
|
30
|
+
|
|
31
|
+
def resolve(node_id, port, visiting=()):
|
|
32
|
+
key = (node_id, port)
|
|
33
|
+
if key in visiting:
|
|
34
|
+
raise ValueError("Local Var / WireNode interface cycle")
|
|
35
|
+
node = nodes[node_id]
|
|
36
|
+
if node.type_name == GET_LOCAL_VAR_TYPE:
|
|
37
|
+
item = parse_get_local_var(node)
|
|
38
|
+
register = nodes.get(item['register_id'])
|
|
39
|
+
if register is None or register.type_name != REGISTER_LOCAL_VAR_TYPE:
|
|
40
|
+
raise ValueError(f"Get {node_id} has no valid Register")
|
|
41
|
+
reference = parse_register_local_var(register)
|
|
42
|
+
if any(item[k] != reference[k] for k in ('name', 'data_type')):
|
|
43
|
+
raise ValueError(f"Get {node_id} name/type differs from Register")
|
|
44
|
+
if port != '0':
|
|
45
|
+
raise ValueError("unsupported Get output component; refusing to collapse")
|
|
46
|
+
return resolve(register.node_id, '0', visiting + (key,))
|
|
47
|
+
if node.type_name in {REGISTER_LOCAL_VAR_TYPE, WIRE_NODE_TYPE}:
|
|
48
|
+
if port != '0' or (node_id, '0') not in incoming:
|
|
49
|
+
raise ValueError(f"unsupported or unconnected interface {node_id}:{port}")
|
|
50
|
+
return resolve(*incoming[(node_id, '0')], visiting + (key,))
|
|
51
|
+
return key
|
|
52
|
+
|
|
53
|
+
interfaces = {GET_LOCAL_VAR_TYPE, REGISTER_LOCAL_VAR_TYPE, WIRE_NODE_TYPE}
|
|
54
|
+
# Validate dormant interface references too; they are not disposable nodes.
|
|
55
|
+
for node in graph.nodes:
|
|
56
|
+
if node.type_name in interfaces:
|
|
57
|
+
resolve(node.node_id, '0')
|
|
58
|
+
return sorted(
|
|
59
|
+
(*resolve(w.out_node, w.out_port), w.in_node, w.in_port)
|
|
60
|
+
for w in graph.wires if nodes[w.in_node].type_name not in interfaces
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def graph_baseline(shader):
|
|
65
|
+
"""Keep all non-layout fields, including opaque defaults and Master settings."""
|
|
66
|
+
interfaces = {GET_LOCAL_VAR_TYPE, REGISTER_LOCAL_VAR_TYPE, WIRE_NODE_TYPE, COMMENTARY_TYPE}
|
|
67
|
+
nodes = {}
|
|
68
|
+
for node in shader.graph.nodes:
|
|
69
|
+
if node.type_name not in interfaces:
|
|
70
|
+
fields = list(node.raw_fields)
|
|
71
|
+
fields[3] = '<position>'
|
|
72
|
+
nodes[node.node_id] = fields
|
|
73
|
+
wires = computation_wires(shader.graph)
|
|
74
|
+
predecessors = defaultdict(set)
|
|
75
|
+
for source, _, target, _ in wires:
|
|
76
|
+
predecessors[target].add(source)
|
|
77
|
+
masters = sorted(n.node_id for n in shader.graph.nodes if n.type_name in MASTER_TYPES)
|
|
78
|
+
active = [n for n in masters if predecessors[n]]
|
|
79
|
+
reachable, stack = set(active), list(active)
|
|
80
|
+
while stack:
|
|
81
|
+
for source in predecessors[stack.pop()]:
|
|
82
|
+
if source not in reachable:
|
|
83
|
+
reachable.add(source)
|
|
84
|
+
stack.append(source)
|
|
85
|
+
return {
|
|
86
|
+
'schema': 'asecli.graph-baseline.v1', 'ase_version': shader.graph.version,
|
|
87
|
+
'source_sha256': shader.source_digest or hashlib.sha256(shader.serialize().encode()).hexdigest(),
|
|
88
|
+
'nodes': nodes, 'computation_wires': wires,
|
|
89
|
+
'active_outputs': active, 'dormant_outputs': sorted(set(masters) - set(active)),
|
|
90
|
+
'output_reachable': sorted(reachable),
|
|
91
|
+
'retained_off_output': sorted(set(nodes) - reachable - set(masters)),
|
|
92
|
+
'generated_source_sha256': hashlib.sha256(shader.prefix.encode()).hexdigest(),
|
|
93
|
+
'limits': 'Raw node fields are protected; this does not prove SG defaults or rendering equivalence.',
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def compare_graph_baselines(before, after):
|
|
98
|
+
changed = [k for k in ('ase_version', 'nodes', 'computation_wires') if before[k] != after[k]]
|
|
99
|
+
return {
|
|
100
|
+
'computation_equal': not changed, 'changed_sections': changed,
|
|
101
|
+
'generated_source_equal': before['generated_source_sha256'] == after['generated_source_sha256'],
|
|
102
|
+
'render_equivalence': 'not_verified',
|
|
103
|
+
'note': 'GUI metadata changes are conservatively reported as node changes; review explicitly.',
|
|
104
|
+
}
|