create-yss-spec 2.2.10 → 3.0.0

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 (381) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/template/.agents/skills/ask-matt/SKILL.md +1 -1
  4. package/template/.agents/skills/wayfinder/SKILL.md +2 -2
  5. package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  6. package/template/.agents/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  7. package/template/.agents/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  8. package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  9. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  10. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  11. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  12. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  13. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  14. package/template/.agents/skills/yss-domain/SKILL.md +2 -1
  15. package/template/.agents/skills/yss-domain/agents/openai.yaml +2 -2
  16. package/template/.agents/skills/yss-domain/references/domain-layer-guide.md +2 -0
  17. package/template/.agents/skills/yss-dto/SKILL.md +6 -0
  18. package/template/.agents/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  19. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +1 -1
  20. package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  21. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  22. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  23. package/template/.agents/skills/yss-repository/SKILL.md +15 -13
  24. package/template/.agents/skills/yss-repository/agents/openai.yaml +2 -2
  25. package/template/.agents/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  26. package/template/.agents/skills/yss-research/SKILL.md +73 -0
  27. package/template/.agents/skills/yss-research/agents/openai.yaml +3 -0
  28. package/template/.agents/skills/yss-research/assets/evidence-template.yaml +68 -0
  29. package/template/.agents/skills/yss-research/assets/research-brief-template.md +36 -0
  30. package/template/.agents/skills/yss-research/references/evidence-contract.md +42 -0
  31. package/template/.agents/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  32. package/template/.agents/skills/yss-research/tests/run-scenarios.mjs +81 -0
  33. package/template/.agents/skills/yss-router/references/router-contract.yaml +7 -3
  34. package/template/.agents/skills/yss-stage-decision/SKILL.md +2 -1
  35. package/template/.agents/skills/yss-web-controller/SKILL.md +16 -10
  36. package/template/.agents/skills/yss-web-controller/agents/openai.yaml +2 -2
  37. package/template/.agents/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  38. package/template/.agents/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  39. package/template/.agents/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  40. package/template/.agents/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  41. package/template/.agents/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  42. package/template/.agents/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  43. package/template/.agents/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  44. package/template/.agents/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  45. package/template/.agents/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  46. package/template/.claude/skills/ask-matt/SKILL.md +1 -1
  47. package/template/.claude/skills/wayfinder/SKILL.md +2 -2
  48. package/template/.claude/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  49. package/template/.claude/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  50. package/template/.claude/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  51. package/template/.claude/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  52. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  53. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  54. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  55. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  56. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  57. package/template/.claude/skills/yss-domain/SKILL.md +2 -1
  58. package/template/.claude/skills/yss-domain/agents/openai.yaml +2 -2
  59. package/template/.claude/skills/yss-domain/references/domain-layer-guide.md +2 -0
  60. package/template/.claude/skills/yss-dto/SKILL.md +6 -0
  61. package/template/.claude/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  62. package/template/.claude/skills/yss-product-lifecycle/SKILL.md +1 -1
  63. package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  64. package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  65. package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  66. package/template/.claude/skills/yss-repository/SKILL.md +15 -13
  67. package/template/.claude/skills/yss-repository/agents/openai.yaml +2 -2
  68. package/template/.claude/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  69. package/template/.claude/skills/yss-research/SKILL.md +73 -0
  70. package/template/.claude/skills/yss-research/agents/openai.yaml +3 -0
  71. package/template/.claude/skills/yss-research/assets/evidence-template.yaml +68 -0
  72. package/template/.claude/skills/yss-research/assets/research-brief-template.md +36 -0
  73. package/template/.claude/skills/yss-research/references/evidence-contract.md +42 -0
  74. package/template/.claude/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  75. package/template/.claude/skills/yss-research/tests/run-scenarios.mjs +81 -0
  76. package/template/.claude/skills/yss-router/references/router-contract.yaml +7 -3
  77. package/template/.claude/skills/yss-stage-decision/SKILL.md +2 -1
  78. package/template/.claude/skills/yss-web-controller/SKILL.md +16 -10
  79. package/template/.claude/skills/yss-web-controller/agents/openai.yaml +2 -2
  80. package/template/.claude/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  81. package/template/.claude/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  82. package/template/.claude/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  83. package/template/.claude/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  84. package/template/.claude/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  85. package/template/.claude/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  86. package/template/.claude/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  87. package/template/.claude/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  88. package/template/.claude/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  89. package/template/.codex/skills/ask-matt/SKILL.md +1 -1
  90. package/template/.codex/skills/product-design/package.json +4 -2
  91. package/template/.codex/skills/product-design/skills/research/SKILL.md +22 -0
  92. package/template/.codex/skills/product-design/skills/research/assets/evidence-template.yaml +65 -0
  93. package/template/.codex/skills/product-design/skills/research/assets/research-brief-template.md +33 -0
  94. package/template/.codex/skills/product-design/skills/research/references/evidence-audited.md +80 -0
  95. package/template/.codex/skills/product-design/skills/research/scripts/validate-research-package.mjs +149 -0
  96. package/template/.codex/skills/product-design/skills/research/tests/run-scenarios.mjs +72 -0
  97. package/template/.codex/skills/wayfinder/SKILL.md +2 -2
  98. package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  99. package/template/.codex/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  100. package/template/.codex/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  101. package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  102. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  103. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  104. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  105. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  106. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  107. package/template/.codex/skills/yss-domain/SKILL.md +2 -1
  108. package/template/.codex/skills/yss-domain/agents/openai.yaml +2 -2
  109. package/template/.codex/skills/yss-domain/references/domain-layer-guide.md +2 -0
  110. package/template/.codex/skills/yss-dto/SKILL.md +6 -0
  111. package/template/.codex/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  112. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +1 -1
  113. package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  114. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  115. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  116. package/template/.codex/skills/yss-repository/SKILL.md +15 -13
  117. package/template/.codex/skills/yss-repository/agents/openai.yaml +2 -2
  118. package/template/.codex/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  119. package/template/.codex/skills/yss-research/SKILL.md +73 -0
  120. package/template/.codex/skills/yss-research/agents/openai.yaml +3 -0
  121. package/template/.codex/skills/yss-research/assets/evidence-template.yaml +68 -0
  122. package/template/.codex/skills/yss-research/assets/research-brief-template.md +36 -0
  123. package/template/.codex/skills/yss-research/references/evidence-contract.md +42 -0
  124. package/template/.codex/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  125. package/template/.codex/skills/yss-research/tests/run-scenarios.mjs +81 -0
  126. package/template/.codex/skills/yss-router/references/router-contract.yaml +7 -3
  127. package/template/.codex/skills/yss-stage-decision/SKILL.md +2 -1
  128. package/template/.codex/skills/yss-web-controller/SKILL.md +16 -10
  129. package/template/.codex/skills/yss-web-controller/agents/openai.yaml +2 -2
  130. package/template/.codex/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  131. package/template/.codex/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  132. package/template/.codex/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  133. package/template/.codex/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  134. package/template/.codex/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  135. package/template/.codex/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  136. package/template/.codex/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  137. package/template/.codex/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  138. package/template/.codex/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  139. package/template/.cursor/skills/ask-matt/SKILL.md +1 -1
  140. package/template/.cursor/skills/wayfinder/SKILL.md +2 -2
  141. package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  142. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  143. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  144. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  145. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  146. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  147. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  148. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  149. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  150. package/template/.cursor/skills/yss-domain/SKILL.md +2 -1
  151. package/template/.cursor/skills/yss-domain/agents/openai.yaml +2 -2
  152. package/template/.cursor/skills/yss-domain/references/domain-layer-guide.md +2 -0
  153. package/template/.cursor/skills/yss-dto/SKILL.md +6 -0
  154. package/template/.cursor/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  155. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +1 -1
  156. package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  157. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  158. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  159. package/template/.cursor/skills/yss-repository/SKILL.md +15 -13
  160. package/template/.cursor/skills/yss-repository/agents/openai.yaml +2 -2
  161. package/template/.cursor/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  162. package/template/.cursor/skills/yss-research/SKILL.md +73 -0
  163. package/template/.cursor/skills/yss-research/agents/openai.yaml +3 -0
  164. package/template/.cursor/skills/yss-research/assets/evidence-template.yaml +68 -0
  165. package/template/.cursor/skills/yss-research/assets/research-brief-template.md +36 -0
  166. package/template/.cursor/skills/yss-research/references/evidence-contract.md +42 -0
  167. package/template/.cursor/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  168. package/template/.cursor/skills/yss-research/tests/run-scenarios.mjs +81 -0
  169. package/template/.cursor/skills/yss-router/references/router-contract.yaml +7 -3
  170. package/template/.cursor/skills/yss-stage-decision/SKILL.md +2 -1
  171. package/template/.cursor/skills/yss-web-controller/SKILL.md +16 -10
  172. package/template/.cursor/skills/yss-web-controller/agents/openai.yaml +2 -2
  173. package/template/.cursor/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  174. package/template/.cursor/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  175. package/template/.cursor/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  176. package/template/.cursor/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  177. package/template/.cursor/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  178. package/template/.cursor/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  179. package/template/.cursor/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  180. package/template/.cursor/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  181. package/template/.cursor/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  182. package/template/.hermes/skills/ask-matt/SKILL.md +1 -1
  183. package/template/.hermes/skills/wayfinder/SKILL.md +2 -2
  184. package/template/.hermes/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  185. package/template/.hermes/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  186. package/template/.hermes/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  187. package/template/.hermes/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  188. package/template/.hermes/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  189. package/template/.hermes/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  190. package/template/.hermes/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  191. package/template/.hermes/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  192. package/template/.hermes/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  193. package/template/.hermes/skills/yss-domain/SKILL.md +2 -1
  194. package/template/.hermes/skills/yss-domain/agents/openai.yaml +2 -2
  195. package/template/.hermes/skills/yss-domain/references/domain-layer-guide.md +2 -0
  196. package/template/.hermes/skills/yss-dto/SKILL.md +6 -0
  197. package/template/.hermes/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  198. package/template/.hermes/skills/yss-product-lifecycle/SKILL.md +1 -1
  199. package/template/.hermes/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  200. package/template/.hermes/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  201. package/template/.hermes/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  202. package/template/.hermes/skills/yss-repository/SKILL.md +15 -13
  203. package/template/.hermes/skills/yss-repository/agents/openai.yaml +2 -2
  204. package/template/.hermes/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  205. package/template/.hermes/skills/yss-research/SKILL.md +73 -0
  206. package/template/.hermes/skills/yss-research/agents/openai.yaml +3 -0
  207. package/template/.hermes/skills/yss-research/assets/evidence-template.yaml +68 -0
  208. package/template/.hermes/skills/yss-research/assets/research-brief-template.md +36 -0
  209. package/template/.hermes/skills/yss-research/references/evidence-contract.md +42 -0
  210. package/template/.hermes/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  211. package/template/.hermes/skills/yss-research/tests/run-scenarios.mjs +81 -0
  212. package/template/.hermes/skills/yss-router/references/router-contract.yaml +7 -3
  213. package/template/.hermes/skills/yss-stage-decision/SKILL.md +2 -1
  214. package/template/.hermes/skills/yss-web-controller/SKILL.md +16 -10
  215. package/template/.hermes/skills/yss-web-controller/agents/openai.yaml +2 -2
  216. package/template/.hermes/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  217. package/template/.hermes/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  218. package/template/.hermes/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  219. package/template/.hermes/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  220. package/template/.hermes/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  221. package/template/.hermes/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  222. package/template/.hermes/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  223. package/template/.hermes/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  224. package/template/.hermes/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  225. package/template/.pi/skills/ask-matt/SKILL.md +1 -1
  226. package/template/.pi/skills/wayfinder/SKILL.md +2 -2
  227. package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  228. package/template/.pi/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  229. package/template/.pi/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  230. package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  231. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  232. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  233. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  234. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  235. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  236. package/template/.pi/skills/yss-domain/SKILL.md +2 -1
  237. package/template/.pi/skills/yss-domain/agents/openai.yaml +2 -2
  238. package/template/.pi/skills/yss-domain/references/domain-layer-guide.md +2 -0
  239. package/template/.pi/skills/yss-dto/SKILL.md +6 -0
  240. package/template/.pi/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  241. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +1 -1
  242. package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  243. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  244. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  245. package/template/.pi/skills/yss-repository/SKILL.md +15 -13
  246. package/template/.pi/skills/yss-repository/agents/openai.yaml +2 -2
  247. package/template/.pi/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  248. package/template/.pi/skills/yss-research/SKILL.md +73 -0
  249. package/template/.pi/skills/yss-research/agents/openai.yaml +3 -0
  250. package/template/.pi/skills/yss-research/assets/evidence-template.yaml +68 -0
  251. package/template/.pi/skills/yss-research/assets/research-brief-template.md +36 -0
  252. package/template/.pi/skills/yss-research/references/evidence-contract.md +42 -0
  253. package/template/.pi/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  254. package/template/.pi/skills/yss-research/tests/run-scenarios.mjs +81 -0
  255. package/template/.pi/skills/yss-router/references/router-contract.yaml +7 -3
  256. package/template/.pi/skills/yss-stage-decision/SKILL.md +2 -1
  257. package/template/.pi/skills/yss-web-controller/SKILL.md +16 -10
  258. package/template/.pi/skills/yss-web-controller/agents/openai.yaml +2 -2
  259. package/template/.pi/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  260. package/template/.pi/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  261. package/template/.pi/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  262. package/template/.pi/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  263. package/template/.pi/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  264. package/template/.pi/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  265. package/template/.pi/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  266. package/template/.pi/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  267. package/template/.pi/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  268. package/template/.qoder/skills/ask-matt/SKILL.md +1 -1
  269. package/template/.qoder/skills/wayfinder/SKILL.md +2 -2
  270. package/template/.qoder/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  271. package/template/.qoder/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  272. package/template/.qoder/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  273. package/template/.qoder/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  274. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  275. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  276. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  277. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  278. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  279. package/template/.qoder/skills/yss-domain/SKILL.md +2 -1
  280. package/template/.qoder/skills/yss-domain/agents/openai.yaml +2 -2
  281. package/template/.qoder/skills/yss-domain/references/domain-layer-guide.md +2 -0
  282. package/template/.qoder/skills/yss-dto/SKILL.md +6 -0
  283. package/template/.qoder/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  284. package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +1 -1
  285. package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  286. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  287. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  288. package/template/.qoder/skills/yss-repository/SKILL.md +15 -13
  289. package/template/.qoder/skills/yss-repository/agents/openai.yaml +2 -2
  290. package/template/.qoder/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  291. package/template/.qoder/skills/yss-research/SKILL.md +73 -0
  292. package/template/.qoder/skills/yss-research/agents/openai.yaml +3 -0
  293. package/template/.qoder/skills/yss-research/assets/evidence-template.yaml +68 -0
  294. package/template/.qoder/skills/yss-research/assets/research-brief-template.md +36 -0
  295. package/template/.qoder/skills/yss-research/references/evidence-contract.md +42 -0
  296. package/template/.qoder/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  297. package/template/.qoder/skills/yss-research/tests/run-scenarios.mjs +81 -0
  298. package/template/.qoder/skills/yss-router/references/router-contract.yaml +7 -3
  299. package/template/.qoder/skills/yss-stage-decision/SKILL.md +2 -1
  300. package/template/.qoder/skills/yss-web-controller/SKILL.md +16 -10
  301. package/template/.qoder/skills/yss-web-controller/agents/openai.yaml +2 -2
  302. package/template/.qoder/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  303. package/template/.qoder/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  304. package/template/.qoder/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  305. package/template/.qoder/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  306. package/template/.qoder/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  307. package/template/.qoder/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  308. package/template/.qoder/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  309. package/template/.qoder/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  310. package/template/.qoder/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  311. package/template/.trae/skills/ask-matt/SKILL.md +1 -1
  312. package/template/.trae/skills/wayfinder/SKILL.md +2 -2
  313. package/template/.trae/skills/yss-ddd-scaffold-generator/SKILL.md +14 -3
  314. package/template/.trae/skills/yss-ddd-scaffold-generator/references/ARCHITECTURE.md +3 -3
  315. package/template/.trae/skills/yss-ddd-scaffold-generator/references/USAGE_EXAMPLES.md +12 -1
  316. package/template/.trae/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +2 -1
  317. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +45 -11
  318. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +164 -0
  319. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +18 -4
  320. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +172 -0
  321. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +14 -1
  322. package/template/.trae/skills/yss-domain/SKILL.md +2 -1
  323. package/template/.trae/skills/yss-domain/agents/openai.yaml +2 -2
  324. package/template/.trae/skills/yss-domain/references/domain-layer-guide.md +2 -0
  325. package/template/.trae/skills/yss-dto/SKILL.md +6 -0
  326. package/template/.trae/skills/yss-dto/references/openapi-wire-profile.yaml +6 -0
  327. package/template/.trae/skills/yss-product-lifecycle/SKILL.md +1 -1
  328. package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  329. package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +12 -10
  330. package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  331. package/template/.trae/skills/yss-repository/SKILL.md +15 -13
  332. package/template/.trae/skills/yss-repository/agents/openai.yaml +2 -2
  333. package/template/.trae/skills/yss-repository/references/infrastructure-layer-guide.md +1 -1
  334. package/template/.trae/skills/yss-research/SKILL.md +73 -0
  335. package/template/.trae/skills/yss-research/agents/openai.yaml +3 -0
  336. package/template/.trae/skills/yss-research/assets/evidence-template.yaml +68 -0
  337. package/template/.trae/skills/yss-research/assets/research-brief-template.md +36 -0
  338. package/template/.trae/skills/yss-research/references/evidence-contract.md +42 -0
  339. package/template/.trae/skills/yss-research/scripts/validate-research-package.mjs +128 -0
  340. package/template/.trae/skills/yss-research/tests/run-scenarios.mjs +81 -0
  341. package/template/.trae/skills/yss-router/references/router-contract.yaml +7 -3
  342. package/template/.trae/skills/yss-stage-decision/SKILL.md +2 -1
  343. package/template/.trae/skills/yss-web-controller/SKILL.md +16 -10
  344. package/template/.trae/skills/yss-web-controller/agents/openai.yaml +2 -2
  345. package/template/.trae/skills/yss-web-controller/assets/templates/Controller.java.template +11 -11
  346. package/template/.trae/skills/yss-web-controller/assets/templates/WebConvertor.java.template +4 -7
  347. package/template/.trae/skills/yss-web-controller/assets/templates/web/dto/CreateRequest.java.template +2 -2
  348. package/template/.trae/skills/yss-web-controller/assets/templates/web/dto/PageRequest.java.template +4 -7
  349. package/template/.trae/skills/yss-web-controller/assets/templates/web/dto/UpdateRequest.java.template +2 -2
  350. package/template/.trae/skills/yss-web-controller/references/web-adapter-layer-guide.md +6 -4
  351. package/template/.trae/skills/yss-web-controller/references/web-generation-contract.schema.json +97 -0
  352. package/template/.trae/skills/yss-web-controller/scripts/generate_controller.mjs +141 -20
  353. package/template/.trae/skills/yss-web-controller/scripts/generate_controller.test.mjs +131 -35
  354. package/template/AGENTS.md +2 -2
  355. package/template/CONTEXT.md +1 -1
  356. package/template/docs/agents/digital-human-roles.yaml +2 -2
  357. package/template/docs/agents/yss-skill-registry.yaml +18 -3
  358. package/template/docs/process/MATT-POCOCK-ENGINEERING-SKILLS.md +1 -0
  359. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +1 -1
  360. package/template/scripts/lib/scenario-checks.mjs +8 -4
  361. package/template/scripts/lib/skill-registry.mjs +49 -5
  362. package/template/scripts/lib/skill-supply-chain.mjs +3 -2
  363. package/template/scripts/verify-yss-dto-openapi-profile +8 -0
  364. package/template/skills-lock.json +30 -30
  365. package/template.snapshot.json +4 -4
  366. package/template/.agents/skills/research/SKILL.md +0 -12
  367. package/template/.agents/skills/research/agents/openai.yaml +0 -3
  368. package/template/.claude/skills/research/SKILL.md +0 -12
  369. package/template/.claude/skills/research/agents/openai.yaml +0 -3
  370. package/template/.codex/skills/research/SKILL.md +0 -12
  371. package/template/.codex/skills/research/agents/openai.yaml +0 -3
  372. package/template/.cursor/skills/research/SKILL.md +0 -12
  373. package/template/.cursor/skills/research/agents/openai.yaml +0 -3
  374. package/template/.hermes/skills/research/SKILL.md +0 -12
  375. package/template/.hermes/skills/research/agents/openai.yaml +0 -3
  376. package/template/.pi/skills/research/SKILL.md +0 -12
  377. package/template/.pi/skills/research/agents/openai.yaml +0 -3
  378. package/template/.qoder/skills/research/SKILL.md +0 -12
  379. package/template/.qoder/skills/research/agents/openai.yaml +0 -3
  380. package/template/.trae/skills/research/SKILL.md +0 -12
  381. package/template/.trae/skills/research/agents/openai.yaml +0 -3
