create-yss-spec 3.4.5 → 3.4.6
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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/yss-application/SKILL.md +8 -6
- package/template/.agents/skills/yss-audit-log/SKILL.md +12 -7
- package/template/.agents/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
- package/template/.agents/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
- package/template/.agents/skills/yss-audit-log/references/source-index.md +6 -39
- package/template/.agents/skills/yss-cache/SKILL.md +5 -1
- package/template/.agents/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
- package/template/.agents/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
- package/template/.agents/skills/yss-cache/references/source-index.md +6 -63
- package/template/.agents/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
- package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.agents/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
- package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
- package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
- package/template/.agents/skills/yss-distributed-id/SKILL.md +4 -0
- package/template/.agents/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
- package/template/.agents/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
- package/template/.agents/skills/yss-distributed-id/references/source-index.md +6 -82
- package/template/.agents/skills/yss-dto/SKILL.md +2 -2
- package/template/.agents/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
- package/template/.agents/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
- package/template/.agents/skills/yss-dto/references/source-index.md +6 -51
- package/template/.agents/skills/yss-excel-mvc/SKILL.md +4 -0
- package/template/.agents/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
- package/template/.agents/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
- package/template/.agents/skills/yss-excel-mvc/references/source-index.md +6 -70
- package/template/.agents/skills/yss-exception/SKILL.md +12 -9
- package/template/.agents/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
- package/template/.agents/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
- package/template/.agents/skills/yss-exception/references/source-index.md +6 -31
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
- package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
- package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
- package/template/.agents/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
- package/template/.agents/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
- package/template/.agents/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
- package/template/.agents/skills/yss-mvc-design/SKILL.md +5 -9
- package/template/.agents/skills/yss-mvc-design/agents/openai.yaml +3 -3
- package/template/.agents/skills/yss-mybatis/SKILL.md +2 -2
- package/template/.agents/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
- package/template/.agents/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
- package/template/.agents/skills/yss-mybatis/references/source-index.md +6 -109
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.agents/skills/yss-repository/SKILL.md +1 -1
- package/template/.agents/skills/yss-resilience4j/SKILL.md +4 -0
- package/template/.agents/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
- package/template/.agents/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
- package/template/.agents/skills/yss-resilience4j/references/source-index.md +6 -29
- package/template/.agents/skills/yss-security-algorithm/SKILL.md +34 -10
- package/template/.agents/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
- package/template/.agents/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
- package/template/.agents/skills/yss-security-algorithm/references/source-index.md +6 -31
- package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
- package/template/.agents/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
- package/template/.agents/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
- package/template/.agents/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
- package/template/.agents/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.agents/skills/yss-tactical-design/references/output-template.md +1 -1
- package/template/.agents/skills/yss-technical-design/SKILL.md +3 -1
- package/template/.agents/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.agents/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
- package/template/.agents/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
- package/template/.agents/skills/yss-up-springboot3/SKILL.md +23 -9
- package/template/.agents/skills/yss-userinfo/SKILL.md +21 -14
- package/template/.agents/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
- package/template/.agents/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
- package/template/.agents/skills/yss-userinfo/references/source-index.md +6 -30
- package/template/.agents/skills/yss-validation/SKILL.md +12 -17
- package/template/.agents/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
- package/template/.agents/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
- package/template/.agents/skills/yss-validation/references/source-index.md +6 -29
- package/template/.agents/skills/yss-web-controller/SKILL.md +4 -4
- package/template/.agents/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
- package/template/.codex/skills/yss-application/SKILL.md +8 -6
- package/template/.codex/skills/yss-audit-log/SKILL.md +12 -7
- package/template/.codex/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
- package/template/.codex/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
- package/template/.codex/skills/yss-audit-log/references/source-index.md +6 -39
- package/template/.codex/skills/yss-cache/SKILL.md +5 -1
- package/template/.codex/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
- package/template/.codex/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
- package/template/.codex/skills/yss-cache/references/source-index.md +6 -63
- package/template/.codex/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
- package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.codex/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
- package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
- package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
- package/template/.codex/skills/yss-distributed-id/SKILL.md +4 -0
- package/template/.codex/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
- package/template/.codex/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
- package/template/.codex/skills/yss-distributed-id/references/source-index.md +6 -82
- package/template/.codex/skills/yss-dto/SKILL.md +2 -2
- package/template/.codex/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
- package/template/.codex/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
- package/template/.codex/skills/yss-dto/references/source-index.md +6 -51
- package/template/.codex/skills/yss-excel-mvc/SKILL.md +4 -0
- package/template/.codex/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
- package/template/.codex/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
- package/template/.codex/skills/yss-excel-mvc/references/source-index.md +6 -70
- package/template/.codex/skills/yss-exception/SKILL.md +12 -9
- package/template/.codex/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
- package/template/.codex/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
- package/template/.codex/skills/yss-exception/references/source-index.md +6 -31
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
- package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
- package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
- package/template/.codex/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
- package/template/.codex/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
- package/template/.codex/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
- package/template/.codex/skills/yss-mvc-design/SKILL.md +5 -9
- package/template/.codex/skills/yss-mvc-design/agents/openai.yaml +3 -3
- package/template/.codex/skills/yss-mybatis/SKILL.md +2 -2
- package/template/.codex/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
- package/template/.codex/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
- package/template/.codex/skills/yss-mybatis/references/source-index.md +6 -109
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.codex/skills/yss-repository/SKILL.md +1 -1
- package/template/.codex/skills/yss-resilience4j/SKILL.md +4 -0
- package/template/.codex/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
- package/template/.codex/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
- package/template/.codex/skills/yss-resilience4j/references/source-index.md +6 -29
- package/template/.codex/skills/yss-security-algorithm/SKILL.md +34 -10
- package/template/.codex/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
- package/template/.codex/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
- package/template/.codex/skills/yss-security-algorithm/references/source-index.md +6 -31
- package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
- package/template/.codex/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
- package/template/.codex/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
- package/template/.codex/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
- package/template/.codex/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.codex/skills/yss-tactical-design/references/output-template.md +1 -1
- package/template/.codex/skills/yss-technical-design/SKILL.md +3 -1
- package/template/.codex/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.codex/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
- package/template/.codex/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
- package/template/.codex/skills/yss-up-springboot3/SKILL.md +23 -9
- package/template/.codex/skills/yss-userinfo/SKILL.md +21 -14
- package/template/.codex/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
- package/template/.codex/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
- package/template/.codex/skills/yss-userinfo/references/source-index.md +6 -30
- package/template/.codex/skills/yss-validation/SKILL.md +12 -17
- package/template/.codex/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
- package/template/.codex/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
- package/template/.codex/skills/yss-validation/references/source-index.md +6 -29
- package/template/.codex/skills/yss-web-controller/SKILL.md +4 -4
- package/template/.codex/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
- package/template/.cursor/skills/yss-application/SKILL.md +8 -6
- package/template/.cursor/skills/yss-audit-log/SKILL.md +12 -7
- package/template/.cursor/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
- package/template/.cursor/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
- package/template/.cursor/skills/yss-audit-log/references/source-index.md +6 -39
- package/template/.cursor/skills/yss-cache/SKILL.md +5 -1
- package/template/.cursor/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
- package/template/.cursor/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
- package/template/.cursor/skills/yss-cache/references/source-index.md +6 -63
- package/template/.cursor/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
- package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.cursor/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
- package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
- package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
- package/template/.cursor/skills/yss-distributed-id/SKILL.md +4 -0
- package/template/.cursor/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
- package/template/.cursor/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
- package/template/.cursor/skills/yss-distributed-id/references/source-index.md +6 -82
- package/template/.cursor/skills/yss-dto/SKILL.md +2 -2
- package/template/.cursor/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
- package/template/.cursor/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
- package/template/.cursor/skills/yss-dto/references/source-index.md +6 -51
- package/template/.cursor/skills/yss-excel-mvc/SKILL.md +4 -0
- package/template/.cursor/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
- package/template/.cursor/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
- package/template/.cursor/skills/yss-excel-mvc/references/source-index.md +6 -70
- package/template/.cursor/skills/yss-exception/SKILL.md +12 -9
- package/template/.cursor/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
- package/template/.cursor/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
- package/template/.cursor/skills/yss-exception/references/source-index.md +6 -31
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
- package/template/.cursor/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
- package/template/.cursor/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
- package/template/.cursor/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
- package/template/.cursor/skills/yss-mvc-design/SKILL.md +5 -9
- package/template/.cursor/skills/yss-mvc-design/agents/openai.yaml +3 -3
- package/template/.cursor/skills/yss-mybatis/SKILL.md +2 -2
- package/template/.cursor/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
- package/template/.cursor/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
- package/template/.cursor/skills/yss-mybatis/references/source-index.md +6 -109
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.cursor/skills/yss-repository/SKILL.md +1 -1
- package/template/.cursor/skills/yss-resilience4j/SKILL.md +4 -0
- package/template/.cursor/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
- package/template/.cursor/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
- package/template/.cursor/skills/yss-resilience4j/references/source-index.md +6 -29
- package/template/.cursor/skills/yss-security-algorithm/SKILL.md +34 -10
- package/template/.cursor/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
- package/template/.cursor/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
- package/template/.cursor/skills/yss-security-algorithm/references/source-index.md +6 -31
- package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.cursor/skills/yss-tactical-design/references/output-template.md +1 -1
- package/template/.cursor/skills/yss-technical-design/SKILL.md +3 -1
- package/template/.cursor/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.cursor/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
- package/template/.cursor/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
- package/template/.cursor/skills/yss-up-springboot3/SKILL.md +23 -9
- package/template/.cursor/skills/yss-userinfo/SKILL.md +21 -14
- package/template/.cursor/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
- package/template/.cursor/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
- package/template/.cursor/skills/yss-userinfo/references/source-index.md +6 -30
- package/template/.cursor/skills/yss-validation/SKILL.md +12 -17
- package/template/.cursor/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
- package/template/.cursor/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
- package/template/.cursor/skills/yss-validation/references/source-index.md +6 -29
- package/template/.cursor/skills/yss-web-controller/SKILL.md +4 -4
- package/template/.cursor/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
- package/template/.pi/skills/yss-application/SKILL.md +8 -6
- package/template/.pi/skills/yss-audit-log/SKILL.md +12 -7
- package/template/.pi/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
- package/template/.pi/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
- package/template/.pi/skills/yss-audit-log/references/source-index.md +6 -39
- package/template/.pi/skills/yss-cache/SKILL.md +5 -1
- package/template/.pi/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
- package/template/.pi/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
- package/template/.pi/skills/yss-cache/references/source-index.md +6 -63
- package/template/.pi/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
- package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.pi/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
- package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
- package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
- package/template/.pi/skills/yss-distributed-id/SKILL.md +4 -0
- package/template/.pi/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
- package/template/.pi/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
- package/template/.pi/skills/yss-distributed-id/references/source-index.md +6 -82
- package/template/.pi/skills/yss-dto/SKILL.md +2 -2
- package/template/.pi/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
- package/template/.pi/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
- package/template/.pi/skills/yss-dto/references/source-index.md +6 -51
- package/template/.pi/skills/yss-excel-mvc/SKILL.md +4 -0
- package/template/.pi/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
- package/template/.pi/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
- package/template/.pi/skills/yss-excel-mvc/references/source-index.md +6 -70
- package/template/.pi/skills/yss-exception/SKILL.md +12 -9
- package/template/.pi/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
- package/template/.pi/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
- package/template/.pi/skills/yss-exception/references/source-index.md +6 -31
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
- package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
- package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
- package/template/.pi/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
- package/template/.pi/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
- package/template/.pi/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
- package/template/.pi/skills/yss-mvc-design/SKILL.md +5 -9
- package/template/.pi/skills/yss-mvc-design/agents/openai.yaml +3 -3
- package/template/.pi/skills/yss-mybatis/SKILL.md +2 -2
- package/template/.pi/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
- package/template/.pi/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
- package/template/.pi/skills/yss-mybatis/references/source-index.md +6 -109
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.pi/skills/yss-repository/SKILL.md +1 -1
- package/template/.pi/skills/yss-resilience4j/SKILL.md +4 -0
- package/template/.pi/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
- package/template/.pi/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
- package/template/.pi/skills/yss-resilience4j/references/source-index.md +6 -29
- package/template/.pi/skills/yss-security-algorithm/SKILL.md +34 -10
- package/template/.pi/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
- package/template/.pi/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
- package/template/.pi/skills/yss-security-algorithm/references/source-index.md +6 -31
- package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
- package/template/.pi/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
- package/template/.pi/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
- package/template/.pi/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
- package/template/.pi/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.pi/skills/yss-tactical-design/references/output-template.md +1 -1
- package/template/.pi/skills/yss-technical-design/SKILL.md +3 -1
- package/template/.pi/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.pi/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
- package/template/.pi/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
- package/template/.pi/skills/yss-up-springboot3/SKILL.md +23 -9
- package/template/.pi/skills/yss-userinfo/SKILL.md +21 -14
- package/template/.pi/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
- package/template/.pi/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
- package/template/.pi/skills/yss-userinfo/references/source-index.md +6 -30
- package/template/.pi/skills/yss-validation/SKILL.md +12 -17
- package/template/.pi/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
- package/template/.pi/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
- package/template/.pi/skills/yss-validation/references/source-index.md +6 -29
- package/template/.pi/skills/yss-web-controller/SKILL.md +4 -4
- package/template/.pi/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
- package/template/docs/agents/backend-architecture-profiles.md +1 -1
- package/template/docs/agents/digital-human-roles.yaml +1 -1
- package/template/docs/agents/skill-migrations.md +23 -0
- package/template/docs/agents/yss-skill-registry.yaml +109 -40
- package/template/docs/api/templates/openapi-draft-review-checklist.md +1 -1
- package/template/docs/architecture/templates/engineering-baseline-review-template.md +3 -3
- package/template/docs/architecture/templates/system-overview-design-template.md +1 -1
- package/template/docs/engineering/backend-platforms.json +662 -9
- package/template/docs/engineering/backend-platforms.md +33 -7
- package/template/docs/process/schemas/backend-architecture-identity.schema.json +102 -0
- package/template/docs/process/schemas/project-scaffold-contract.schema.json +16 -4
- package/template/docs/process/schemas/scaffold-architecture-decisions.schema.json +7 -0
- package/template/docs/process/schemas/slice-implementation-contract-v3.schema.json +143 -0
- package/template/docs/process/strategic-handoff-package.md +1 -1
- package/template/docs/templates/implementation-routing-template.md +1 -1
- package/template/docs/user-guide//346/212/200/346/234/257/350/256/276/350/256/241/347/224/250/346/210/267/346/214/207/345/215/227.md +2 -2
- package/template/scripts/backend-platforms +77 -8
- package/template/scripts/lib/backend-platform.mjs +232 -5
- package/template/scripts/lib/existing-backend-architecture.mjs +3 -2
- package/template/scripts/lib/implementation-contract-compiler.mjs +93 -9
- package/template/scripts/lib/skill-registry.mjs +165 -12
- package/template/scripts/lib/slice-contract-preparation.mjs +6 -5
- package/template/scripts/verify-backend-platform-matrix +1 -1
- package/template/skills-lock.json +29 -29
- package/template.snapshot.json +4 -4
|
@@ -9,13 +9,161 @@ export const PLATFORM_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta
|
|
|
9
9
|
export const PLATFORM_CATALOG_REF = "docs/engineering/backend-platforms.json";
|
|
10
10
|
export const PLATFORM_SKILLS = ["yss-ddd-scaffold-generator", "yss-layered-mvc-scaffold-generator"];
|
|
11
11
|
const fail = (message) => { throw new TypeError(`backend-platform: ${message}`); };
|
|
12
|
+
const componentFail = (code, message) => {
|
|
13
|
+
const error = new TypeError(`component-capability: ${code}: ${message}`);
|
|
14
|
+
error.code = code;
|
|
15
|
+
throw error;
|
|
16
|
+
};
|
|
12
17
|
const stable = (value) => Array.isArray(value) ? value.map(stable) : value && typeof value === "object" ? Object.fromEntries(Object.keys(value).sort().map(key => [key, stable(value[key])])) : value;
|
|
13
18
|
export const platformDigest = value => `sha256:${createHash("sha256").update(typeof value === "string" || Buffer.isBuffer(value) ? value : JSON.stringify(stable(value ?? null))).digest("hex")}`;
|
|
19
|
+
const exactVersion = value => typeof value === "string" && value.length > 0 && !/[\[\](),*+]|\bx\b|latest/i.test(value);
|
|
20
|
+
const portableEvidence = item => item && typeof item.ref === "string" && item.ref.length > 0 && !path.isAbsolute(item.ref) && !item.ref.split(/[\\/]/).includes("..") && /^sha256:[a-f0-9]{64}$/.test(item.digest ?? "");
|
|
21
|
+
const sha256 = value => /^sha256:[a-f0-9]{64}$/.test(value ?? "");
|
|
22
|
+
const gitTree = value => /^[a-f0-9]{40}$/.test(value ?? "");
|
|
23
|
+
const major = value => Number.parseInt(String(value ?? "").match(/^(\d+)/)?.[1] ?? "", 10);
|
|
24
|
+
const platformGeneration = profile => major(profile?.spring_boot_version) === 2 ? { line: "boot2-java8", componentMajor: 2 } : major(profile?.spring_boot_version) === 3 ? { line: "boot3-java17", componentMajor: 3 } : { line: "boot4", componentMajor: null };
|
|
25
|
+
const COMPONENT_PLATFORM_LINES = new Set(["boot2-java8", "boot3-java17"]);
|
|
26
|
+
const normalizedComponentPlatformLine = profile => COMPONENT_PLATFORM_LINES.has(profile?.component_platform_line) ? profile.component_platform_line : undefined;
|
|
27
|
+
const retirementEvidenceComplete = value => {
|
|
28
|
+
const required = new Set(["organization-code-search", "maven-download-metrics", "runtime-bean-and-configuration-scan", "30-90-day-zero-usage-window"]);
|
|
29
|
+
if (!Array.isArray(value) || !value.every(item => item?.status === "zero" && typeof item.ref === "string" && item.ref.length > 0)) return false;
|
|
30
|
+
for (const item of value) required.delete(item.kind);
|
|
31
|
+
return required.size === 0;
|
|
32
|
+
};
|
|
33
|
+
const candidateArtifactFieldsEmpty = binding =>
|
|
34
|
+
["resolved_version", "published_at", "pom_sha256", "jar_sha256", "sources_jar_sha256", "source_tree"].every(field => binding[field] === null) &&
|
|
35
|
+
Array.isArray(binding.evidence) && binding.evidence.length === 0 &&
|
|
36
|
+
Array.isArray(binding.blockers) && binding.blockers.length > 0;
|
|
37
|
+
function validateArtifactBinding(binding, label, { role, expected, snapshot, allowedStatuses = ["candidate"] }) {
|
|
38
|
+
if (!binding || typeof binding !== "object" || typeof role !== "string" || !role.length || binding.role !== role || !allowedStatuses.includes(binding.status)) componentFail("component-binding-drift", `invalid artifact binding: ${label}`);
|
|
39
|
+
if (!binding.group_id || !binding.artifact_id || !exactVersion(binding.declared_version)) componentFail("component-artifact-coordinate-conflict", `invalid candidate artifact coordinate: ${label}`);
|
|
40
|
+
if (expected && (binding.group_id !== expected.group_id || binding.artifact_id !== expected.artifact_id || binding.declared_version !== expected.version)) componentFail("component-binding-drift", `candidate artifact differs from compatibility coordinates: ${label}`);
|
|
41
|
+
if (snapshot !== binding.declared_version.endsWith("-SNAPSHOT")) componentFail("component-artifact-coordinate-conflict", `candidate artifact release kind mismatch: ${label}`);
|
|
42
|
+
if (binding.status === "candidate" && !candidateArtifactFieldsEmpty(binding)) componentFail("component-evidence-missing", `candidate artifact must remain unresolved until evidence is published: ${label}`);
|
|
43
|
+
if (binding.status === "resolved") {
|
|
44
|
+
if (snapshot || binding.resolved_version !== binding.declared_version || !sha256(binding.pom_sha256) || !sha256(binding.jar_sha256) || !sha256(binding.sources_jar_sha256)) componentFail("component-evidence-missing", `resolved external release lacks immutable version or POM/JAR/sources digest: ${label}`);
|
|
45
|
+
if (binding.published_at !== null && (typeof binding.published_at !== "string" || !binding.published_at.length)) componentFail("component-binding-drift", `invalid external release timestamp: ${label}`);
|
|
46
|
+
if (binding.source_tree !== null && !gitTree(binding.source_tree)) componentFail("component-binding-drift", `invalid external release source tree: ${label}`);
|
|
47
|
+
if (!Array.isArray(binding.evidence) || !Array.isArray(binding.blockers)) componentFail("component-evidence-missing", `resolved external release evidence fields are invalid: ${label}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function componentCapabilityDigest(value, capabilityId = value?.capability_id) {
|
|
51
|
+
const { capability_id, component_digest, status, evidence, blockers, ...recipe } = value ?? {};
|
|
52
|
+
return platformDigest({ capability_id: capabilityId, ...recipe });
|
|
53
|
+
}
|
|
54
|
+
function validateBoot3Java17Policy(entry, profile) {
|
|
55
|
+
if (profile.component_platform_line !== "boot3-java17") return;
|
|
56
|
+
if (profile.spring_cloud_version !== "2025.0.3" || profile.spring_cloud_alibaba_version !== "2025.0.0.0" || profile.validation_namespace !== "jakarta" || profile.jackson_major !== 2 || profile.auto_configuration_imports_path !== "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports") componentFail("component-binding-drift", `Boot 3.5/JDK17 platform constraints changed: ${profile.id}`);
|
|
57
|
+
if (!entry.platform_artifact_bindings || !Array.isArray(entry.external_snapshot_bindings) || !Array.isArray(entry.external_artifact_bindings)) componentFail("component-binding-drift", `Boot 3.5/JDK17 artifact binding structures are missing: ${entry.id}`);
|
|
58
|
+
if (entry.external_snapshot_bindings.length) componentFail("component-artifact-coordinate-conflict", `Boot 3.5/JDK17 does not allow unresolved external SNAPSHOT bindings: ${entry.id}`);
|
|
59
|
+
const components = entry.component_capabilities ?? {};
|
|
60
|
+
const exactComponent = (capabilityId, expected) => {
|
|
61
|
+
const artifacts = components[capabilityId]?.artifacts;
|
|
62
|
+
if (!Array.isArray(artifacts) || artifacts.length !== expected.length || artifacts.some((artifact, index) => `${artifact.group_id}:${artifact.artifact_id}:${artifact.declared_version}` !== expected[index])) componentFail("component-binding-drift", `Boot 3.5/JDK17 component coordinates changed: ${entry.id}:${capabilityId}`);
|
|
63
|
+
};
|
|
64
|
+
exactComponent("contract.request-validation", [`org.springframework.boot:spring-boot-starter-validation:${profile.spring_boot_version}`]);
|
|
65
|
+
exactComponent("component.cache", ["com.yss.cloud:yss-component-cache-starter:3.1.0-SNAPSHOT"]);
|
|
66
|
+
exactComponent("component.distributed-id", ["com.yss.cloud:yss-component-distributed-id:3.1.0-SNAPSHOT"]);
|
|
67
|
+
if (Object.values(components).some(item => item.artifacts?.some(artifact => artifact.artifact_id === "yss-component-excel-starter"))) componentFail("component-new-adoption-forbidden", `removed yss-component-excel-starter is present: ${entry.id}`);
|
|
68
|
+
exactComponent("component.excel-import-export", ["com.yss.cloud:yss-component-excel-mvc:3.0.0-SNAPSHOT"]);
|
|
69
|
+
for (const [capabilityId, item] of Object.entries(components)) {
|
|
70
|
+
if (item.status !== "blocked" || item.verified_architectures.length || item.evidence.length || item.artifacts.some(artifact => ["resolved_version", "pom_sha256", "jar_sha256", "source_tree"].some(field => artifact[field] !== null))) componentFail("component-evidence-missing", `Boot 3.5/JDK17 unpublished component must remain blocked and unresolved: ${entry.id}:${capabilityId}`);
|
|
71
|
+
}
|
|
72
|
+
const external = entry.external_artifact_bindings;
|
|
73
|
+
if (external.length !== 1 || `${external[0].group_id}:${external[0].artifact_id}:${external[0].declared_version}` !== "org.apache.fesod:fesod-sheet:2.0.2-incubating" || external[0].status !== "resolved") componentFail("component-binding-drift", `Boot 3.5/JDK17 Fesod release binding changed: ${entry.id}`);
|
|
74
|
+
}
|
|
75
|
+
function validateComponentCatalog(value, root = PLATFORM_ROOT) {
|
|
76
|
+
if (Object.hasOwn(value, "component_capabilities") || Object.hasOwn(value, "component_capability_ids")) componentFail("component-binding-drift", "component capabilities must be nested in their compatibility entry");
|
|
77
|
+
for (const entry of value.compatibility) {
|
|
78
|
+
const profile = value.profiles.find(item => item.id === entry.profile_id && item.spring_boot_version === entry.spring_boot_version);
|
|
79
|
+
if (!profile) componentFail("component-unavailable-for-platform", `compatibility profile is missing: ${entry.id}`);
|
|
80
|
+
const generation = platformGeneration(profile);
|
|
81
|
+
if (!COMPONENT_PLATFORM_LINES.has(generation.line) || profile.component_platform_line !== generation.line) componentFail("component-platform-generation-mismatch", `profile component line does not match ${generation.line}: ${profile.id}`);
|
|
82
|
+
if (entry.platform_artifact_bindings !== undefined) {
|
|
83
|
+
if (!entry.platform_artifact_bindings || Array.isArray(entry.platform_artifact_bindings) || Object.keys(entry.platform_artifact_bindings).sort().join(",") !== "bom,parent") componentFail("component-binding-drift", `platform artifact bindings must contain parent and bom: ${entry.id}`);
|
|
84
|
+
validateArtifactBinding(entry.platform_artifact_bindings.parent, `${entry.id}:parent`, { role: "parent", expected: entry.parent, snapshot: true });
|
|
85
|
+
validateArtifactBinding(entry.platform_artifact_bindings.bom, `${entry.id}:bom`, { role: "bom", expected: entry.bom, snapshot: true });
|
|
86
|
+
}
|
|
87
|
+
for (const [field, snapshot] of [["external_snapshot_bindings", true], ["external_artifact_bindings", false]]) {
|
|
88
|
+
const bindings = entry[field];
|
|
89
|
+
if (bindings === undefined) continue;
|
|
90
|
+
if (!Array.isArray(bindings)) componentFail("component-binding-drift", `${field} must be an array: ${entry.id}`);
|
|
91
|
+
const coordinates = new Set();
|
|
92
|
+
for (const binding of bindings) {
|
|
93
|
+
validateArtifactBinding(binding, `${entry.id}:${field}:${binding?.group_id ?? "?"}:${binding?.artifact_id ?? "?"}`, { role: binding?.role, snapshot, allowedStatuses: field === "external_artifact_bindings" ? ["candidate", "resolved"] : ["candidate"] });
|
|
94
|
+
const coordinate = `${binding.group_id}:${binding.artifact_id}`;
|
|
95
|
+
if (coordinates.has(coordinate)) componentFail("component-artifact-coordinate-conflict", `duplicate ${field} coordinate: ${entry.id}:${coordinate}`);
|
|
96
|
+
coordinates.add(coordinate);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let artifactResolution = null;
|
|
100
|
+
if (entry.artifact_resolution_evidence !== undefined) {
|
|
101
|
+
const binding = entry.artifact_resolution_evidence;
|
|
102
|
+
if (!portableEvidence(binding) || typeof binding.report_id !== "string" || typeof binding.repository_id !== "string") componentFail("component-evidence-missing", `invalid artifact resolution evidence: ${entry.id}`);
|
|
103
|
+
let bytes;
|
|
104
|
+
try { bytes = readFileSync(path.join(root, binding.ref)); }
|
|
105
|
+
catch { componentFail("component-evidence-missing", `artifact resolution evidence is unreadable: ${entry.id}`); }
|
|
106
|
+
if (platformDigest(bytes) !== binding.digest) componentFail("component-binding-drift", `artifact resolution evidence drift: ${entry.id}`);
|
|
107
|
+
try { artifactResolution = JSON.parse(bytes); }
|
|
108
|
+
catch { componentFail("component-binding-drift", `artifact resolution evidence is not valid JSON: ${entry.id}`); }
|
|
109
|
+
if (artifactResolution.schema_version !== 1 || artifactResolution.kind !== "backend-component-artifact-resolution" || artifactResolution.report_id !== binding.report_id || artifactResolution.repository?.id !== binding.repository_id || !Array.isArray(artifactResolution.artifacts)) componentFail("component-binding-drift", `artifact resolution evidence identity mismatch: ${entry.id}`);
|
|
110
|
+
artifactResolution = new Map(artifactResolution.artifacts.map(item => [`${item.group_id}:${item.artifact_id}:${item.declared_version}`, item]));
|
|
111
|
+
}
|
|
112
|
+
if (entry.component_capabilities === undefined) continue;
|
|
113
|
+
if (!entry.component_capabilities || Array.isArray(entry.component_capabilities) || typeof entry.component_capabilities !== "object") componentFail("component-evidence-missing", `component capability map is invalid: ${entry.id}`);
|
|
114
|
+
for (const [capabilityId, item] of Object.entries(entry.component_capabilities)) {
|
|
115
|
+
const key = `${entry.id}:${capabilityId}`;
|
|
116
|
+
if (!capabilityId.includes(".") || !item || typeof item !== "object") componentFail("component-binding-drift", `invalid component capability binding: ${key}`);
|
|
117
|
+
if (!["candidate", "verified", "blocked"].includes(item.status) || !Array.isArray(item.verified_architectures) || !Array.isArray(item.artifacts) || !Array.isArray(item.evidence) || !Array.isArray(item.blockers)) componentFail("component-evidence-missing", `incomplete capability entry: ${key}`);
|
|
118
|
+
if (item.provider_kind !== undefined && !["yss-component", "platform-managed"].includes(item.provider_kind)) componentFail("component-binding-drift", `invalid component provider kind: ${key}`);
|
|
119
|
+
if (item.provider_kind === "platform-managed") {
|
|
120
|
+
if (capabilityId !== "contract.request-validation" || item.artifacts.length !== 1) componentFail("component-binding-drift", `unsupported platform-managed capability: ${key}`);
|
|
121
|
+
const artifact = item.artifacts[0];
|
|
122
|
+
if (artifact.group_id !== "org.springframework.boot" || artifact.artifact_id !== "spring-boot-starter-validation" || artifact.declared_version !== profile.spring_boot_version) componentFail("component-binding-drift", `platform-managed validation must match Spring Boot ${profile.spring_boot_version}: ${key}`);
|
|
123
|
+
}
|
|
124
|
+
if (!["active", "maintenance", "deprecated", "retired"].includes(item.lifecycle ?? "active") || !["allowed", "forbidden"].includes(item.adoption_policy ?? "allowed")) componentFail("component-binding-drift", `invalid component lifecycle/adoption policy: ${key}`);
|
|
125
|
+
if (item.lifecycle === "retired" && !retirementEvidenceComplete(item.retirement_evidence)) componentFail("component-retirement-evidence-missing", `organizational zero-consumption evidence is incomplete: ${key}`);
|
|
126
|
+
if (new Set(item.verified_architectures).size !== item.verified_architectures.length || item.verified_architectures.some(family => !["domain-driven", "layered-mvc"].includes(family))) componentFail("component-binding-drift", `invalid verified architectures: ${key}`);
|
|
127
|
+
const coordinates = new Set();
|
|
128
|
+
for (const artifact of item.artifacts) {
|
|
129
|
+
const coordinate = `${artifact.group_id}:${artifact.artifact_id}`;
|
|
130
|
+
if (!artifact.group_id || !artifact.artifact_id || !exactVersion(artifact.declared_version) || coordinates.has(coordinate)) componentFail("component-artifact-coordinate-conflict", `invalid or duplicate artifact coordinate in ${key}: ${coordinate}`);
|
|
131
|
+
if (artifact.resolved_version !== null && artifact.resolved_version !== undefined && !exactVersion(artifact.resolved_version)) componentFail("component-artifact-coordinate-conflict", `invalid resolved version in ${key}: ${coordinate}`);
|
|
132
|
+
if (artifact.declared_version.endsWith("-SNAPSHOT") && artifact.resolved_version && (artifact.resolved_version === artifact.declared_version || artifact.resolved_version.endsWith("-SNAPSHOT"))) componentFail("component-artifact-coordinate-conflict", `SNAPSHOT is not uniquely resolved in ${key}: ${coordinate}`);
|
|
133
|
+
if (artifactResolution) {
|
|
134
|
+
const resolved = artifactResolution.get(`${coordinate}:${artifact.declared_version}`);
|
|
135
|
+
if (!resolved) componentFail("component-evidence-missing", `artifact is absent from resolution evidence: ${key}:${coordinate}`);
|
|
136
|
+
const expectedPom = resolved.pom_sha256 ? `sha256:${resolved.pom_sha256}` : null;
|
|
137
|
+
const expectedJar = resolved.jar_sha256 ? `sha256:${resolved.jar_sha256}` : null;
|
|
138
|
+
const expectedTree = resolved.sources_match_source_tree === true && resolved.pom_matches_source_tree === true ? resolved.source_tree : null;
|
|
139
|
+
if (artifact.resolved_version !== resolved.resolved_version || artifact.pom_sha256 !== expectedPom || artifact.jar_sha256 !== expectedJar || artifact.source_tree !== expectedTree) componentFail("component-binding-drift", `artifact binding differs from resolution evidence: ${key}:${coordinate}`);
|
|
140
|
+
}
|
|
141
|
+
coordinates.add(coordinate);
|
|
142
|
+
}
|
|
143
|
+
if (!sha256(item.component_digest) || item.component_digest !== componentCapabilityDigest(item, capabilityId)) componentFail("component-binding-drift", `component digest mismatch: ${key}`);
|
|
144
|
+
if (item.status === "verified") {
|
|
145
|
+
if (!item.verified_architectures.length || !item.artifacts.length || !item.evidence.length || item.blockers.length) componentFail("component-evidence-missing", `verified capability is incomplete: ${key}`);
|
|
146
|
+
if (entry.status !== "verified") componentFail("component-unavailable-for-platform", `verified capability belongs to an unverified compatibility entry: ${key}`);
|
|
147
|
+
if (item.artifacts.some(artifact => !exactVersion(artifact.resolved_version) || !sha256(artifact.pom_sha256) || !sha256(artifact.jar_sha256) || !gitTree(artifact.source_tree))) componentFail("component-evidence-missing", `verified artifact evidence is missing: ${key}`);
|
|
148
|
+
const generation = platformGeneration(value.profiles.find(profile => profile.id === entry.profile_id));
|
|
149
|
+
if (generation.componentMajor !== null && item.artifacts.some(artifact => major(artifact.declared_version) !== generation.componentMajor)) componentFail("component-platform-generation-mismatch", `${key} does not match ${generation.line}`);
|
|
150
|
+
if (item.evidence.some(evidence => !portableEvidence(evidence) || !item.verified_architectures.includes(evidence.architecture_family))) componentFail("component-evidence-missing", `verified capability evidence is invalid: ${key}`);
|
|
151
|
+
} else if (!item.blockers.length) componentFail("component-evidence-missing", `unverified capability lacks blockers: ${key}`);
|
|
152
|
+
}
|
|
153
|
+
validateBoot3Java17Policy(entry, profile);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
14
156
|
export function loadBackendPlatforms(root = PLATFORM_ROOT) {
|
|
15
157
|
const value = JSON.parse(readFileSync(path.join(root, PLATFORM_CATALOG_REF), "utf8"));
|
|
16
|
-
if (value.schema_version !==
|
|
158
|
+
if (value.schema_version !== 2 || value.kind !== "backend-platform-catalog" || !Array.isArray(value.profiles) || !Array.isArray(value.compatibility)) fail("invalid catalog");
|
|
17
159
|
if (new Set(value.profiles.map(item => `${item.id}:${item.spring_boot_version}:${item.java_version}`)).size !== value.profiles.length || new Set(value.compatibility.map(item => item.id)).size !== value.compatibility.length) fail("duplicate catalog release/id");
|
|
18
|
-
for (const profile of value.profiles)
|
|
160
|
+
for (const profile of value.profiles) {
|
|
161
|
+
if (!/^\d+\.\d+\.\d+$/.test(profile.spring_boot_version)) fail("catalog requires exact patch versions");
|
|
162
|
+
const generation = platformGeneration(profile);
|
|
163
|
+
if (COMPONENT_PLATFORM_LINES.has(generation.line) && profile.component_platform_line !== generation.line) componentFail("component-platform-generation-mismatch", `profile component line does not match ${generation.line}: ${profile.id}`);
|
|
164
|
+
if (!COMPONENT_PLATFORM_LINES.has(generation.line) && profile.component_platform_line !== undefined) componentFail("component-platform-generation-mismatch", `unsupported component platform line for ${profile.id}: ${profile.component_platform_line}`);
|
|
165
|
+
}
|
|
166
|
+
validateComponentCatalog(value, root);
|
|
19
167
|
return value;
|
|
20
168
|
}
|
|
21
169
|
export function platformProfile(id, catalog = loadBackendPlatforms(), version) {
|
|
@@ -27,15 +175,20 @@ export function platformProfile(id, catalog = loadBackendPlatforms(), version) {
|
|
|
27
175
|
}
|
|
28
176
|
export function platformRecipeDigest(profile, entry) {
|
|
29
177
|
const { candidate_blockers, recommended, ...recipe } = profile;
|
|
30
|
-
return platformDigest({ profile: recipe, entry: { id: entry.id, profile_id: entry.profile_id, spring_boot_version: entry.spring_boot_version, parent: entry.parent, bom: entry.bom, components: entry.components ?? {} } });
|
|
178
|
+
return platformDigest({ profile: recipe, entry: { id: entry.id, profile_id: entry.profile_id, spring_boot_version: entry.spring_boot_version, parent: entry.parent, bom: entry.bom, components: entry.components ?? {}, platform_artifact_bindings: entry.platform_artifact_bindings ?? {}, external_snapshot_bindings: entry.external_snapshot_bindings ?? [], external_artifact_bindings: entry.external_artifact_bindings ?? [] } });
|
|
31
179
|
}
|
|
32
180
|
export function platformBinding(profile, entry) {
|
|
33
|
-
|
|
181
|
+
const componentPlatformLine = normalizedComponentPlatformLine(profile);
|
|
182
|
+
return { schema_version: 2, profile_id: profile.id, spring_boot_version: profile.spring_boot_version, java_version: profile.java_version, ...(componentPlatformLine ? { component_platform_line: componentPlatformLine } : {}), parent: entry.parent, bom: entry.bom, compatibility_id: entry.id, compatibility_digest: platformRecipeDigest(profile, entry) };
|
|
34
183
|
}
|
|
35
|
-
export function resolveBackendPlatform(binding,
|
|
184
|
+
export function resolveBackendPlatform(binding, options = {}) {
|
|
185
|
+
const root = options.root ?? PLATFORM_ROOT;
|
|
186
|
+
const catalog = options.catalog ?? loadBackendPlatforms(root);
|
|
187
|
+
const requireVerified = options.requireVerified ?? true;
|
|
36
188
|
if (!binding || binding.schema_version !== 2) fail("missing platform_configuration v2 (v1 is historical read-only); 生命周期须展示 Boot/Java/YSS 组合并取得用户确认");
|
|
37
189
|
const profile = platformProfile(binding.profile_id, catalog, binding.spring_boot_version);
|
|
38
190
|
if (binding.spring_boot_version !== profile.spring_boot_version || binding.java_version !== profile.java_version) fail("unsupported exact Boot/Java combination (x/latest and Java 8/11 for Boot 3.5/4.1 are rejected)");
|
|
191
|
+
if (binding.component_platform_line !== normalizedComponentPlatformLine(profile)) fail("component_platform_line does not match the selected platform profile");
|
|
39
192
|
const entry = catalog.compatibility.find(item => item.id === binding.compatibility_id);
|
|
40
193
|
const evidenceReports = [];
|
|
41
194
|
if (!entry || entry.profile_id !== profile.id || entry.spring_boot_version !== profile.spring_boot_version) fail("YSS compatibility entry missing; parent/BOM/starter verification required");
|
|
@@ -66,6 +219,80 @@ export function resolveBackendPlatform(binding, { catalog = loadBackendPlatforms
|
|
|
66
219
|
}
|
|
67
220
|
return { profile, entry, evidenceReports };
|
|
68
221
|
}
|
|
222
|
+
export function resolveComponentCapabilities(binding, capabilityIds, architectureFamily, options = {}) {
|
|
223
|
+
const root = options.root ?? PLATFORM_ROOT;
|
|
224
|
+
const catalog = options.catalog ?? loadBackendPlatforms(root);
|
|
225
|
+
let resolvedPlatform;
|
|
226
|
+
try { resolvedPlatform = resolveBackendPlatform(binding, { catalog, root, requireVerified: false }); }
|
|
227
|
+
catch (error) {
|
|
228
|
+
const code = /drift|stale/i.test(error.message ?? "") ? "component-binding-drift" : "component-unavailable-for-platform";
|
|
229
|
+
componentFail(code, error.message);
|
|
230
|
+
}
|
|
231
|
+
if (!Array.isArray(capabilityIds) || !capabilityIds.length || capabilityIds.some(id => typeof id !== "string" || !id.length) || new Set(capabilityIds).size !== capabilityIds.length) componentFail("component-unavailable-for-platform", "capability ids must be a non-empty unique list");
|
|
232
|
+
if (!["domain-driven", "layered-mvc"].includes(architectureFamily)) componentFail("component-unavailable-for-platform", `unsupported architecture family: ${architectureFamily}`);
|
|
233
|
+
const records = capabilityIds.map(capabilityId => {
|
|
234
|
+
const item = resolvedPlatform.entry.component_capabilities?.[capabilityId];
|
|
235
|
+
if (!item) componentFail("component-unavailable-for-platform", `${capabilityId} is not declared for ${resolvedPlatform.entry.id}`);
|
|
236
|
+
if (item.lifecycle === "retired" && !retirementEvidenceComplete(item.retirement_evidence)) componentFail("component-retirement-evidence-missing", `${capabilityId} lacks organizational zero-consumption evidence`);
|
|
237
|
+
if ((item.adoption_policy ?? "allowed") === "forbidden" && !(options.allowForbiddenExisting ?? false)) componentFail("component-new-adoption-forbidden", `${capabilityId} is ${item.lifecycle ?? "deprecated"}; use ${item.replacement_binding_id ?? item.replacement_gav ?? "the approved migration route"}`);
|
|
238
|
+
const generation = platformGeneration(resolvedPlatform.profile);
|
|
239
|
+
if (generation.componentMajor !== null && item.artifacts.some(artifact => major(artifact.declared_version) !== generation.componentMajor)) componentFail("component-platform-generation-mismatch", `${capabilityId} requires component ${generation.componentMajor}.x for ${generation.line}`);
|
|
240
|
+
if (item.status !== "verified") {
|
|
241
|
+
const blockers = (item.blockers ?? []).join("; ");
|
|
242
|
+
const code = item.blockers?.some(blocker => blocker.startsWith("component-platform-generation-mismatch:"))
|
|
243
|
+
? "component-platform-generation-mismatch"
|
|
244
|
+
: item.blockers?.some(blocker => blocker.startsWith("component-new-adoption-forbidden:"))
|
|
245
|
+
? "component-new-adoption-forbidden"
|
|
246
|
+
: item.blockers?.some(blocker => blocker.startsWith("component-retirement-evidence-missing:"))
|
|
247
|
+
? "component-retirement-evidence-missing"
|
|
248
|
+
: item.blockers?.some(blocker => blocker.startsWith("component-artifact-coordinate-conflict:"))
|
|
249
|
+
? "component-artifact-coordinate-conflict"
|
|
250
|
+
: item.blockers?.some(blocker => blocker.startsWith("component-binding-drift:"))
|
|
251
|
+
? "component-binding-drift"
|
|
252
|
+
: item.blockers?.some(blocker => blocker.startsWith("component-evidence-missing:"))
|
|
253
|
+
? "component-evidence-missing"
|
|
254
|
+
: "component-unavailable-for-platform";
|
|
255
|
+
componentFail(code, `${capabilityId} is ${item.status}; ${blockers}`);
|
|
256
|
+
}
|
|
257
|
+
if (!item.verified_architectures.includes(architectureFamily)) componentFail("component-unavailable-for-platform", `${capabilityId} is not verified for ${architectureFamily}`);
|
|
258
|
+
if (!item.artifacts.length || item.artifacts.some(artifact => !artifact.group_id || !artifact.artifact_id || !exactVersion(artifact.declared_version) || !exactVersion(artifact.resolved_version) || !sha256(artifact.pom_sha256) || !sha256(artifact.jar_sha256) || !gitTree(artifact.source_tree))) componentFail("component-evidence-missing", `${capabilityId} lacks exact artifact evidence`);
|
|
259
|
+
const artifactCoordinates = item.artifacts.map(artifact => `${artifact.group_id}:${artifact.artifact_id}`);
|
|
260
|
+
if (new Set(artifactCoordinates).size !== artifactCoordinates.length || item.artifacts.some(artifact => artifact.declared_version.endsWith("-SNAPSHOT") && (artifact.resolved_version === artifact.declared_version || artifact.resolved_version.endsWith("-SNAPSHOT")))) componentFail("component-artifact-coordinate-conflict", `${capabilityId} has duplicate coordinates or an unresolved SNAPSHOT`);
|
|
261
|
+
if (item.component_digest !== componentCapabilityDigest(item, capabilityId)) componentFail("component-binding-drift", `${capabilityId} component digest changed`);
|
|
262
|
+
return { capabilityId, item };
|
|
263
|
+
});
|
|
264
|
+
if (options.requirePlatformVerified ?? true) {
|
|
265
|
+
try { resolveBackendPlatform(binding, { catalog, root, requireVerified: true }); }
|
|
266
|
+
catch (error) {
|
|
267
|
+
const code = /drift|stale/i.test(error.message ?? "") ? "component-binding-drift" : "component-unavailable-for-platform";
|
|
268
|
+
componentFail(code, error.message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const coordinates = new Map();
|
|
272
|
+
for (const { capabilityId, item } of records) for (const artifact of item.artifacts) {
|
|
273
|
+
const coordinate = `${artifact.group_id}:${artifact.artifact_id}`;
|
|
274
|
+
const previous = coordinates.get(coordinate);
|
|
275
|
+
const version = `${artifact.declared_version}->${artifact.resolved_version}`;
|
|
276
|
+
if (previous && previous.version !== version) componentFail("component-artifact-coordinate-conflict", `${coordinate} resolves to both ${previous.version} (${previous.capabilityId}) and ${version} (${capabilityId})`);
|
|
277
|
+
coordinates.set(coordinate, { version, capabilityId });
|
|
278
|
+
}
|
|
279
|
+
return records.map(({ capabilityId, item }) => {
|
|
280
|
+
const evidence = item.evidence.filter(record => record.architecture_family === architectureFamily);
|
|
281
|
+
if (!evidence.length) componentFail("component-evidence-missing", `${capabilityId} lacks ${architectureFamily} evidence`);
|
|
282
|
+
for (const record of evidence) {
|
|
283
|
+
if (!portableEvidence(record)) componentFail("component-evidence-missing", `${capabilityId} has invalid portable evidence`);
|
|
284
|
+
let bytes;
|
|
285
|
+
try { bytes = readFileSync(path.join(root, record.ref)); }
|
|
286
|
+
catch { componentFail("component-evidence-missing", `${capabilityId} evidence is unreadable: ${record.ref}`); }
|
|
287
|
+
if (platformDigest(bytes) !== record.digest) componentFail("component-binding-drift", `${capabilityId} evidence bytes changed`);
|
|
288
|
+
let report;
|
|
289
|
+
try { report = JSON.parse(bytes); }
|
|
290
|
+
catch { componentFail("component-binding-drift", `${capabilityId} evidence is not valid JSON`); }
|
|
291
|
+
if (report.schema_version !== 1 || report.kind !== "backend-component-capability-evidence" || report.status !== "passed" || report.capability_id !== capabilityId || report.compatibility_id !== resolvedPlatform.entry.id || report.profile_id !== resolvedPlatform.profile.id || report.spring_boot_version !== resolvedPlatform.profile.spring_boot_version || report.architecture_family !== architectureFamily || report.component_digest !== item.component_digest || platformDigest(report.artifacts) !== platformDigest(item.artifacts)) componentFail("component-binding-drift", `${capabilityId} evidence identity mismatch`);
|
|
292
|
+
}
|
|
293
|
+
return { capability_id: capabilityId, status: item.status, verified_architectures: [...item.verified_architectures], artifacts: item.artifacts.map(artifact => ({ ...artifact })), evidence: evidence.map(record => ({ ...record })), component_digest: item.component_digest };
|
|
294
|
+
});
|
|
295
|
+
}
|
|
69
296
|
export function assertContractPlatform(contract, decision, options = {}) {
|
|
70
297
|
const binding = contract.platform_configuration;
|
|
71
298
|
const resolved = resolveBackendPlatform(binding, options);
|
|
@@ -17,10 +17,11 @@ function file(root,ref){relative(ref);let current=realpathSync(root);for(const p
|
|
|
17
17
|
function parse(bytes){const doc=parseDocument(String(bytes),{uniqueKeys:true,maxAliasCount:0});requireThat(!doc.errors.length,'ARCH_EVIDENCE_FORMAT',doc.errors[0]?.message);return doc.toJS({maxAliasCount:0});}
|
|
18
18
|
function bound(root,binding){requireThat(binding&&text(binding.ref)&&digest(binding.digest),'ARCH_EVIDENCE_REF','缺少原始证据 ref/digest');const bytes=readFileSync(file(root,binding.ref));requireThat(sha(bytes)===binding.digest,'ARCH_EVIDENCE_STALE',`原始证据已改变: ${binding.ref}`);return parse(bytes);}
|
|
19
19
|
function same(a,b,code,label){requireThat(existingArchitectureDigest(a)===existingArchitectureDigest(b),code,label);}
|
|
20
|
-
const
|
|
20
|
+
const REQUIRED_FIELDS=['schema_version','source_kind','architecture_family','architecture_profile','repository_id','project_id','source_digest','build_units_digest'];
|
|
21
|
+
const FIELDS=[...REQUIRED_FIELDS,'platform_configuration'];
|
|
21
22
|
export function validateExistingArchitecture(identity,registry){
|
|
22
23
|
requireThat(identity?.schema_version===2&&identity.source_kind==='existing-registration','ARCH_SOURCE_UNSUPPORTED','仅支持 existing-registration v2');
|
|
23
|
-
requireThat(
|
|
24
|
+
requireThat(REQUIRED_FIELDS.every(k=>identity[k]!==undefined)&&Object.keys(identity).every(k=>FIELDS.includes(k)),'ARCH_IDENTITY_SHAPE','既有身份字段缺失或混入生成事实');
|
|
24
25
|
const p=registry.existing_project_profiles?.[identity.architecture_profile];
|
|
25
26
|
requireThat(p&&p.source_kind==='existing-registration'&&p.build_system==='maven'&&p.architecture_family===identity.architecture_family,'ARCH_PROFILE_UNSUPPORTED','未支持的既有工程架构/Profile');
|
|
26
27
|
requireThat(['domain-driven','layered-mvc'].includes(identity.architecture_family)&&text(identity.repository_id)&&text(identity.project_id)&&digest(identity.source_digest)&&digest(identity.build_units_digest),'ARCH_IDENTITY_SHAPE','既有身份未绑定项目或源码/构建摘要');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveBackendPlatform } from "./backend-platform.mjs";
|
|
1
|
+
import { resolveBackendPlatform, resolveComponentCapabilities } from "./backend-platform.mjs";
|
|
2
2
|
import { safe } from './strategic-handoff-io.mjs';
|
|
3
3
|
import { selectSliceWorkUnit, normalizeSliceContract, withinSlicePath } from './slice-contract.mjs';
|
|
4
4
|
import { createApprovedExecutionContext, createApprovedRecompilationContext, assertApprovedExecutionContext } from './approved-execution-context.mjs';
|
|
@@ -8,7 +8,7 @@ import { createHash } from "node:crypto";
|
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { parseDocument } from "../vendor/yaml.mjs";
|
|
11
|
-
import { DEFAULT_REGISTRY, loadSkillRegistry } from "./skill-registry.mjs";
|
|
11
|
+
import { DEFAULT_REGISTRY, loadSkillRegistry, resolveSkillForNewUse } from "./skill-registry.mjs";
|
|
12
12
|
import { ROOT } from "./skill-supply-chain.mjs";
|
|
13
13
|
import { architectureDigest, assertArchitectureAgreement, validateArchitectureIdentity, verifyArchitectureEvidence } from "./backend-architecture.mjs";
|
|
14
14
|
import { enforceFrontendDelivery } from "./frontend-delivery-boundary.mjs";
|
|
@@ -26,6 +26,20 @@ function fail(message) {
|
|
|
26
26
|
throw new TypeError(message);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
function componentFail(code, message) {
|
|
30
|
+
const error = new TypeError(`component-capability: ${code}: ${message}`);
|
|
31
|
+
error.code = code;
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function bindComponentContext(bindings, architectureIdentity) {
|
|
36
|
+
return bindings.map((binding) => ({
|
|
37
|
+
...binding,
|
|
38
|
+
architecture_family: architectureIdentity.architecture_family,
|
|
39
|
+
platform_configuration: structuredClone(architectureIdentity.platform_configuration)
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
function stable(value) {
|
|
30
44
|
if (Array.isArray(value)) return value.map(stable);
|
|
31
45
|
if (!value || typeof value !== "object") return value;
|
|
@@ -46,11 +60,29 @@ export function loadCompilerContract(filePath = DEFAULT_COMPILER_CONTRACT) {
|
|
|
46
60
|
return loadYaml(filePath, "实现合同编译器合同");
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
function
|
|
50
|
-
if (registry?.schema_version !==
|
|
63
|
+
function assertV3(registry, compilerContract) {
|
|
64
|
+
if (registry?.schema_version !== 3) fail("技能注册表 schema v1/v2 已停止支持;请迁移到 provider/deprecation v3");
|
|
51
65
|
if (compilerContract?.schema_version !== 2) fail("实现合同编译器合同 schema v1 已停止支持;请迁移到 v2");
|
|
52
66
|
}
|
|
53
67
|
|
|
68
|
+
function skillFail(code, message, details = {}) {
|
|
69
|
+
const error = new TypeError(`${code}: ${message}`);
|
|
70
|
+
error.code = code;
|
|
71
|
+
error.details = details;
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function componentBindingIds(registry, capabilityIds, skillIds, nonExpanding = []) {
|
|
76
|
+
const capabilitySet = new Set(capabilityIds);
|
|
77
|
+
const skillSet = new Set([
|
|
78
|
+
...skillIds,
|
|
79
|
+
...nonExpanding.filter(item => item.type === "component-dependency").map(item => item.skill)
|
|
80
|
+
]);
|
|
81
|
+
return [...new Set(registry.capabilities
|
|
82
|
+
.filter(capability => capability.provider?.kind === "yss-component" && (capabilitySet.has(capability.id) || skillSet.has(capability.primary_skill)))
|
|
83
|
+
.map(capability => capability.provider.binding_id))];
|
|
84
|
+
}
|
|
85
|
+
|
|
54
86
|
function assertNoRemovedId(value, field) {
|
|
55
87
|
for (const id of value) if (REMOVED_SKILL_IDS.has(id)) fail(`${field} 使用已移除 skill id ${id};不提供兼容 alias`);
|
|
56
88
|
}
|
|
@@ -77,7 +109,7 @@ export function compileImplementationContract({
|
|
|
77
109
|
technical_design,
|
|
78
110
|
readOnly = false
|
|
79
111
|
}) {
|
|
80
|
-
|
|
112
|
+
assertV3(registry, compilerContract);
|
|
81
113
|
const recompilationExecution=approved_slice?createApprovedRecompilationContext(approved_slice,{root,work_unit_id}):undefined;
|
|
82
114
|
const deliveryInput = enforceFrontendDelivery({ slice_id, frontend_delivery }, { root });
|
|
83
115
|
if (!Array.isArray(recipeIds) || !Array.isArray(requiredCapabilities) || !Array.isArray(conditions)) {
|
|
@@ -91,7 +123,7 @@ export function compileImplementationContract({
|
|
|
91
123
|
for (const recipeId of requestedRecipes) if (!knownRecipes.has(recipeId)) fail(`未知 recipe: ${recipeId}`);
|
|
92
124
|
const orderedRecipes = registry.recipes.filter((recipe) => requestedRecipes.has(recipe.id));
|
|
93
125
|
const retiredRecipes = new Set(["backend.domain-behavior", "backend.persistence-mybatis", "backend.http-api"]);
|
|
94
|
-
for (const recipe of orderedRecipes) if (retiredRecipes.has(recipe.id) || recipe.maturity === "deprecated")
|
|
126
|
+
for (const recipe of orderedRecipes) if (retiredRecipes.has(recipe.id) || recipe.maturity === "deprecated") skillFail("skill-deprecated", `Recipe ${recipe.id} 已停止新用法;必须按架构重新编译`, { recipe_id: recipe.id });
|
|
95
127
|
const architectural = orderedRecipes.some((recipe) => recipe.architecture_family) || requiredCapabilities.some((id) => id.startsWith("layer."));
|
|
96
128
|
let architectureProfile;
|
|
97
129
|
if (architectural || architecture_identity) {
|
|
@@ -101,7 +133,6 @@ export function compileImplementationContract({
|
|
|
101
133
|
for (const recipe of orderedRecipes) if (recipe.architecture_family && recipe.architecture_family !== architecture_identity.architecture_family) fail(`Recipe ${recipe.id} 与架构族不匹配`);
|
|
102
134
|
}
|
|
103
135
|
|
|
104
|
-
if (architecture_identity?.platform_configuration) resolveBackendPlatform(architecture_identity.platform_configuration);
|
|
105
136
|
enforceTechnicalDesign({ technical_design, conditions, architecture_identity, slice_id }, { root, execution:recompilationExecution, readOnly });
|
|
106
137
|
|
|
107
138
|
const capabilitySources = new Map();
|
|
@@ -127,7 +158,7 @@ export function compileImplementationContract({
|
|
|
127
158
|
const family = capabilities.get(id).architecture_family ?? (dddCapabilities.has(id) ? "domain-driven" : null);
|
|
128
159
|
if (family && family !== architecture_identity?.architecture_family) fail(`capability ${id} 与 architecture_identity 不匹配`);
|
|
129
160
|
}
|
|
130
|
-
const knownSkills = new Set(registry.skills.map((skill) => skill.id));
|
|
161
|
+
const knownSkills = new Set([...(registry.skills ?? []), ...(registry.external_skills ?? [])].map((skill) => skill.id));
|
|
131
162
|
const conditionSet = new Set(conditions);
|
|
132
163
|
const reasons = new Map();
|
|
133
164
|
const nonExpanding = [];
|
|
@@ -142,6 +173,7 @@ export function compileImplementationContract({
|
|
|
142
173
|
for (const capabilityId of orderedCapabilities) {
|
|
143
174
|
const skill = capabilities.get(capabilityId).primary_skill;
|
|
144
175
|
if (!knownSkills.has(skill)) fail(`${capabilityId} 解析到未知 skill: ${skill}`);
|
|
176
|
+
resolveSkillForNewUse(registry, skill);
|
|
145
177
|
if (!roots.includes(skill)) roots.push(skill);
|
|
146
178
|
for (const source of capabilitySources.get(capabilityId)) addReason(skill, { ...source, capability: capabilityId });
|
|
147
179
|
}
|
|
@@ -156,6 +188,7 @@ export function compileImplementationContract({
|
|
|
156
188
|
const dependencies = [...(registry.skill_dependencies?.[skill] ?? [])]
|
|
157
189
|
.sort((left, right) => left.skill.localeCompare(right.skill));
|
|
158
190
|
for (const dependency of dependencies) {
|
|
191
|
+
if (knownSkills.has(dependency.skill)) resolveSkillForNewUse(registry, dependency.skill);
|
|
159
192
|
const conditionMatches = !dependency.when || conditionSet.has(dependency.when);
|
|
160
193
|
if (dependency.type === "context-conditional" && !conditionMatches) {
|
|
161
194
|
excludedConditional.push({ from: skill, ...dependency });
|
|
@@ -177,6 +210,23 @@ export function compileImplementationContract({
|
|
|
177
210
|
for (const root of roots) visit(root);
|
|
178
211
|
enforceHarnessSkillScope(orderedSkills, registry, { root });
|
|
179
212
|
|
|
213
|
+
const requiredSkillSet = new Set(orderedSkills);
|
|
214
|
+
const componentCapabilityIds = componentBindingIds(registry, orderedCapabilities, requiredSkillSet, nonExpanding);
|
|
215
|
+
let componentBindings = [];
|
|
216
|
+
if (componentCapabilityIds.length && !architecture_identity?.platform_configuration) {
|
|
217
|
+
componentFail("component-platform-binding-required", `组件能力 ${componentCapabilityIds.join(", ")} 必须绑定 architecture_identity.platform_configuration v2`);
|
|
218
|
+
}
|
|
219
|
+
if (architecture_identity?.platform_configuration) {
|
|
220
|
+
if (componentCapabilityIds.length) {
|
|
221
|
+
componentBindings = bindComponentContext(resolveComponentCapabilities(
|
|
222
|
+
architecture_identity.platform_configuration,
|
|
223
|
+
componentCapabilityIds,
|
|
224
|
+
architecture_identity.architecture_family,
|
|
225
|
+
{ root }
|
|
226
|
+
), architecture_identity);
|
|
227
|
+
} else resolveBackendPlatform(architecture_identity.platform_configuration, { root });
|
|
228
|
+
}
|
|
229
|
+
|
|
180
230
|
return {
|
|
181
231
|
schema_version: 2,
|
|
182
232
|
status: "draft",
|
|
@@ -193,6 +243,10 @@ export function compileImplementationContract({
|
|
|
193
243
|
recipe_ids: orderedRecipes.map((recipe) => recipe.id),
|
|
194
244
|
conditions: [...conditionSet].sort(),
|
|
195
245
|
required_capabilities: orderedCapabilities,
|
|
246
|
+
...(componentBindings.length ? {
|
|
247
|
+
component_bindings: structuredClone(componentBindings),
|
|
248
|
+
component_bindings_digest: digestDocument(componentBindings)
|
|
249
|
+
} : {}),
|
|
196
250
|
required_skills: orderedSkills,
|
|
197
251
|
reason_chains: Object.fromEntries(orderedSkills.map((skill) => [skill, reasons.get(skill) ?? []])),
|
|
198
252
|
non_expanding_dependencies: nonExpanding,
|
|
@@ -213,7 +267,7 @@ export function compileDefaultImplementationContract(input = {}) {
|
|
|
213
267
|
}
|
|
214
268
|
|
|
215
269
|
export function evaluateContractFreshness(contract, { registry, compilerContract, root = ROOT, approved_slice, readOnly = false, work_unit_id }, execution) {
|
|
216
|
-
|
|
270
|
+
assertV3(registry, compilerContract);
|
|
217
271
|
try { contract=normalizeSliceContract(contract,{root}); } catch(error) { return {freshness:'stale',reasons:[error.message]}; }
|
|
218
272
|
if (![2,3].includes(contract?.schema_version)) fail("Slice Implementation Contract schema v1 已停止支持;必须重新编译 v2 合同");
|
|
219
273
|
const all=contract;
|
|
@@ -240,6 +294,35 @@ export function evaluateContractFreshness(contract, { registry, compilerContract
|
|
|
240
294
|
}
|
|
241
295
|
if (resolution.architecture_identity_digest !== architectureDigest(resolution.architecture_identity)) reasons.push("architecture-identity-digest-changed");
|
|
242
296
|
}
|
|
297
|
+
const requiredCapabilitySet = new Set(resolution.required_capabilities ?? []);
|
|
298
|
+
const requiredSkillSet = new Set(resolution.required_skills ?? []);
|
|
299
|
+
const componentCapabilityIds = componentBindingIds(registry, requiredCapabilitySet, requiredSkillSet, resolution.non_expanding_dependencies ?? []);
|
|
300
|
+
if (componentCapabilityIds.length) {
|
|
301
|
+
if (!Array.isArray(resolution.component_bindings) || !resolution.component_bindings.length) {
|
|
302
|
+
reasons.push("component-binding-drift");
|
|
303
|
+
} else {
|
|
304
|
+
try {
|
|
305
|
+
const storedIds = new Set(resolution.component_bindings.map((binding) => binding.capability_id));
|
|
306
|
+
if (componentCapabilityIds.some((id) => !storedIds.has(id))) throw Object.assign(new TypeError("component-binding-drift: required capability binding missing"), { code: "component-binding-drift" });
|
|
307
|
+
const groups = new Map();
|
|
308
|
+
for (const binding of resolution.component_bindings) {
|
|
309
|
+
if (!binding.platform_configuration || !binding.architecture_family) throw Object.assign(new TypeError("component-binding-drift: binding context missing"), { code: "component-binding-drift" });
|
|
310
|
+
const key = digestDocument({ platform_configuration: binding.platform_configuration, architecture_family: binding.architecture_family });
|
|
311
|
+
if (!groups.has(key)) groups.set(key, { platform_configuration: binding.platform_configuration, architecture_family: binding.architecture_family, capability_ids: [] });
|
|
312
|
+
groups.get(key).capability_ids.push(binding.capability_id);
|
|
313
|
+
}
|
|
314
|
+
const currentBindings = [...groups.values()].flatMap((group) => bindComponentContext(resolveComponentCapabilities(
|
|
315
|
+
group.platform_configuration,
|
|
316
|
+
group.capability_ids,
|
|
317
|
+
group.architecture_family,
|
|
318
|
+
{ root }
|
|
319
|
+
), { platform_configuration: group.platform_configuration, architecture_family: group.architecture_family }));
|
|
320
|
+
if (resolution.component_bindings_digest !== digestDocument(currentBindings) || digestDocument(resolution.component_bindings) !== digestDocument(currentBindings)) reasons.push("component-binding-drift");
|
|
321
|
+
} catch (error) {
|
|
322
|
+
reasons.push(error.code ?? ["component-new-adoption-forbidden", "component-retirement-evidence-missing", "component-platform-generation-mismatch", "component-unavailable-for-platform", "component-artifact-coordinate-conflict", "component-evidence-missing", "component-binding-drift"].find((code) => error.message?.includes(code)) ?? "component-binding-drift");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
243
326
|
return { freshness: reasons.length ? "stale" : "current", reasons };
|
|
244
327
|
}
|
|
245
328
|
|
|
@@ -259,6 +342,7 @@ export function validateExecutionResult(result, contract, current) {
|
|
|
259
342
|
if (resolution.readiness_blockers?.length) blockers.push(...resolution.readiness_blockers);
|
|
260
343
|
if (consumed.contract_id !== contract.contract_id || consumed.contract_version !== contract.contract_version) blockers.push("contract-version-mismatch");
|
|
261
344
|
if (consumed.registry_digest !== resolution.registry_digest || consumed.compiler_contract_digest !== resolution.compiler_contract_digest) blockers.push("resolution-digest-mismatch");
|
|
345
|
+
if (resolution.component_bindings_digest && consumed.component_bindings_digest !== resolution.component_bindings_digest) blockers.push("component-binding-mismatch");
|
|
262
346
|
if (!Array.isArray(result.verification_results) || !result.verification_results.length) blockers.push("verification-not-executed");
|
|
263
347
|
else for (const item of result.verification_results) {
|
|
264
348
|
if (!item?.command || item.exit_code === undefined || !item.executed_at) blockers.push("verification-result-incomplete");
|