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.
Files changed (392) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
  4. package/template/.agents/skills/yss-application/SKILL.md +8 -6
  5. package/template/.agents/skills/yss-audit-log/SKILL.md +12 -7
  6. package/template/.agents/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
  7. package/template/.agents/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
  8. package/template/.agents/skills/yss-audit-log/references/source-index.md +6 -39
  9. package/template/.agents/skills/yss-cache/SKILL.md +5 -1
  10. package/template/.agents/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
  11. package/template/.agents/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
  12. package/template/.agents/skills/yss-cache/references/source-index.md +6 -63
  13. package/template/.agents/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
  14. package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
  15. package/template/.agents/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
  16. package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
  17. package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
  18. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
  19. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
  20. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
  21. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
  22. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  23. package/template/.agents/skills/yss-distributed-id/SKILL.md +4 -0
  24. package/template/.agents/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
  25. package/template/.agents/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
  26. package/template/.agents/skills/yss-distributed-id/references/source-index.md +6 -82
  27. package/template/.agents/skills/yss-dto/SKILL.md +2 -2
  28. package/template/.agents/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
  29. package/template/.agents/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
  30. package/template/.agents/skills/yss-dto/references/source-index.md +6 -51
  31. package/template/.agents/skills/yss-excel-mvc/SKILL.md +4 -0
  32. package/template/.agents/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
  33. package/template/.agents/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
  34. package/template/.agents/skills/yss-excel-mvc/references/source-index.md +6 -70
  35. package/template/.agents/skills/yss-exception/SKILL.md +12 -9
  36. package/template/.agents/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
  37. package/template/.agents/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
  38. package/template/.agents/skills/yss-exception/references/source-index.md +6 -31
  39. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  40. package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
  41. package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
  42. package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
  43. package/template/.agents/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
  44. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
  45. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
  46. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
  47. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
  48. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
  49. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
  50. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
  51. package/template/.agents/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
  52. package/template/.agents/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
  53. package/template/.agents/skills/yss-mvc-design/SKILL.md +5 -9
  54. package/template/.agents/skills/yss-mvc-design/agents/openai.yaml +3 -3
  55. package/template/.agents/skills/yss-mybatis/SKILL.md +2 -2
  56. package/template/.agents/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
  57. package/template/.agents/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
  58. package/template/.agents/skills/yss-mybatis/references/source-index.md +6 -109
  59. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
  60. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  61. package/template/.agents/skills/yss-repository/SKILL.md +1 -1
  62. package/template/.agents/skills/yss-resilience4j/SKILL.md +4 -0
  63. package/template/.agents/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
  64. package/template/.agents/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
  65. package/template/.agents/skills/yss-resilience4j/references/source-index.md +6 -29
  66. package/template/.agents/skills/yss-security-algorithm/SKILL.md +34 -10
  67. package/template/.agents/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
  68. package/template/.agents/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
  69. package/template/.agents/skills/yss-security-algorithm/references/source-index.md +6 -31
  70. package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
  71. package/template/.agents/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
  72. package/template/.agents/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
  73. package/template/.agents/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
  74. package/template/.agents/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
  75. package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
  76. package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
  77. package/template/.agents/skills/yss-tactical-design/SKILL.md +1 -1
  78. package/template/.agents/skills/yss-tactical-design/references/output-template.md +1 -1
  79. package/template/.agents/skills/yss-technical-design/SKILL.md +3 -1
  80. package/template/.agents/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
  81. package/template/.agents/skills/yss-technical-design/references/technical-design-contract.md +1 -1
  82. package/template/.agents/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
  83. package/template/.agents/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
  84. package/template/.agents/skills/yss-up-springboot3/SKILL.md +23 -9
  85. package/template/.agents/skills/yss-userinfo/SKILL.md +21 -14
  86. package/template/.agents/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
  87. package/template/.agents/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
  88. package/template/.agents/skills/yss-userinfo/references/source-index.md +6 -30
  89. package/template/.agents/skills/yss-validation/SKILL.md +12 -17
  90. package/template/.agents/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
  91. package/template/.agents/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
  92. package/template/.agents/skills/yss-validation/references/source-index.md +6 -29
  93. package/template/.agents/skills/yss-web-controller/SKILL.md +4 -4
  94. package/template/.agents/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
  95. package/template/.codex/skills/yss-application/SKILL.md +8 -6
  96. package/template/.codex/skills/yss-audit-log/SKILL.md +12 -7
  97. package/template/.codex/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
  98. package/template/.codex/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
  99. package/template/.codex/skills/yss-audit-log/references/source-index.md +6 -39
  100. package/template/.codex/skills/yss-cache/SKILL.md +5 -1
  101. package/template/.codex/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
  102. package/template/.codex/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
  103. package/template/.codex/skills/yss-cache/references/source-index.md +6 -63
  104. package/template/.codex/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
  105. package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
  106. package/template/.codex/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
  107. package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
  108. package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
  109. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
  110. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
  111. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
  112. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
  113. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  114. package/template/.codex/skills/yss-distributed-id/SKILL.md +4 -0
  115. package/template/.codex/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
  116. package/template/.codex/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
  117. package/template/.codex/skills/yss-distributed-id/references/source-index.md +6 -82
  118. package/template/.codex/skills/yss-dto/SKILL.md +2 -2
  119. package/template/.codex/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
  120. package/template/.codex/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
  121. package/template/.codex/skills/yss-dto/references/source-index.md +6 -51
  122. package/template/.codex/skills/yss-excel-mvc/SKILL.md +4 -0
  123. package/template/.codex/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
  124. package/template/.codex/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
  125. package/template/.codex/skills/yss-excel-mvc/references/source-index.md +6 -70
  126. package/template/.codex/skills/yss-exception/SKILL.md +12 -9
  127. package/template/.codex/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
  128. package/template/.codex/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
  129. package/template/.codex/skills/yss-exception/references/source-index.md +6 -31
  130. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  131. package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
  132. package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
  133. package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
  134. package/template/.codex/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
  135. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
  136. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
  137. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
  138. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
  139. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
  140. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
  141. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
  142. package/template/.codex/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
  143. package/template/.codex/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
  144. package/template/.codex/skills/yss-mvc-design/SKILL.md +5 -9
  145. package/template/.codex/skills/yss-mvc-design/agents/openai.yaml +3 -3
  146. package/template/.codex/skills/yss-mybatis/SKILL.md +2 -2
  147. package/template/.codex/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
  148. package/template/.codex/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
  149. package/template/.codex/skills/yss-mybatis/references/source-index.md +6 -109
  150. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
  151. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  152. package/template/.codex/skills/yss-repository/SKILL.md +1 -1
  153. package/template/.codex/skills/yss-resilience4j/SKILL.md +4 -0
  154. package/template/.codex/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
  155. package/template/.codex/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
  156. package/template/.codex/skills/yss-resilience4j/references/source-index.md +6 -29
  157. package/template/.codex/skills/yss-security-algorithm/SKILL.md +34 -10
  158. package/template/.codex/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
  159. package/template/.codex/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
  160. package/template/.codex/skills/yss-security-algorithm/references/source-index.md +6 -31
  161. package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
  162. package/template/.codex/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
  163. package/template/.codex/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
  164. package/template/.codex/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
  165. package/template/.codex/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
  166. package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
  167. package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
  168. package/template/.codex/skills/yss-tactical-design/SKILL.md +1 -1
  169. package/template/.codex/skills/yss-tactical-design/references/output-template.md +1 -1
  170. package/template/.codex/skills/yss-technical-design/SKILL.md +3 -1
  171. package/template/.codex/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
  172. package/template/.codex/skills/yss-technical-design/references/technical-design-contract.md +1 -1
  173. package/template/.codex/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
  174. package/template/.codex/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
  175. package/template/.codex/skills/yss-up-springboot3/SKILL.md +23 -9
  176. package/template/.codex/skills/yss-userinfo/SKILL.md +21 -14
  177. package/template/.codex/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
  178. package/template/.codex/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
  179. package/template/.codex/skills/yss-userinfo/references/source-index.md +6 -30
  180. package/template/.codex/skills/yss-validation/SKILL.md +12 -17
  181. package/template/.codex/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
  182. package/template/.codex/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
  183. package/template/.codex/skills/yss-validation/references/source-index.md +6 -29
  184. package/template/.codex/skills/yss-web-controller/SKILL.md +4 -4
  185. package/template/.codex/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
  186. package/template/.cursor/skills/yss-application/SKILL.md +8 -6
  187. package/template/.cursor/skills/yss-audit-log/SKILL.md +12 -7
  188. package/template/.cursor/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
  189. package/template/.cursor/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
  190. package/template/.cursor/skills/yss-audit-log/references/source-index.md +6 -39
  191. package/template/.cursor/skills/yss-cache/SKILL.md +5 -1
  192. package/template/.cursor/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
  193. package/template/.cursor/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
  194. package/template/.cursor/skills/yss-cache/references/source-index.md +6 -63
  195. package/template/.cursor/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
  196. package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
  197. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
  198. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
  199. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
  200. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
  201. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
  202. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
  203. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
  204. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  205. package/template/.cursor/skills/yss-distributed-id/SKILL.md +4 -0
  206. package/template/.cursor/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
  207. package/template/.cursor/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
  208. package/template/.cursor/skills/yss-distributed-id/references/source-index.md +6 -82
  209. package/template/.cursor/skills/yss-dto/SKILL.md +2 -2
  210. package/template/.cursor/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
  211. package/template/.cursor/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
  212. package/template/.cursor/skills/yss-dto/references/source-index.md +6 -51
  213. package/template/.cursor/skills/yss-excel-mvc/SKILL.md +4 -0
  214. package/template/.cursor/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
  215. package/template/.cursor/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
  216. package/template/.cursor/skills/yss-excel-mvc/references/source-index.md +6 -70
  217. package/template/.cursor/skills/yss-exception/SKILL.md +12 -9
  218. package/template/.cursor/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
  219. package/template/.cursor/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
  220. package/template/.cursor/skills/yss-exception/references/source-index.md +6 -31
  221. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  222. package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
  223. package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
  224. package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
  225. package/template/.cursor/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
  226. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
  227. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
  228. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
  229. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
  230. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
  231. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
  232. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
  233. package/template/.cursor/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
  234. package/template/.cursor/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
  235. package/template/.cursor/skills/yss-mvc-design/SKILL.md +5 -9
  236. package/template/.cursor/skills/yss-mvc-design/agents/openai.yaml +3 -3
  237. package/template/.cursor/skills/yss-mybatis/SKILL.md +2 -2
  238. package/template/.cursor/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
  239. package/template/.cursor/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
  240. package/template/.cursor/skills/yss-mybatis/references/source-index.md +6 -109
  241. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
  242. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  243. package/template/.cursor/skills/yss-repository/SKILL.md +1 -1
  244. package/template/.cursor/skills/yss-resilience4j/SKILL.md +4 -0
  245. package/template/.cursor/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
  246. package/template/.cursor/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
  247. package/template/.cursor/skills/yss-resilience4j/references/source-index.md +6 -29
  248. package/template/.cursor/skills/yss-security-algorithm/SKILL.md +34 -10
  249. package/template/.cursor/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
  250. package/template/.cursor/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
  251. package/template/.cursor/skills/yss-security-algorithm/references/source-index.md +6 -31
  252. package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
  253. package/template/.cursor/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
  254. package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
  255. package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
  256. package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
  257. package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
  258. package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
  259. package/template/.cursor/skills/yss-tactical-design/SKILL.md +1 -1
  260. package/template/.cursor/skills/yss-tactical-design/references/output-template.md +1 -1
  261. package/template/.cursor/skills/yss-technical-design/SKILL.md +3 -1
  262. package/template/.cursor/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
  263. package/template/.cursor/skills/yss-technical-design/references/technical-design-contract.md +1 -1
  264. package/template/.cursor/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
  265. package/template/.cursor/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
  266. package/template/.cursor/skills/yss-up-springboot3/SKILL.md +23 -9
  267. package/template/.cursor/skills/yss-userinfo/SKILL.md +21 -14
  268. package/template/.cursor/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
  269. package/template/.cursor/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
  270. package/template/.cursor/skills/yss-userinfo/references/source-index.md +6 -30
  271. package/template/.cursor/skills/yss-validation/SKILL.md +12 -17
  272. package/template/.cursor/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
  273. package/template/.cursor/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
  274. package/template/.cursor/skills/yss-validation/references/source-index.md +6 -29
  275. package/template/.cursor/skills/yss-web-controller/SKILL.md +4 -4
  276. package/template/.cursor/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
  277. package/template/.pi/skills/yss-application/SKILL.md +8 -6
  278. package/template/.pi/skills/yss-audit-log/SKILL.md +12 -7
  279. package/template/.pi/skills/yss-audit-log/references/source-index.boot2-java8.md +57 -0
  280. package/template/.pi/skills/yss-audit-log/references/source-index.boot3-java17.md +58 -0
  281. package/template/.pi/skills/yss-audit-log/references/source-index.md +6 -39
  282. package/template/.pi/skills/yss-cache/SKILL.md +5 -1
  283. package/template/.pi/skills/yss-cache/references/source-index.boot2-java8.md +81 -0
  284. package/template/.pi/skills/yss-cache/references/source-index.boot3-java17.md +83 -0
  285. package/template/.pi/skills/yss-cache/references/source-index.md +6 -63
  286. package/template/.pi/skills/yss-cache/scripts/check-skill-freshness.sh +20 -15
  287. package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
  288. package/template/.pi/skills/yss-ddd-scaffold-generator/references/engineering-baseline.md +53 -0
  289. package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +5 -51
  290. package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/agents/openai.yaml +3 -3
  291. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +1 -1
  292. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +2 -2
  293. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -3
  294. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +1 -1
  295. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  296. package/template/.pi/skills/yss-distributed-id/SKILL.md +4 -0
  297. package/template/.pi/skills/yss-distributed-id/references/source-index.boot2-java8.md +102 -0
  298. package/template/.pi/skills/yss-distributed-id/references/source-index.boot3-java17.md +90 -0
  299. package/template/.pi/skills/yss-distributed-id/references/source-index.md +6 -82
  300. package/template/.pi/skills/yss-dto/SKILL.md +2 -2
  301. package/template/.pi/skills/yss-dto/references/source-index.boot2-java8.md +67 -0
  302. package/template/.pi/skills/yss-dto/references/source-index.boot3-java17.md +70 -0
  303. package/template/.pi/skills/yss-dto/references/source-index.md +6 -51
  304. package/template/.pi/skills/yss-excel-mvc/SKILL.md +4 -0
  305. package/template/.pi/skills/yss-excel-mvc/references/source-index.boot2-java8.md +90 -0
  306. package/template/.pi/skills/yss-excel-mvc/references/source-index.boot3-java17.md +58 -0
  307. package/template/.pi/skills/yss-excel-mvc/references/source-index.md +6 -70
  308. package/template/.pi/skills/yss-exception/SKILL.md +12 -9
  309. package/template/.pi/skills/yss-exception/references/source-index.boot2-java8.md +50 -0
  310. package/template/.pi/skills/yss-exception/references/source-index.boot3-java17.md +50 -0
  311. package/template/.pi/skills/yss-exception/references/source-index.md +6 -31
  312. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  313. package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +3 -5
  314. package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +27 -2
  315. package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +2 -1
  316. package/template/.pi/skills/yss-implementation-contract-compiler/tests/compiler-scenarios.test.mjs +60 -14
  317. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +6 -5
  318. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/agents/openai.yaml +2 -2
  319. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/references/architecture.md +2 -0
  320. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/data-analysis-profile.mjs +82 -0
  321. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +23 -9
  322. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +30 -6
  323. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/tests/scaffold-generator.test.mjs +2 -0
  324. package/template/.pi/skills/yss-mvc-data-analysis-project-initializer/SKILL.md +5 -15
  325. package/template/.pi/skills/yss-mvc-data-analysis-project-initializer/scripts/generate_project.mjs +9 -68
  326. package/template/.pi/skills/yss-mvc-design/SKILL.md +5 -9
  327. package/template/.pi/skills/yss-mvc-design/agents/openai.yaml +3 -3
  328. package/template/.pi/skills/yss-mybatis/SKILL.md +2 -2
  329. package/template/.pi/skills/yss-mybatis/references/source-index.boot2-java8.md +126 -0
  330. package/template/.pi/skills/yss-mybatis/references/source-index.boot3-java17.md +126 -0
  331. package/template/.pi/skills/yss-mybatis/references/source-index.md +6 -109
  332. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +10 -8
  333. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  334. package/template/.pi/skills/yss-repository/SKILL.md +1 -1
  335. package/template/.pi/skills/yss-resilience4j/SKILL.md +4 -0
  336. package/template/.pi/skills/yss-resilience4j/references/source-index.boot2-java8.md +48 -0
  337. package/template/.pi/skills/yss-resilience4j/references/source-index.boot3-java17.md +48 -0
  338. package/template/.pi/skills/yss-resilience4j/references/source-index.md +6 -29
  339. package/template/.pi/skills/yss-security-algorithm/SKILL.md +34 -10
  340. package/template/.pi/skills/yss-security-algorithm/references/source-index.boot2-java8.md +50 -0
  341. package/template/.pi/skills/yss-security-algorithm/references/source-index.boot3-java17.md +51 -0
  342. package/template/.pi/skills/yss-security-algorithm/references/source-index.md +6 -31
  343. package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +12 -6
  344. package/template/.pi/skills/yss-skill-source-index-refresh/references/backend-component-platform-compatibility.md +27 -0
  345. package/template/.pi/skills/yss-skill-source-index-refresh/references/source-location.md +4 -4
  346. package/template/.pi/skills/yss-skill-source-index-refresh/references/source-map-config.md +10 -3
  347. package/template/.pi/skills/yss-skill-source-index-refresh/scripts/check-backend-skill-source-index.mjs +60 -0
  348. package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +247 -54
  349. package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +74 -7
  350. package/template/.pi/skills/yss-tactical-design/SKILL.md +1 -1
  351. package/template/.pi/skills/yss-tactical-design/references/output-template.md +1 -1
  352. package/template/.pi/skills/yss-technical-design/SKILL.md +3 -1
  353. package/template/.pi/skills/yss-technical-design/references/mvc-design.schema.json +315 -0
  354. package/template/.pi/skills/yss-technical-design/references/technical-design-contract.md +1 -1
  355. package/template/.pi/skills/yss-technical-design/scripts/generate-schema.mjs +1 -1
  356. package/template/.pi/skills/yss-technical-design/tests/run-scenarios.mjs +4 -1
  357. package/template/.pi/skills/yss-up-springboot3/SKILL.md +23 -9
  358. package/template/.pi/skills/yss-userinfo/SKILL.md +21 -14
  359. package/template/.pi/skills/yss-userinfo/references/source-index.boot2-java8.md +49 -0
  360. package/template/.pi/skills/yss-userinfo/references/source-index.boot3-java17.md +54 -0
  361. package/template/.pi/skills/yss-userinfo/references/source-index.md +6 -30
  362. package/template/.pi/skills/yss-validation/SKILL.md +12 -17
  363. package/template/.pi/skills/yss-validation/references/source-index.boot2-java8.md +47 -0
  364. package/template/.pi/skills/yss-validation/references/source-index.boot3-java17.md +47 -0
  365. package/template/.pi/skills/yss-validation/references/source-index.md +6 -29
  366. package/template/.pi/skills/yss-web-controller/SKILL.md +4 -4
  367. package/template/.pi/skills/yss-web-controller/scripts/generate_controller.test.mjs +1 -1
  368. package/template/docs/agents/backend-architecture-profiles.md +1 -1
  369. package/template/docs/agents/digital-human-roles.yaml +1 -1
  370. package/template/docs/agents/skill-migrations.md +23 -0
  371. package/template/docs/agents/yss-skill-registry.yaml +109 -40
  372. package/template/docs/api/templates/openapi-draft-review-checklist.md +1 -1
  373. package/template/docs/architecture/templates/engineering-baseline-review-template.md +3 -3
  374. package/template/docs/architecture/templates/system-overview-design-template.md +1 -1
  375. package/template/docs/engineering/backend-platforms.json +662 -9
  376. package/template/docs/engineering/backend-platforms.md +33 -7
  377. package/template/docs/process/schemas/backend-architecture-identity.schema.json +102 -0
  378. package/template/docs/process/schemas/project-scaffold-contract.schema.json +16 -4
  379. package/template/docs/process/schemas/scaffold-architecture-decisions.schema.json +7 -0
  380. package/template/docs/process/schemas/slice-implementation-contract-v3.schema.json +143 -0
  381. package/template/docs/process/strategic-handoff-package.md +1 -1
  382. package/template/docs/templates/implementation-routing-template.md +1 -1
  383. 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
  384. package/template/scripts/backend-platforms +77 -8
  385. package/template/scripts/lib/backend-platform.mjs +232 -5
  386. package/template/scripts/lib/existing-backend-architecture.mjs +3 -2
  387. package/template/scripts/lib/implementation-contract-compiler.mjs +93 -9
  388. package/template/scripts/lib/skill-registry.mjs +165 -12
  389. package/template/scripts/lib/slice-contract-preparation.mjs +6 -5
  390. package/template/scripts/verify-backend-platform-matrix +1 -1
  391. package/template/skills-lock.json +29 -29
  392. 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 !== 1 || value.kind !== "backend-platform-catalog" || !Array.isArray(value.profiles) || !Array.isArray(value.compatibility)) fail("invalid catalog");
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) if (!/^\d+\.\d+\.\d+$/.test(profile.spring_boot_version)) fail("catalog requires exact patch versions");
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
- return { schema_version: 2, profile_id: profile.id, spring_boot_version: profile.spring_boot_version, java_version: profile.java_version, parent: entry.parent, bom: entry.bom, compatibility_id: entry.id, compatibility_digest: platformRecipeDigest(profile, entry) };
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, { catalog = loadBackendPlatforms(), requireVerified = true, root = PLATFORM_ROOT } = {}) {
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 FIELDS=['schema_version','source_kind','architecture_family','architecture_profile','repository_id','project_id','source_digest','build_units_digest'];
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(FIELDS.every(k=>identity[k]!==undefined)&&Object.keys(identity).every(k=>FIELDS.includes(k)),'ARCH_IDENTITY_SHAPE','既有身份字段缺失或混入生成事实');
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 assertV2(registry, compilerContract) {
50
- if (registry?.schema_version !== 2) fail("技能注册表 schema v1 已停止支持;请迁移到 capability/typed-dependency v2");
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
- assertV2(registry, compilerContract);
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") fail(`deprecated/read-only Recipe ${recipe.id};必须按架构重新编译`);
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
- assertV2(registry, compilerContract);
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");