package/README.md CHANGED
@@ -52,7 +52,7 @@ npx create-yss-spec@latest --version
52
52
 
53
53
  ## 当前版本说明
54
54
 
55
- 当前 CLI 版本为 `2.2.10`,模板固定到 `c2308bb36a1f835343af5de1ee9ec2666f9d18cb`,同步 YSS DDD Target Profile 严格边界、跨平台技能投影及最新 CLI gitlink。
55
+ 当前 CLI 版本为 `3.0.0`,模板固定到 `ec54212e2a3c3ab2f2496dc27c3979b6f2ecba03`。该主版本将 Web 生成升级为批准的 schema v2 合同,绑定 `yss-dto` wire profile,并要求通过完整首切片验证器后才能声明 `first-slice-verified`。
56
56
 
57
57
  ## 接管已有项目
58
58
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-yss-spec",
3
- "version": "2.2.10",
3
+ "version": "3.0.0",
4
4
  "description": "Initialize a YSS spec project template repository",
5
5
  "repository": {
6
6
  "type": "git",
@@ -84,7 +84,7 @@ Off the main flow entirely.
84
84
  - **`/grilling`** — the interview primitive itself: rounds, the frontier, facts are the agent's job and decisions are yours. `/grill-me` and `/grill-with-docs` are the two named ways in, and `/triage`, `/wayfinder` and `/improve-codebase-architecture` all run it internally. Reach for it directly only when you want the interview with no wrapper around it.
85
85
  - **`/resolving-merge-conflicts`** — work an in-progress merge or rebase conflict hunk by hunk, resolving by **intent** traced to each side's primary source rather than by picking lines, then finish the operation. It never runs `--abort`. Standalone and off every flow: reach for it when you are already mid-conflict.
86
86
  - **`/prototype`** — a small, throwaway program that answers one design question: does this state model feel right, or what should this UI look like. Throwaway is a constraint on how the code is written, not a promise to destroy it: the answer folds into the real code, and the prototype itself is kept as a **primary source** on a `prototype/<name>` branch out of main, pointed at from the implementation issue. It's the detour in step 2 of the main flow, but reach for it any time a design question is hard to settle on paper.
87
- - **`/research`** — delegate reading legwork to a **background agent**: it investigates a question against **primary sources**, then leaves a cited Markdown file in the repo. Keep working while it reads. The file it produces is something to take *into* the main flow at `/grill-with-docs` — research feeds the thinking, it doesn't replace it.
87
+ - **`/yss-research`** — investigate technical or strategy evidence using `technical-evidence` / `strategy-evidence` and `quick` / `evidence-audited` modes. Use a background agent when the runtime supports it and parallel reading is useful; delegation is not a trust guarantee. The old `/research` name is a deprecated alias. Research feeds `/grill-with-docs` and lifecycle decisions; it does not approve them.
88
88
  - **`/to-questionnaire`** — when the thing blocking you isn't in your head or the codebase but in **someone else's**, this writes them a questionnaire to fill in. It's the inverse of `/grill-me`: instead of interviewing you about the subject, it interviews you about the **send** — who it's going to, what you need back — and aims the questions at the gap. What comes back is material for `/grill-with-docs` or `/to-spec`.
89
89
  - **`/wait-what`** — the corrective for a message that didn't land. Use it mid-conversation, inside any other skill, and the agent re-pitches what it just said with the context you were missing, in plain English, using the `CONTEXT.md` vocabulary. It works after the fact; `/grill-with-docs` is the upfront cure, because a shared language agreed early is what stops the jargon arriving at all.
90
90
  - **`/teach`** — learn a concept over multiple sessions, using the current directory as a stateful workspace.
@@ -74,7 +74,7 @@ The answer isn't part of the body — it's recorded on resolution (see [Work thr
74
74
 
75
75
  Every ticket is either **HITL** — human in the loop, worked _with_ a human who speaks for themselves — or **AFK**, driven by the agent alone. A HITL ticket only resolves through that live exchange; the agent never stands in for the human's side of it (a grilling agent that answers its own questions has broken this).
76
76
 
77
- - **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a `/research` **subagent**. Use when knowledge outside the current working directory is required.
77
+ - **Research** (AFK): Reading documentation, third-party APIs, or local resources like knowledge bases to surface a fact a decision waits on. Resolved by a `/yss-research` **subagent** (`/research` is a deprecated alias). Use when knowledge outside the current working directory is required.
78
78
  - **Prototype** (HITL): Raise the fidelity of the discussion by making a cheap, rough, concrete artifact to react to — an outline, a rough take, a stub, or UI/logic code via the /prototype skill. Links the prototype as an asset. Use when "how should it look" or "how should it behave" is the key question.
79
79
  - **Grilling** (HITL): Conversation. The default case. Always invoke the /grilling and /domain-modeling skills.
80
80
  - **Task** (HITL or AFK): Manual work that must happen before a _decision_ can be made — nothing to decide, prototype, or research, but the discussion is blocked until it's done. Signing up for a service so its API can be judged, provisioning access, moving data so its shape can be seen. This is the one type that _does_ rather than decides — and it earns its place by unblocking a decision, not by delivering the destination. The agent drives it alone where it can (AFK); otherwise it hands the human a precise checklist (HITL). Resolved when the work is done; the answer records what was done and any resulting facts (credentials location, new URLs, row counts) later tickets depend on.
@@ -112,7 +112,7 @@ User invokes with a loose idea.
112
112
  2. **Map the frontier.** Grill again, **breadth-first** this time: fan out across the whole space rather than deep on any one thread, surfacing the open decisions and the first steps takeable now. **If this surfaces no fog** — the way to the destination is already clear, the whole journey small enough for one session — you don't need a map. Stop and ask the user how they'd like to proceed.
113
113
  3. **Create the map** (label `wayfinder:map`): Destination and Notes filled in, Decisions-so-far empty, the fog sketched into **Not yet specified**.
114
114
  4. **Create the tickets you can specify now** as child issues of the map — then wire blocking edges in a **second pass** (issues need ids before they can reference each other). Wiring sorts them into the frontier and the blocked; everything you can't yet specify stays in the fog — the **Not yet specified** section.
115
- 5. **Fire the research subagents.** For each `research` ticket you just created, spin up a `/research` subagent to resolve it in parallel, capturing its findings on a throwaway `research/<name>` branch with a context pointer from the ticket.
115
+ 5. **Fire the research subagents.** For each `research` ticket you just created, spin up a `/yss-research` subagent to resolve it in parallel, capturing its findings on a throwaway `research/<name>` branch with a context pointer from the ticket. `/research` remains only as a deprecated compatibility alias.
116
116
  6. Stop — charting is one session's work; it hand-resolves nothing.
117
117
 
118
118
  ### Work through the map
@@ -28,7 +28,7 @@ description: 用于生成完整的 YSS DDD 多模块后端脚手架。当用户
28
28
  2. 优先运行 `node scripts/generate_and_verify_scaffold.mjs`,在同一个受控工作流中生成骨架并执行真实 Maven 验证。`generate_scaffold.mjs` 只是底层生成原语,单独返回 0 不代表脚手架完成。
29
29
  3. 检查生成的模块名、POM、机械启动入口、基础配置文件和包路径。
30
30
  4. 受控工作流必须在生成项目根目录实际执行 `./mvnw validate`、`./mvnw test` 和 `./mvnw package`;三条命令全部返回 0 后才能报告完成。
31
- 5. 三条 Wrapper 命令通过只得到 `empty-scaffold-verified`。如需声称已满足下游技能的首切片就绪条件,必须再通过 golden first slice,得到 `first-slice-verified`。
31
+ 5. 三条 Wrapper 命令通过只得到 `empty-scaffold-verified`。如需声称已满足下游技能的首切片就绪条件,必须使用 `node scripts/run_first_slice_verification.mjs` 校验批准且版本当前的 Slice Implementation Contract、完整分层产物、skill tree digest 与根 Wrapper;只有验证器成功更新 Manifest 后才得到 `first-slice-verified`。
32
32
 
33
33
  受控验证命令由本 skill 的 `node scripts/run_scaffold_verification.mjs` 固定执行;验证器先检查 `.yss/scaffold-generation.json` 的合同元数据和 Wrapper、Java、项目级 Maven settings/profile、仓库凭据是否就绪,再在指定 evidence 目录写入每条命令的 stdout/stderr、`exit_code`、`failure_category`、耗时、执行时间和 `scaffold-verification.json`。仓库或凭据失败归为 `repository-access`,与 `project-model`、`compilation`、`bootstrap-entrypoint`、`test-failure`、`packaging` 分开;任何一条命令失败或未执行都必须阻断。
34
34
 
@@ -55,6 +55,15 @@ node scripts/generate_and_verify_scaffold.mjs \
55
55
  --evidence-dir /path/to/evidence/scaffold
56
56
  ```
57
57
 
58
+ 完成批准的 golden first slice 后运行:
59
+
60
+ ```bash
61
+ node scripts/run_first_slice_verification.mjs \
62
+ --project-root /path/to/implementation-repo/my-service \
63
+ --slice-contract-file /path/to/approved-slice-contract.json \
64
+ --evidence-dir /path/to/evidence/first-slice
65
+ ```
66
+
58
67
  ## 生成结果应包含
59
68
 
60
69
  - 父工程 POM
@@ -75,7 +84,7 @@ node scripts/generate_and_verify_scaffold.mjs \
75
84
  - Harness 内多项目布局必须使用 `apps/backend/<project>/`;`apps/backend/` 只能是生成器的父容器,`app/backend/`、`app/frontend/` 及其子路径一律拒绝。`git-submodule` gitlink、空挂载点、detached HEAD 工作树不得覆盖生成,即使传入 `--force` 也不得当成普通目录,且不得走「请显式传入 `--force`」普通目录覆盖 / rename 路径。`--output-dir` 指向 detached HEAD 子仓时不得 mkdir、staging 或生成工程。先 `git submodule update --init` 并在子仓附加分支工作树内生成。生成器必须先调用 `gitSubmoduleScaffoldViolation`,再在 exists / `--force` / rename 之前调用 `refuseGitlinkAsRegularDirectory`。
76
85
  - 不要在 skill 里硬编码用户业务字段或真实连接信息。
77
86
  - 生成后要检查依赖关系是否仍符合分层约束。
78
- - 生成后必须继续使用 `yss-backend-scaffold-parent` 校验工程基线,再按垂直切片加载 `yss-domain`、`yss-application`、`yss-repository`、`yss-web-controller` 等行为 skill;各 skill 的 `references/*-layer-guide.md` 承载分层开发规范。
87
+ - 生成时的静态依赖由技能注册表与 Router 共同约束为 `yss-backend-scaffold-parent`、`alibaba-java-code-style`。生成后必须回到 Router,并按批准切片加载 `yss-domain`、`yss-application`、`yss-repository`、`yss-mybatis`、`yss-web-controller`、`yss-dto`、`yss-exception`、`yss-validation`、`mapstruct`、`lombok`、`alibaba-java-code-style` 等实际命中的行为 skill。
79
88
  - 当前脚手架第一阶段仅支持经过验证的 `mysql`;未提供完整模板和验证的数据库类型不得伪装成已支持。
80
89
  - 生成后的后端工程必须使用项目根目录 `./mvnw ...` 执行构建、测试、运行和 CI 验证;不得在 README、实施记录、Ticket、Review 或 Release 中默认写裸 `mvn ...`。既有仓库确实无法使用 wrapper 时,必须记录受控例外。
81
90
  - 原型确认后,`scaffold_status=required` 才能进入本 skill;本 skill 的生成边界是工程结构、POM、配置、Wrapper 和机械模板,不是业务实现。
@@ -83,7 +92,8 @@ node scripts/generate_and_verify_scaffold.mjs \
83
92
  - 新脚手架合同只接受 schema v2,必须分别携带 `project_name`、`base_package` 和 `maven_coordinates`;后者包含项目 `group_id` / `project_version`、父 POM GAV 与 `yss_components_version`,并由 CLI 原样传入。schema v1 为 `unsupported`,直接拒绝且不自动升级。
84
93
  - 合同 `profiles` 只支持 `target-domain-model`、`mybatis-plus`、`mysql`、`spring-boot-2.7-jdk8`、`javax`、`web`、`yss-internal`。普通 MyBatis、Boot 3、独立 client module、client-in-domain 和其他旧架构均为 `unsupported`,不提供回退分支。
85
94
  - 运行生成器必须传入 `--contract-file`;生成器会校验合同 `status=approved`、`current_version`、`primary_skill`、`controlled-generation`、实际输出路径和固定三条验证命令,不接受仅凭任意字符串引用的放行。
86
- - 生成项目必须写入 Manifest v2 `.yss/scaffold-generation.json`,记录合同 digest、Target Profile、模板 digest、下游 skill hash、generator-owned 文件 hash、严格 `generation_policy` 和完成等级;清单缺失或不一致时不得交给后续 Router。
95
+ - 生成项目必须写入 Manifest v2 `.yss/scaffold-generation.json`,记录合同 digest、Target Profile、模板 digest、下游完整 skill tree digest、脚手架父合同与 Router 合同 digest、generator-owned 文件 hash、严格 `generation_policy` 和完成等级;清单缺失或不一致时不得交给后续 Router。
96
+ - `first-slice-verified` 只能由 `run_first_slice_verification.mjs` 写入。手工改 Manifest、只生成 Controller、只通过局部模块测试或仅有结构扫描都不能升级完成等级。
87
97
  - 严禁把领域规则、状态机、权限、事务、复杂查询、错误映射、业务字段或用户可见行为塞进脚手架生成步骤。`./mvnw validate`、输出目录存在或“生成成功”都不等于生命周期批准、架构放行或 `ready-for-agent`。
88
98
  - 生命周期脚手架生成必须关闭 `--with-example`,不得把 User CRUD 或业务字段当作样板。生成器严格 `initialize-only`:非空目标、`--force`、旧项目迁移和当前模板升级一律 `unsupported`。未来若支持同一 Target Profile 内的模板升级,必须另行设计和批准,当前不预留可执行承诺。
89
99
  - 脚手架完成后,所有后续生成的后端代码必须回到 `yss-router`,消费批准且版本当前的 Slice Implementation Contract 和对应 YSS skill;业务行为使用 `behavior-tdd`,机械生成才使用 `controlled-generation`。
@@ -98,6 +108,7 @@ node scripts/generate_and_verify_scaffold.mjs \
98
108
  - 主脚本:`scripts/generate_scaffold.mjs`
99
109
  - 推荐的一键生成验证入口:`scripts/generate_and_verify_scaffold.mjs`
100
110
  - 受控验证器:`scripts/run_scaffold_verification.mjs`
111
+ - 首切片验证器:`scripts/run_first_slice_verification.mjs`
101
112
  - 模板目录:`assets/templates/`
102
113
  - 分层细化参考:`references/yss-backend-scaffold-parent/` 及其子 skill
103
114
 
@@ -104,13 +104,13 @@ Domain Error -> Application propagation/translation -> Web Exception Translator
104
104
 
105
105
  - Scaffold 只生成机械模块、POM、Wrapper、配置、架构规则和 Manifest,不生成生产业务 CRUD。
106
106
  - 初始生成器为 `initialize-only`,非空目标失败。
107
- - Manifest v2 记录模板/合同/downstream skill digest 与 generator-owned 文件 hash。
107
+ - Manifest v2 记录模板、脚手架父合同、Router 合同、downstream 完整 skill tree digest 与 generator-owned 文件 hash。
108
108
  - 当前不支持模板升级,不得重跑初始生成器覆盖业务工程。未来如需支持同一 Target Profile 内的模板版本升级,必须另行设计、批准并验证。
109
109
 
110
110
  ## 5. 完成等级
111
111
 
112
112
  - `generated`:文件已原子生成,尚未完成 Wrapper 验证。
113
113
  - `empty-scaffold-verified`:根目录 `./mvnw validate/test/package` 全部通过。
114
- - `first-slice-verified`:golden first slice 的 Domain、Application、Repository/MyBatis、DTO/Web、Exception、Wire 与架构负例全部通过。
114
+ - `first-slice-verified`:批准且版本当前的 golden first slice 已具备 Domain 模型/Gateway、Application Service 实现/事务/Query Port、Repository/Mapper/GatewayImpl/QueryAdapter、DTO/Web/Exception 与分层测试;下游完整 skill tree digest 无漂移,且根 Wrapper 全部通过。该状态只能由 `scripts/run_first_slice_verification.mjs` 写入。
115
115
 
116
- 只有最后一级可以声明已满足下游 YSS skills 的首切片就绪条件。
116
+ 只有首切片验证器可以把 Manifest 从 `empty-scaffold-verified` 升级到最后一级;手工写值、局部测试或结构扫描均无效。只有最后一级可以声明已满足下游 YSS skills 的首切片就绪条件。
@@ -102,7 +102,18 @@ metadata-service/
102
102
 
103
103
  ## 4. 后续路由
104
104
 
105
- `empty-scaffold-verified` 不等于业务切片可实现。后续必须回到 `yss-router`,消费批准且版本当前的 Slice Implementation Contract,再按影响面加载 `yss-domain`、`yss-application`、`yss-repository`、`yss-mybatis`、`yss-dto`、`yss-exception`、`yss-web-controller` 等 skill,并使用 `behavior-tdd` 实现业务行为。只有 golden first slice 全部通过才能标记 `first-slice-verified`。
105
+ `empty-scaffold-verified` 不等于业务切片可实现。后续必须回到 `yss-router`,消费批准且版本当前的 Slice Implementation Contract,再按影响面加载 `yss-domain`、`yss-application`、`yss-repository`、`yss-mybatis`、`yss-web-controller`、`yss-dto`、`yss-exception`、`yss-validation`、`mapstruct`、`lombok`、`alibaba-java-code-style` 等 skill,并使用 `behavior-tdd` 实现业务行为。
106
+
107
+ 完成 golden first slice 后,必须运行:
108
+
109
+ ```bash
110
+ node .agents/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs \
111
+ --project-root /path/to/implementation-repo/metadata-service \
112
+ --slice-contract-file /path/to/approved-slice-contract.json \
113
+ --evidence-dir /path/to/evidence/first-slice
114
+ ```
115
+
116
+ 只有该验证器确认合同、全层产物、skill tree digest 与根 Wrapper 全部通过,并更新 Manifest 后,才能标记 `first-slice-verified`。
106
117
 
107
118
  目标目录必须不存在。`--force`、旧项目迁移和当前模板升级均为 `unsupported`。旧项目继续按原工程维护;现代化改造必须单独立项、先评估再逐切片迁移。
108
119
 
@@ -45,7 +45,7 @@ infrastructure-+
45
45
  - Maven 内部仓库通过命名 profile `yss-internal` 与环境变量注入;共享模板不写内部 URL 或凭据。
46
46
  - Wrapper 必须带 checksum;DEBUG 和 MyBatis stdout SQL 只允许在 `application-local.yml`。
47
47
  - `./mvnw validate`、`./mvnw test`、`./mvnw package` 全部成功只得到 `empty-scaffold-verified`。
48
- - 只有 golden first slice 真实组合 Domain/Application/Infrastructure/Web 并通过根 Wrapper,才能得到 `first-slice-verified`。
48
+ - 只有批准且版本当前的 golden first slice 真实组合 Domain/Application/Infrastructure/Web、通过下游 skill tree drift 校验与根 Wrapper,才能由 `run_first_slice_verification.mjs` 写入 `first-slice-verified`。
49
49
 
50
50
  ## 下游权威技能
51
51
 
@@ -53,5 +53,6 @@ infrastructure-+
53
53
  - Application:`yss-application`
54
54
  - Persistence:`yss-repository` + `yss-mybatis`
55
55
  - Web:`yss-web-controller` + `yss-dto` + `yss-exception`
56
+ - 横切实现约束:`yss-validation` + `mapstruct` + `lombok` + `alibaba-java-code-style`
56
57
 
57
58
  业务代码必须回到 `yss-router`,消费批准且版本当前的 Slice Implementation Contract,并采用 `behavior-tdd`;脚手架只生成机械工程资产。
@@ -1,5 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { execFile } from "node:child_process";
3
+ import { createHash } from "node:crypto";
3
4
  import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
5
  import os from "node:os";
5
6
  import path from "node:path";
@@ -7,9 +8,11 @@ import test from "node:test";
7
8
  import { fileURLToPath } from "node:url";
8
9
 
9
10
  import { generate as generateWeb, parseArgs as parseWebArgs } from "../../yss-web-controller/scripts/generate_controller.mjs";
11
+ import { runFirstSliceVerification } from "./run_first_slice_verification.mjs";
10
12
 
11
13
  const scripts = path.dirname(fileURLToPath(import.meta.url));
12
14
  const generator = path.join(scripts, "generate_scaffold.mjs");
15
+ const dtoWireProfileFile = path.resolve(scripts, "../../yss-dto/references/openapi-wire-profile.yaml");
13
16
  const execute = (file, args, options = {}) => new Promise((resolve) => execFile(file, args, { encoding: "utf8", ...options }, (error, stdout, stderr) => resolve({ code: error?.code ?? 0, stdout, stderr })));
14
17
 
15
18
  function scaffoldContract(output) {
@@ -57,12 +60,19 @@ async function prepareGoldenProject(t) {
57
60
  const generated = await execute(process.execPath, [generator, ...args]);
58
61
  assert.equal(generated.code, 0, generated.stderr);
59
62
  const project = path.join(output, "golden-service");
63
+ const manifestPath = path.join(project, ".yss", "scaffold-generation.json");
64
+ const emptyVerificationPath = path.join(root, "empty-scaffold-verification.json");
65
+ await writeFile(emptyVerificationPath, JSON.stringify({ status: "passed", completion_level: "empty-scaffold-verified", commands: ["./mvnw validate", "./mvnw test", "./mvnw package"] }));
66
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
67
+ manifest.completion_level = "empty-scaffold-verified";
68
+ manifest.empty_scaffold_verification_ref = emptyVerificationPath;
69
+ await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
60
70
  const java = "src/main/java/com/yss/golden";
61
71
  const testJava = "src/test/java/com/yss/golden";
62
72
  await writeJava(project, `golden-service-domain/${java}/domain/quality/model/QualityRule.java`, `package com.yss.golden.domain.quality.model;
63
73
  public final class QualityRule { private final Long id; private final String name; public QualityRule(Long id, String name) { if (name == null || name.trim().isEmpty()) throw new IllegalArgumentException("quality-rule-name-required"); this.id=id; this.name=name; } public Long getId(){return id;} public String getName(){return name;} }`);
64
74
  await writeJava(project, `golden-service-domain/${java}/domain/quality/gateway/QualityRuleGateway.java`, `package com.yss.golden.domain.quality.gateway;
65
- import com.yss.golden.domain.quality.model.QualityRule; public interface QualityRuleGateway { void save(QualityRule rule); }`);
75
+ import com.yss.golden.domain.quality.model.QualityRule; import java.util.Optional; public interface QualityRuleGateway { Optional<QualityRule> findById(Long id); void save(QualityRule rule); void delete(Long id); }`);
66
76
  await writeJava(project, `golden-service-domain/${testJava}/domain/quality/model/QualityRuleTest.java`, `package com.yss.golden.domain.quality.model;
67
77
  import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertThrows; class QualityRuleTest { @Test void rejectsBlankName(){ assertThrows(IllegalArgumentException.class, () -> new QualityRule(1L, " ")); } }`);
68
78
  for (const [relative, source] of Object.entries({
@@ -72,16 +82,26 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertion
72
82
  [`golden-service-application/${java}/application/result/QualityRuleResult.java`]: `package com.yss.golden.application.result; import java.io.Serializable; public class QualityRuleResult implements Serializable { private Long id; private String ruleName; public Long getId(){return id;} public void setId(Long value){this.id=value;} public String getRuleName(){return ruleName;} public void setRuleName(String value){this.ruleName=value;} }`,
73
83
  [`golden-service-application/${java}/application/port/QualityRuleQueryPort.java`]: `package com.yss.golden.application.port; import com.yss.cloud.dto.result.PageResult; import com.yss.golden.application.query.QualityRulePageQuery; import com.yss.golden.application.result.QualityRuleResult; public interface QualityRuleQueryPort { PageResult<QualityRuleResult> page(QualityRulePageQuery query); }`,
74
84
  [`golden-service-application/${java}/application/service/QualityRuleService.java`]: `package com.yss.golden.application.service; import com.yss.cloud.dto.result.PageResult; import com.yss.golden.application.command.*; import com.yss.golden.application.query.QualityRulePageQuery; import com.yss.golden.application.result.QualityRuleResult; public interface QualityRuleService { PageResult<QualityRuleResult> page(QualityRulePageQuery query); QualityRuleResult detail(Long id); Long add(QualityRuleCreateCommand command); Boolean update(QualityRuleUpdateCommand command); Boolean delete(Long id); }`,
85
+ [`golden-service-application/${java}/application/service/impl/QualityRuleServiceImpl.java`]: `package com.yss.golden.application.service.impl;
86
+ import com.yss.cloud.dto.result.PageResult; import com.yss.golden.application.command.*; import com.yss.golden.application.port.QualityRuleQueryPort; import com.yss.golden.application.query.QualityRulePageQuery; import com.yss.golden.application.result.QualityRuleResult; import com.yss.golden.application.service.QualityRuleService; import com.yss.golden.domain.quality.gateway.QualityRuleGateway; import com.yss.golden.domain.quality.model.QualityRule; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;
87
+ @Service public class QualityRuleServiceImpl implements QualityRuleService { private final QualityRuleGateway gateway; private final QualityRuleQueryPort queryPort; public QualityRuleServiceImpl(QualityRuleGateway gateway, QualityRuleQueryPort queryPort){this.gateway=gateway;this.queryPort=queryPort;} public PageResult<QualityRuleResult> page(QualityRulePageQuery query){return queryPort.page(query);} public QualityRuleResult detail(Long id){QualityRule rule=gateway.findById(id).orElseThrow(IllegalArgumentException::new); QualityRuleResult result=new QualityRuleResult(); result.setId(rule.getId()); result.setRuleName(rule.getName()); return result;} @Transactional public Long add(QualityRuleCreateCommand command){QualityRule rule=new QualityRule(null, command.getRuleName()); gateway.save(rule); return rule.getId();} @Transactional public Boolean update(QualityRuleUpdateCommand command){gateway.save(new QualityRule(command.getId(), command.getRuleName())); return true;} @Transactional public Boolean delete(Long id){gateway.delete(id); return true;} }`,
75
88
  [`golden-service-application/${java}/application/error/QualityRuleConflictException.java`]: `package com.yss.golden.application.error; public final class QualityRuleConflictException extends RuntimeException { public QualityRuleConflictException(String message) { super(message); } }`,
76
89
  [`golden-service-application/${java}/application/error/QualityRuleSystemException.java`]: `package com.yss.golden.application.error; public final class QualityRuleSystemException extends RuntimeException { public QualityRuleSystemException(String message, Throwable cause) { super(message, cause); } }`,
77
90
  [`golden-service-infrastructure/${java}/infrastructure/persistence/po/QualityRulePO.java`]: `package com.yss.golden.infrastructure.persistence.po; public class QualityRulePO { private Long id; private String name; public Long getId(){return id;} public void setId(Long value){this.id=value;} public String getName(){return name;} public void setName(String value){this.name=value;} }`,
78
- [`golden-service-infrastructure/${java}/infrastructure/persistence/convertor/QualityRulePersistenceConvertor.java`]: `package com.yss.golden.infrastructure.persistence.convertor; import com.yss.golden.domain.quality.model.QualityRule; import com.yss.golden.infrastructure.persistence.po.QualityRulePO; import org.mapstruct.Mapper; @Mapper(componentModel="spring") public interface QualityRulePersistenceConvertor { QualityRule toDomain(QualityRulePO source); QualityRulePO toPO(QualityRule source); }`
91
+ [`golden-service-infrastructure/${java}/infrastructure/persistence/convertor/QualityRulePersistenceConvertor.java`]: `package com.yss.golden.infrastructure.persistence.convertor; import com.yss.golden.domain.quality.model.QualityRule; import com.yss.golden.infrastructure.persistence.po.QualityRulePO; import org.mapstruct.Mapper; @Mapper(componentModel="spring") public interface QualityRulePersistenceConvertor { QualityRule toDomain(QualityRulePO source); QualityRulePO toPO(QualityRule source); }`,
92
+ [`golden-service-infrastructure/${java}/infrastructure/persistence/repository/QualityRuleRepository.java`]: `package com.yss.golden.infrastructure.persistence.repository; import com.yss.golden.infrastructure.persistence.po.QualityRulePO; import java.util.List; import org.apache.ibatis.annotations.*; @Mapper public interface QualityRuleRepository { @Select("select id, rule_name as name from quality_rule where id = #{id}") QualityRulePO selectById(Long id); @Select("select id, rule_name as name from quality_rule") List<QualityRulePO> selectAll(); @Insert("insert into quality_rule(rule_name) values(#{name})") int insert(QualityRulePO po); @Delete("delete from quality_rule where id = #{id}") int deleteById(Long id); }`,
93
+ [`golden-service-infrastructure/${java}/infrastructure/persistence/gateway/QualityRuleGatewayImpl.java`]: `package com.yss.golden.infrastructure.persistence.gateway; import com.yss.golden.domain.quality.gateway.QualityRuleGateway; import com.yss.golden.domain.quality.model.QualityRule; import com.yss.golden.infrastructure.persistence.convertor.QualityRulePersistenceConvertor; import com.yss.golden.infrastructure.persistence.repository.QualityRuleRepository; import java.util.Optional; import org.springframework.stereotype.Repository; @Repository public class QualityRuleGatewayImpl implements QualityRuleGateway { private final QualityRuleRepository repository; private final QualityRulePersistenceConvertor convertor; public QualityRuleGatewayImpl(QualityRuleRepository repository, QualityRulePersistenceConvertor convertor){this.repository=repository;this.convertor=convertor;} public Optional<QualityRule> findById(Long id){return Optional.ofNullable(repository.selectById(id)).map(convertor::toDomain);} public void save(QualityRule rule){repository.insert(convertor.toPO(rule));} public void delete(Long id){repository.deleteById(id);} }`,
94
+ [`golden-service-infrastructure/${java}/infrastructure/query/adapter/QualityRuleQueryAdapter.java`]: `package com.yss.golden.infrastructure.query.adapter; import com.yss.cloud.dto.result.PageResult; import com.yss.golden.application.port.QualityRuleQueryPort; import com.yss.golden.application.query.QualityRulePageQuery; import com.yss.golden.application.result.QualityRuleResult; import java.util.Collections; import org.springframework.stereotype.Repository; @Repository public class QualityRuleQueryAdapter implements QualityRuleQueryPort { public PageResult<QualityRuleResult> page(QualityRulePageQuery query){return PageResult.of(Collections.emptyList(), 0L, query.getPageSize(), query.getPageIndex());} }`
79
95
  })) await writeJava(project, relative, source);
96
+ await writeJava(project, `golden-service-application/${testJava}/application/service/QualityRuleServiceTest.java`, `package com.yss.golden.application.service; import com.yss.golden.application.command.QualityRuleCreateCommand; import com.yss.golden.application.port.QualityRuleQueryPort; import com.yss.golden.application.service.impl.QualityRuleServiceImpl; import com.yss.golden.domain.quality.gateway.QualityRuleGateway; import org.junit.jupiter.api.Test; import static org.mockito.Mockito.*; class QualityRuleServiceTest { @Test void createPersistsThroughDomainGateway(){QualityRuleGateway gateway=mock(QualityRuleGateway.class); QualityRuleCreateCommand command=new QualityRuleCreateCommand(); command.setRuleName("rule"); new QualityRuleServiceImpl(gateway, mock(QualityRuleQueryPort.class)).add(command); verify(gateway).save(any());} }`);
97
+ await writeJava(project, `golden-service-infrastructure/${testJava}/infrastructure/persistence/QualityRuleGatewayIntegrationTest.java`, `package com.yss.golden.infrastructure.persistence; import com.yss.golden.infrastructure.persistence.convertor.QualityRulePersistenceConvertor; import com.yss.golden.infrastructure.persistence.po.QualityRulePO; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; import static org.junit.jupiter.api.Assertions.assertEquals; class QualityRuleGatewayIntegrationTest { @Test void persistenceMappingRoundTrips(){QualityRulePO po=new QualityRulePO(); po.setId(1L); po.setName("rule"); assertEquals("rule", Mappers.getMapper(QualityRulePersistenceConvertor.class).toDomain(po).getName());} }`);
80
98
  const metadata = path.join(root, "metadata.json");
81
99
  const webContract = path.join(root, "web-contract.json");
100
+ const dtoWireProfileDigest = createHash("sha256").update(await readFile(dtoWireProfileFile)).digest("hex");
82
101
  await writeFile(metadata, JSON.stringify({ tables: [{ table_name: "quality_rule", table_comment: "质量规则", columns: [{ name: "id", sql_type: "bigint", primary: true, nullable: false }, { name: "rule_name", sql_type: "varchar(64)", nullable: false }] }] }));
83
- await writeFile(webContract, JSON.stringify({ schema_version: 1, status: "approved", base_package: "com.yss.golden", module_name: "golden", domain_segment: "quality", architecture_profile: "target-domain-model", platform_profile: "spring-boot-2.7-jdk8", validation_namespace: "javax", dto_placement: "web", openapi_freeze_ref: "openapi://quality-rule@1", fields: { quality_rule: { create: ["rule_name"], update: ["id", "rule_name"], query: ["rule_name"], response: ["id", "rule_name"] } } }));
84
- await generateWeb(parseWebArgs(["--metadata-file", metadata, "--contract-file", webContract, "--base-package", "com.yss.golden", "--module-name", "golden", "--domain-segment", "quality", "--web-project-dir", path.join(project, "golden-service-adapter", "golden-service-web"), "--application-service-package", "com.yss.golden.application.service", "--validation-namespace", "javax"]), { log() {}, warn() {} });
102
+ const webProject = path.join(project, "golden-service-adapter", "golden-service-web");
103
+ await writeFile(webContract, JSON.stringify({ schema_version: 2, contract_id: "golden-slice-1", contract_version: 1, current_version: 1, slice_id: "quality-rule-first-slice", status: "approved", integration_mode: "scaffold-v2", implementation_project_root: project, scaffold_manifest_ref: manifestPath, base_package: "com.yss.golden", module_name: "golden", domain_segment: "quality", application_service_package: "com.yss.golden.application.service", architecture_profile: "target-domain-model", platform_profile: "spring-boot-2.7-jdk8", validation_namespace: "javax", dto_placement: "web", dto_wire_profile_ref: dtoWireProfileFile, dto_wire_profile_digest: dtoWireProfileDigest, openapi_freeze_ref: "openapi://quality-rule@1", allowed_write_paths: [path.join(webProject, "src/main/java/com/yss/golden/rest")], expected_evidence_files: ["first-slice-verification.json"], verification_commands: ["./mvnw test", "./mvnw package"], fields: { quality_rule: { create: ["rule_name"], update: ["id", "rule_name"], query: ["rule_name"], pagination: ["pageIndex", "pageSize"], response: ["id", "rule_name"] } } }));
104
+ await generateWeb(parseWebArgs(["--metadata-file", metadata, "--contract-file", webContract, "--dto-wire-profile-file", dtoWireProfileFile, "--scaffold-manifest-file", manifestPath, "--base-package", "com.yss.golden", "--module-name", "golden", "--domain-segment", "quality", "--web-project-dir", webProject, "--application-service-package", "com.yss.golden.application.service", "--validation-namespace", "javax"]), { log() {}, warn() {} });
85
105
  await writeJava(project, `golden-service-adapter/golden-service-web/${java}/rest/advice/TargetProfileExceptionAdvice.java`, `package com.yss.golden.rest.advice;
86
106
  import com.yss.golden.application.error.QualityRuleConflictException;
87
107
  import com.yss.golden.application.error.QualityRuleSystemException;
@@ -147,7 +167,10 @@ class GoldenExceptionIntegrationTest {
147
167
  @GetMapping("/exception-probe/unknown") void unknown() { throw new RuntimeException("runtime-secret"); }
148
168
  }
149
169
  }`);
150
- return { root, project };
170
+ const sliceContract = path.join(root, "slice-contract.json");
171
+ const requiredSkills = ["yss-domain", "yss-application", "yss-repository", "yss-mybatis", "yss-web-controller", "yss-dto", "yss-exception", "yss-validation", "mapstruct", "lombok", "alibaba-java-code-style"];
172
+ await writeFile(sliceContract, JSON.stringify({ schema_version: 1, contract_id: "golden-slice-1", contract_version: 1, slice_id: "quality-rule-first-slice", status: "approved", readiness: { blockers: [], stale_inputs: [] }, common: { required_skills: requiredSkills }, backend: { status: "required", affected_layers: ["domain", "application", "infrastructure", "web"], required_skills: requiredSkills }, work_units: [{ id: "slice-backend", contract_id: "golden-slice-1", contract_version: 1, work_unit: { primary_skill: "yss-domain" } }] }));
173
+ return { root, project, sliceContract };
151
174
  }
152
175
 
153
176
  test("golden first slice 组合 Domain/Application/Infrastructure/Web 且不发生 DTO/PO 穿层", async (t) => {
@@ -158,25 +181,36 @@ test("golden first slice 组合 Domain/Application/Infrastructure/Web 且不发
158
181
  const controller = await readFile(path.join(project, "golden-service-adapter", "golden-service-web", "src/main/java/com/yss/golden/rest/QualityRuleController.java"), "utf8");
159
182
  const convertor = await readFile(path.join(project, "golden-service-adapter", "golden-service-web", "src/main/java/com/yss/golden/rest/convertor/QualityRuleWebConvertor.java"), "utf8");
160
183
  const pageRequest = await readFile(path.join(project, "golden-service-adapter", "golden-service-web", "src/main/java/com/yss/golden/rest/dto/request/QualityRulePageRequest.java"), "utf8");
184
+ const serviceImpl = await readFile(path.join(project, "golden-service-application", "src/main/java/com/yss/golden/application/service/impl/QualityRuleServiceImpl.java"), "utf8");
185
+ const repository = await readFile(path.join(project, "golden-service-infrastructure", "src/main/java/com/yss/golden/infrastructure/persistence/repository/QualityRuleRepository.java"), "utf8");
186
+ const gatewayImpl = await readFile(path.join(project, "golden-service-infrastructure", "src/main/java/com/yss/golden/infrastructure/persistence/gateway/QualityRuleGatewayImpl.java"), "utf8");
187
+ const queryAdapter = await readFile(path.join(project, "golden-service-infrastructure", "src/main/java/com/yss/golden/infrastructure/query/adapter/QualityRuleQueryAdapter.java"), "utf8");
161
188
  assert.doesNotMatch(domainPom, /yss-component-dto|yss-component-exception|spring-web|swagger/);
162
189
  assert.match(applicationPom, /yss-component-dto/);
163
190
  assert.doesNotMatch(webPom, /golden-service-domain|golden-service-infrastructure/);
164
191
  assert.doesNotMatch(`${controller}\n${convertor}`, /\.domain\.|\.infrastructure\.|\.repository\.|Mappers\.getMapper|INSTANCE/);
165
192
  assert.match(convertor, /@Mapper\(componentModel = "spring"\)/);
166
193
  assert.doesNotMatch(pageRequest, /offset|needTotalCount|tempTotalCount|extends PageQuery/);
194
+ assert.match(pageRequest, /pageIndex/);
195
+ assert.match(pageRequest, /pageSize/);
196
+ assert.doesNotMatch(pageRequest, /orderBy|orderDirection|groupBy/);
197
+ assert.match(serviceImpl, /implements QualityRuleService/);
198
+ assert.match(serviceImpl, /@Transactional/);
199
+ assert.match(repository, /@Mapper/);
200
+ assert.match(gatewayImpl, /implements QualityRuleGateway/);
201
+ assert.match(queryAdapter, /implements QualityRuleQueryPort/);
167
202
  });
168
203
 
169
- test("golden first slice 通过真实 Wrapper 后才允许 first-slice-verified", { timeout: 300_000 }, async (t) => {
204
+ test("golden first slice 通过真实 Wrapper 后才写入 first-slice-verified", { timeout: 300_000 }, async (t) => {
170
205
  if (!["YSS_MAVEN_REPOSITORY_URL", "MAVEN_REPO_USERNAME", "MAVEN_REPO_PASSWORD"].every((name) => process.env[name])) {
171
206
  t.skip("缺少受控 YSS Maven 仓库环境;不得声明 first-slice-verified");
172
207
  return;
173
208
  }
174
- const { project } = await prepareGoldenProject(t);
209
+ const { project, sliceContract, root } = await prepareGoldenProject(t);
175
210
  await chmod(path.join(project, "mvnw"), 0o755);
176
- for (const phase of ["validate", "test", "package"]) {
177
- const result = await execute(path.join(project, "mvnw"), [phase], { cwd: project, timeout: 300_000 });
178
- assert.equal(result.code, 0, `${phase}\n${result.stdout}\n${result.stderr}`);
179
- }
211
+ const result = await runFirstSliceVerification(project, path.join(root, "first-slice-evidence"), sliceContract, process.env);
212
+ assert.equal(result.status, "passed", JSON.stringify(result, null, 2));
213
+ assert.equal(JSON.parse(await readFile(path.join(project, ".yss/scaffold-generation.json"), "utf8")).completion_level, "first-slice-verified");
180
214
  });
181
215
 
182
216
  test("真实 YSS exception starter 的自动配置、优先级、三类映射和序列化均受保护", { timeout: 300_000 }, async (t) => {
@@ -0,0 +1,164 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHash } from "node:crypto";
3
+ import { chmod, mkdir, mkdtemp, readFile, readdir, writeFile } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import test from "node:test";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ import { runFirstSliceVerification } from "./run_first_slice_verification.mjs";
10
+
11
+ const requiredSkills = ["yss-domain", "yss-application", "yss-repository", "yss-mybatis", "yss-web-controller", "yss-dto", "yss-exception", "yss-validation", "mapstruct", "lombok", "alibaba-java-code-style"];
12
+ const scripts = path.dirname(fileURLToPath(import.meta.url));
13
+ const repositoryRoot = path.resolve(scripts, "../../../..");
14
+
15
+ async function treeDigest(root) {
16
+ const relativeFiles = [];
17
+ async function visit(directory) {
18
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
19
+ const absolute = path.join(directory, entry.name);
20
+ if (entry.isDirectory()) await visit(absolute);
21
+ else if (entry.isFile()) relativeFiles.push(path.relative(root, absolute).split(path.sep).join("/"));
22
+ }
23
+ }
24
+ await visit(root);
25
+ const hash = createHash("sha256");
26
+ for (const relative of relativeFiles.sort()) hash.update(relative).update("\0").update(await readFile(path.join(root, relative))).update("\0");
27
+ return hash.digest("hex");
28
+ }
29
+
30
+ async function readiness() {
31
+ const downstreamSkills = {};
32
+ for (const skill of requiredSkills) downstreamSkills[skill] = await treeDigest(path.join(repositoryRoot, ".agents", "skills", skill));
33
+ const digest = async (relative) => createHash("sha256").update(await readFile(path.join(repositoryRoot, relative))).digest("hex");
34
+ return {
35
+ downstream_skills: downstreamSkills,
36
+ contracts: {
37
+ scaffold_parent: await digest(".agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md"),
38
+ router_contract: await digest(".agents/skills/yss-router/references/router-contract.yaml")
39
+ },
40
+ architecture_ruleset: "b".repeat(64)
41
+ };
42
+ }
43
+
44
+ async function write(project, relative, content = "fixture\n") {
45
+ const target = path.join(project, relative);
46
+ await mkdir(path.dirname(target), { recursive: true });
47
+ await writeFile(target, content);
48
+ }
49
+
50
+ async function fixture({ omitGatewayImpl = false, omitReadiness = false } = {}) {
51
+ const root = await mkdtemp(path.join(os.tmpdir(), "yss-first-slice-verification-"));
52
+ const project = path.join(root, "demo-service");
53
+ const evidence = path.join(root, "evidence");
54
+ const manifestPath = path.join(project, ".yss", "scaffold-generation.json");
55
+ const contractPath = path.join(root, "slice-contract.json");
56
+ await mkdir(path.dirname(manifestPath), { recursive: true });
57
+ await writeFile(manifestPath, JSON.stringify({
58
+ schema_version: 2,
59
+ contract_id: "scaffold-1",
60
+ contract_version: 1,
61
+ scaffold_request_id: "scaffold-request-1",
62
+ contract_digest: "a".repeat(64),
63
+ profiles: { architecture: "target-domain-model", persistence: "mybatis-plus", database: "mysql", platform: "spring-boot-2.7-jdk8", validation_namespace: "javax", dto_placement: "web", repository: "yss-internal" },
64
+ ownership: { generated_files: [] },
65
+ readiness: omitReadiness ? { downstream_skills: {}, contracts: {}, architecture_ruleset: "b".repeat(64) } : await readiness(),
66
+ generation_policy: { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" },
67
+ completion_level: "empty-scaffold-verified",
68
+ approval_ref: "approval-1",
69
+ approver: "maintainer",
70
+ lifecycle_approval_ref: "approval-1",
71
+ router_draft_ref: "router-1",
72
+ persisted_ref: "persisted-1",
73
+ contract_file_ref: contractPath,
74
+ current_version: 1,
75
+ allowed_write_paths: ["."],
76
+ expected_evidence_files: [".yss/scaffold-generation.json"],
77
+ verification_commands: ["./mvnw validate", "./mvnw test", "./mvnw package"],
78
+ generation_mode: "controlled-generation",
79
+ maven_coordinates_source: "approved-contract"
80
+ }));
81
+ await writeFile(contractPath, JSON.stringify({
82
+ schema_version: 1,
83
+ contract_id: "slice-1",
84
+ contract_version: 1,
85
+ slice_id: "quality-rule-first-slice",
86
+ status: "approved",
87
+ readiness: { blockers: [], stale_inputs: [] },
88
+ common: { required_skills: requiredSkills },
89
+ backend: { status: "required", affected_layers: ["domain", "application", "infrastructure", "web"], required_skills: requiredSkills },
90
+ work_units: [{ id: "slice-backend", contract_id: "slice-1", contract_version: 1, work_unit: { primary_skill: "yss-domain" } }]
91
+ }));
92
+ await write(project, "mvnw", "#!/bin/sh\nexit 0\n");
93
+ await chmod(path.join(project, "mvnw"), 0o755);
94
+ await write(project, ".mvn/settings.xml", "<settings/>\n");
95
+ await write(project, ".mvn/maven.config", "-s .mvn/settings.xml -P yss-internal\n");
96
+ const files = [
97
+ "demo-service-domain/src/main/java/com/yss/demo/domain/quality/model/QualityRule.java",
98
+ "demo-service-domain/src/main/java/com/yss/demo/domain/quality/gateway/QualityRuleGateway.java",
99
+ "demo-service-domain/src/test/java/com/yss/demo/domain/quality/model/QualityRuleTest.java",
100
+ "demo-service-application/src/main/java/com/yss/demo/application/command/QualityRuleCreateCommand.java",
101
+ "demo-service-application/src/main/java/com/yss/demo/application/query/QualityRulePageQuery.java",
102
+ "demo-service-application/src/main/java/com/yss/demo/application/result/QualityRuleResult.java",
103
+ "demo-service-application/src/main/java/com/yss/demo/application/service/QualityRuleService.java",
104
+ "demo-service-application/src/main/java/com/yss/demo/application/service/impl/QualityRuleServiceImpl.java",
105
+ "demo-service-application/src/test/java/com/yss/demo/application/service/QualityRuleServiceTest.java",
106
+ "demo-service-infrastructure/src/main/java/com/yss/demo/infrastructure/persistence/po/QualityRulePO.java",
107
+ "demo-service-infrastructure/src/main/java/com/yss/demo/infrastructure/persistence/repository/QualityRuleRepository.java",
108
+ "demo-service-infrastructure/src/main/java/com/yss/demo/infrastructure/persistence/convertor/QualityRulePersistenceConvertor.java",
109
+ "demo-service-infrastructure/src/main/java/com/yss/demo/infrastructure/query/adapter/QualityRuleQueryAdapter.java",
110
+ "demo-service-infrastructure/src/test/java/com/yss/demo/infrastructure/persistence/QualityRuleGatewayIntegrationTest.java",
111
+ "demo-service-adapter/demo-service-web/src/main/java/com/yss/demo/rest/QualityRuleController.java",
112
+ "demo-service-adapter/demo-service-web/src/main/java/com/yss/demo/rest/convertor/QualityRuleWebConvertor.java",
113
+ "demo-service-adapter/demo-service-web/src/main/java/com/yss/demo/rest/dto/request/QualityRuleCreateRequest.java",
114
+ "demo-service-adapter/demo-service-web/src/main/java/com/yss/demo/rest/dto/response/QualityRuleResponse.java",
115
+ "demo-service-adapter/demo-service-web/src/test/java/com/yss/demo/rest/QualityRuleContractTest.java"
116
+ ];
117
+ if (!omitGatewayImpl) files.push("demo-service-infrastructure/src/main/java/com/yss/demo/infrastructure/persistence/gateway/QualityRuleGatewayImpl.java");
118
+ for (const relative of files) await write(project, relative);
119
+ return { root, project, evidence, manifestPath, contractPath };
120
+ }
121
+
122
+ const environment = { ...process.env, JAVA_HOME: "/fixture/java", YSS_MAVEN_REPOSITORY_URL: "https://repo.example.invalid", MAVEN_REPO_USERNAME: "user", MAVEN_REPO_PASSWORD: "secret" };
123
+
124
+ test("refuses first-slice promotion when a required persistence seam is absent", async () => {
125
+ const data = await fixture({ omitGatewayImpl: true });
126
+ const report = await runFirstSliceVerification(data.project, data.evidence, data.contractPath, environment);
127
+ assert.equal(report.status, "failed");
128
+ assert.ok(report.missing_artifacts.includes("infrastructure-gateway-implementation"));
129
+ const manifest = JSON.parse(await readFile(data.manifestPath, "utf8"));
130
+ assert.equal(manifest.completion_level, "empty-scaffold-verified");
131
+ });
132
+
133
+ test("refuses first-slice promotion when downstream skill or contract digests are absent", async () => {
134
+ const data = await fixture({ omitReadiness: true });
135
+ const report = await runFirstSliceVerification(data.project, data.evidence, data.contractPath, environment);
136
+ assert.equal(report.status, "failed");
137
+ assert.ok(report.downstream_skill_drift.includes("yss-domain:digest-missing"));
138
+ assert.ok(report.downstream_skill_drift.includes("router_contract:digest-missing"));
139
+ const manifest = JSON.parse(await readFile(data.manifestPath, "utf8"));
140
+ assert.equal(manifest.completion_level, "empty-scaffold-verified");
141
+ });
142
+
143
+ test("refuses first-slice promotion when a work unit references a stale contract version", async () => {
144
+ const data = await fixture();
145
+ const contract = JSON.parse(await readFile(data.contractPath, "utf8"));
146
+ contract.work_units[0].contract_version = 0;
147
+ await writeFile(data.contractPath, JSON.stringify(contract));
148
+ const report = await runFirstSliceVerification(data.project, data.evidence, data.contractPath, environment);
149
+ assert.equal(report.status, "failed");
150
+ assert.ok(report.contract_failures.includes("work-unit-contract-version-mismatch:slice-backend"));
151
+ });
152
+
153
+ test("promotes a complete approved slice only after all root wrapper commands pass", async () => {
154
+ const data = await fixture();
155
+ const report = await runFirstSliceVerification(data.project, data.evidence, data.contractPath, environment);
156
+ assert.equal(report.status, "passed");
157
+ assert.equal(report.completion_level, "first-slice-verified");
158
+ assert.deepEqual(report.commands.map((item) => item.exit_code), [0, 0, 0]);
159
+ const manifest = JSON.parse(await readFile(data.manifestPath, "utf8"));
160
+ assert.equal(manifest.completion_level, "first-slice-verified");
161
+ assert.equal(manifest.first_slice_contract.contract_id, "slice-1");
162
+ assert.equal(manifest.first_slice_contract.slice_id, "quality-rule-first-slice");
163
+ assert.equal(JSON.parse(await readFile(path.join(data.evidence, "first-slice-verification.json"), "utf8")).status, "passed");
164
+ });
@@ -25,7 +25,19 @@ const SUPPORTED_PROFILES = Object.freeze({
25
25
  dto_placement: "web",
26
26
  repository: "yss-internal"
27
27
  });
28
- const DOWNSTREAM_SKILLS = ["yss-domain", "yss-application", "yss-repository", "yss-mybatis", "yss-dto", "yss-exception", "yss-web-controller"];
28
+ const DOWNSTREAM_SKILLS = [
29
+ "yss-domain",
30
+ "yss-application",
31
+ "yss-repository",
32
+ "yss-mybatis",
33
+ "yss-web-controller",
34
+ "yss-dto",
35
+ "yss-exception",
36
+ "yss-validation",
37
+ "mapstruct",
38
+ "lombok",
39
+ "alibaba-java-code-style"
40
+ ];
29
41
  function fail(message) { throw new Error(message); }
30
42
  function isoNow() { return new Date().toISOString(); }
31
43
  function localDate() { return new Date().toISOString().slice(0, 10); }
@@ -324,10 +336,12 @@ class ScaffoldGenerator {
324
336
  }
325
337
  const downstream = {};
326
338
  for (const skill of DOWNSTREAM_SKILLS) {
327
- const skillFile = path.join(REPOSITORY_ROOT, ".agents", "skills", skill, "SKILL.md");
328
- downstream[skill] = await isFile(skillFile) ? sha256(await readFile(skillFile)) : "unavailable";
339
+ const skillRoot = path.join(REPOSITORY_ROOT, ".agents", "skills", skill);
340
+ downstream[skill] = await isFile(path.join(skillRoot, "SKILL.md")) ? await treeDigest(skillRoot) : "unavailable";
329
341
  }
330
- const manifest = { schema_version: 2, contract_id: this.options.contractId, contract_version: this.options.contractVersion, scaffold_request_id: contract.scaffold_request_id, approval_ref: this.options.approvalRef, router_draft_ref: this.options.routerDraftRef, persisted_ref: this.options.persistedRef, contract_file_ref: this.contractFile, contract_digest: this.contractDigest, lifecycle_approval_ref: contract.lifecycle_approval_ref, current_version: contract.current_version, approver: contract.approval.approver, allowed_write_paths: contract.allowed_write_paths, expected_evidence_files: contract.expected_evidence_files, project_name: this.projectName, base_package: this.basePackage, bootstrap_main_class: `${this.basePackage}.${this.applicationClassName}`, bootstrap_main_source: this.bootstrapMainSource, maven_coordinates: this.mavenCoordinates, maven_coordinates_source: this.mavenCoordinatesSource, profiles: this.profiles, database: this.options.database, generation_mode: "controlled-generation", completion_level: "generated", generator: { id: "yss-ddd-scaffold-generator", template_digest: await treeDigest(path.join(SKILL_ROOT, "assets")) }, ownership: { generated_files: generatedFiles, user_owned_globs: ["**/src/main/java/**", "**/src/test/java/**", "db/**"] }, readiness: { downstream_skills: downstream, architecture_ruleset: sha256(await readFile(path.join(this.javaTemplateDir, "architecture-rules-test.java.template"))) }, generation_policy: { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" }, verification_commands: COMMANDS, generated_at: isoNow() };
342
+ const scaffoldParent = path.join(SKILL_ROOT, "references", "yss-backend-scaffold-parent", "SKILL.md");
343
+ const routerContract = path.join(REPOSITORY_ROOT, ".agents", "skills", "yss-router", "references", "router-contract.yaml");
344
+ const manifest = { schema_version: 2, contract_id: this.options.contractId, contract_version: this.options.contractVersion, scaffold_request_id: contract.scaffold_request_id, approval_ref: this.options.approvalRef, router_draft_ref: this.options.routerDraftRef, persisted_ref: this.options.persistedRef, contract_file_ref: this.contractFile, contract_digest: this.contractDigest, lifecycle_approval_ref: contract.lifecycle_approval_ref, current_version: contract.current_version, approver: contract.approval.approver, allowed_write_paths: contract.allowed_write_paths, expected_evidence_files: contract.expected_evidence_files, project_name: this.projectName, base_package: this.basePackage, bootstrap_main_class: `${this.basePackage}.${this.applicationClassName}`, bootstrap_main_source: this.bootstrapMainSource, maven_coordinates: this.mavenCoordinates, maven_coordinates_source: this.mavenCoordinatesSource, profiles: this.profiles, database: this.options.database, generation_mode: "controlled-generation", completion_level: "generated", generator: { id: "yss-ddd-scaffold-generator", template_digest: await treeDigest(path.join(SKILL_ROOT, "assets")) }, ownership: { generated_files: generatedFiles, user_owned_globs: ["**/src/main/java/**", "**/src/test/java/**", "db/**"] }, readiness: { downstream_skills: downstream, contracts: { scaffold_parent: sha256(await readFile(scaffoldParent)), router_contract: sha256(await readFile(routerContract)) }, architecture_ruleset: sha256(await readFile(path.join(this.javaTemplateDir, "architecture-rules-test.java.template"))) }, generation_policy: { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" }, verification_commands: COMMANDS, generated_at: isoNow() };
331
345
  await writeText(path.join(this.projectRoot, ".yss", "scaffold-generation.json"), `${JSON.stringify(manifest, null, 2)}\n`); console.log(" ✓ .yss/scaffold-generation.json");
332
346
  }
333
347
  async copyWrapperFiles() {