create-yss-spec 3.4.1 → 3.4.3

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 (373) hide show
  1. package/README.md +1 -1
  2. package/package.json +2 -2
  3. package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
  4. package/template/.agents/skills/archify/SKILL.md +1 -1
  5. package/template/.agents/skills/code-review/SKILL.md +12 -8
  6. package/template/.agents/skills/file-export-download/SKILL.md +1 -1
  7. package/template/.agents/skills/frontend-commit/SKILL.md +1 -1
  8. package/template/.agents/skills/java-backend-commit/SKILL.md +1 -1
  9. package/template/.agents/skills/llm-wiki/SKILL.md +1 -6
  10. package/template/.agents/skills/lombok/SKILL.md +10 -336
  11. package/template/.agents/skills/lombok/references/annotation-examples.md +307 -0
  12. package/template/.agents/skills/maintaining-skills/SKILL.md +2 -1
  13. package/template/.agents/skills/maintaining-skills/references/authoring.md +27 -0
  14. package/template/.agents/skills/mapstruct/SKILL.md +11 -318
  15. package/template/.agents/skills/mapstruct/references/annotation-examples.md +300 -0
  16. package/template/.agents/skills/page-form-module/SKILL.md +1 -1
  17. package/template/.agents/skills/page-skeleton/SKILL.md +1 -1
  18. package/template/.agents/skills/theme-token-usage/SKILL.md +1 -1
  19. package/template/.agents/skills/to-tickets/SKILL.md +1 -1
  20. package/template/.agents/skills/using-git-worktrees/SKILL.md +1 -1
  21. package/template/.agents/skills/wayfinder/SKILL.md +1 -1
  22. package/template/.agents/skills/yedit-table-usage/SKILL.md +1 -1
  23. package/template/.agents/skills/yss-api-integration/SKILL.md +1 -1
  24. package/template/.agents/skills/yss-audit-log/SKILL.md +1 -1
  25. package/template/.agents/skills/yss-cache/SKILL.md +1 -1
  26. package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +15 -2
  27. package/template/.agents/skills/yss-ddd-scaffold-generator/assets/templates/pom/application-pom.xml.template +1 -1
  28. package/template/.agents/skills/yss-ddd-scaffold-generator/assets/templates/pom/parent-pom.xml.template +15 -10
  29. package/template/.agents/skills/yss-ddd-scaffold-generator/assets/templates/pom/web-pom.xml.template +3 -3
  30. package/template/.agents/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +3 -3
  31. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +5 -1
  32. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +5 -2
  33. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +13 -10
  34. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -1
  35. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +35 -3
  36. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  37. package/template/.agents/skills/yss-distributed-id/SKILL.md +1 -1
  38. package/template/.agents/skills/yss-dto/SKILL.md +5 -1
  39. package/template/.agents/skills/yss-excel-mvc/SKILL.md +1 -1
  40. package/template/.agents/skills/yss-exception/SKILL.md +5 -1
  41. package/template/.agents/skills/yss-formily-schema-generator/SKILL.md +1 -1
  42. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +13 -5
  43. package/template/.agents/skills/yss-implementation-contract-compiler/agents/openai.yaml +1 -1
  44. package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -0
  45. package/template/.agents/skills/yss-implementation-contract-compiler/references/slice-implementation-contract-v2.md +214 -0
  46. package/template/.agents/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +66 -204
  47. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +15 -2
  48. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +28 -19
  49. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +10 -10
  50. package/template/.agents/skills/yss-mybatis/SKILL.md +4 -0
  51. package/template/.agents/skills/yss-openapi-draft-review/SKILL.md +1 -1
  52. package/template/.agents/skills/yss-openapi-governance/SKILL.md +1 -1
  53. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +4 -4
  54. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +7 -2
  55. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +4 -0
  56. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +2 -0
  57. package/template/.agents/skills/yss-product-lifecycle/references/user-decisions.md +23 -3
  58. package/template/.agents/skills/yss-prototype-stage/SKILL.md +1 -1
  59. package/template/.agents/skills/yss-repository/SKILL.md +4 -0
  60. package/template/.agents/skills/yss-research/SKILL.md +1 -1
  61. package/template/.agents/skills/yss-resilience4j/SKILL.md +1 -1
  62. package/template/.agents/skills/yss-security-algorithm/SKILL.md +1 -1
  63. package/template/.agents/skills/yss-tactical-design/SKILL.md +4 -0
  64. package/template/.agents/skills/yss-technical-design/SKILL.md +4 -0
  65. package/template/.agents/skills/yss-technical-design/scripts/validate-technical-design.mjs +2 -2
  66. package/template/.agents/skills/yss-ui/SKILL.md +1 -1
  67. package/template/.agents/skills/yss-ui-business-page-generation/SKILL.md +1 -1
  68. package/template/.agents/skills/yss-up-springboot3/SKILL.md +1 -1
  69. package/template/.agents/skills/yss-use-table-height/SKILL.md +1 -1
  70. package/template/.agents/skills/yss-use-tree-height/SKILL.md +1 -1
  71. package/template/.agents/skills/yss-userinfo/SKILL.md +1 -1
  72. package/template/.agents/skills/yss-validation/SKILL.md +5 -1
  73. package/template/.agents/skills/yss-web-controller/SKILL.md +5 -1
  74. package/template/.agents/skills/yss-web-controller/scripts/generate_controller.mjs +5 -2
  75. package/template/.agents/skills/ytable-usage/SKILL.md +1 -1
  76. package/template/.agents/skills/ytree-usage/SKILL.md +1 -1
  77. package/template/.codex/skills/archify/SKILL.md +1 -1
  78. package/template/.codex/skills/code-review/SKILL.md +12 -8
  79. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +1 -1
  80. package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +1 -1
  81. package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +1 -1
  82. package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +1 -1
  83. package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +1 -1
  84. package/template/.codex/skills/data-analytics/skills/index/SKILL.md +1 -1
  85. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +1 -1
  86. package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +1 -1
  87. package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +1 -1
  88. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +1 -1
  89. package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +1 -1
  90. package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +1 -1
  91. package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +1 -1
  92. package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +1 -1
  93. package/template/.codex/skills/file-export-download/SKILL.md +1 -1
  94. package/template/.codex/skills/frontend-commit/SKILL.md +1 -1
  95. package/template/.codex/skills/java-backend-commit/SKILL.md +1 -1
  96. package/template/.codex/skills/llm-wiki/SKILL.md +1 -6
  97. package/template/.codex/skills/lombok/SKILL.md +10 -336
  98. package/template/.codex/skills/lombok/references/annotation-examples.md +307 -0
  99. package/template/.codex/skills/maintaining-skills/SKILL.md +2 -1
  100. package/template/.codex/skills/maintaining-skills/references/authoring.md +27 -0
  101. package/template/.codex/skills/mapstruct/SKILL.md +11 -318
  102. package/template/.codex/skills/mapstruct/references/annotation-examples.md +300 -0
  103. package/template/.codex/skills/page-form-module/SKILL.md +1 -1
  104. package/template/.codex/skills/page-skeleton/SKILL.md +1 -1
  105. package/template/.codex/skills/product-design/skills/audit/SKILL.md +1 -1
  106. package/template/.codex/skills/product-design/skills/design-qa/SKILL.md +1 -1
  107. package/template/.codex/skills/product-design/skills/get-context/SKILL.md +1 -1
  108. package/template/.codex/skills/product-design/skills/ideate/SKILL.md +1 -1
  109. package/template/.codex/skills/product-design/skills/image-to-code/SKILL.md +1 -1
  110. package/template/.codex/skills/product-design/skills/index/SKILL.md +1 -1
  111. package/template/.codex/skills/product-design/skills/prototype/SKILL.md +1 -1
  112. package/template/.codex/skills/product-design/skills/research/SKILL.md +1 -1
  113. package/template/.codex/skills/product-design/skills/user-context/SKILL.md +1 -1
  114. package/template/.codex/skills/theme-token-usage/SKILL.md +1 -1
  115. package/template/.codex/skills/to-tickets/SKILL.md +1 -1
  116. package/template/.codex/skills/using-git-worktrees/SKILL.md +1 -1
  117. package/template/.codex/skills/wayfinder/SKILL.md +1 -1
  118. package/template/.codex/skills/yedit-table-usage/SKILL.md +1 -1
  119. package/template/.codex/skills/yss-api-integration/SKILL.md +1 -1
  120. package/template/.codex/skills/yss-audit-log/SKILL.md +1 -1
  121. package/template/.codex/skills/yss-cache/SKILL.md +1 -1
  122. package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +15 -2
  123. package/template/.codex/skills/yss-ddd-scaffold-generator/assets/templates/pom/application-pom.xml.template +1 -1
  124. package/template/.codex/skills/yss-ddd-scaffold-generator/assets/templates/pom/parent-pom.xml.template +15 -10
  125. package/template/.codex/skills/yss-ddd-scaffold-generator/assets/templates/pom/web-pom.xml.template +3 -3
  126. package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +3 -3
  127. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +5 -1
  128. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +5 -2
  129. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +13 -10
  130. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -1
  131. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +35 -3
  132. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  133. package/template/.codex/skills/yss-distributed-id/SKILL.md +1 -1
  134. package/template/.codex/skills/yss-dto/SKILL.md +5 -1
  135. package/template/.codex/skills/yss-excel-mvc/SKILL.md +1 -1
  136. package/template/.codex/skills/yss-exception/SKILL.md +5 -1
  137. package/template/.codex/skills/yss-formily-schema-generator/SKILL.md +1 -1
  138. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +13 -5
  139. package/template/.codex/skills/yss-implementation-contract-compiler/agents/openai.yaml +1 -1
  140. package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -0
  141. package/template/.codex/skills/yss-implementation-contract-compiler/references/slice-implementation-contract-v2.md +214 -0
  142. package/template/.codex/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +66 -204
  143. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +15 -2
  144. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +28 -19
  145. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +10 -10
  146. package/template/.codex/skills/yss-mybatis/SKILL.md +4 -0
  147. package/template/.codex/skills/yss-openapi-draft-review/SKILL.md +1 -1
  148. package/template/.codex/skills/yss-openapi-governance/SKILL.md +1 -1
  149. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +4 -4
  150. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +7 -2
  151. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +4 -0
  152. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +2 -0
  153. package/template/.codex/skills/yss-product-lifecycle/references/user-decisions.md +23 -3
  154. package/template/.codex/skills/yss-prototype-stage/SKILL.md +1 -1
  155. package/template/.codex/skills/yss-repository/SKILL.md +4 -0
  156. package/template/.codex/skills/yss-research/SKILL.md +1 -1
  157. package/template/.codex/skills/yss-resilience4j/SKILL.md +1 -1
  158. package/template/.codex/skills/yss-security-algorithm/SKILL.md +1 -1
  159. package/template/.codex/skills/yss-tactical-design/SKILL.md +4 -0
  160. package/template/.codex/skills/yss-technical-design/SKILL.md +4 -0
  161. package/template/.codex/skills/yss-technical-design/scripts/validate-technical-design.mjs +2 -2
  162. package/template/.codex/skills/yss-ui/SKILL.md +1 -1
  163. package/template/.codex/skills/yss-ui-business-page-generation/SKILL.md +1 -1
  164. package/template/.codex/skills/yss-up-springboot3/SKILL.md +1 -1
  165. package/template/.codex/skills/yss-use-table-height/SKILL.md +1 -1
  166. package/template/.codex/skills/yss-use-tree-height/SKILL.md +1 -1
  167. package/template/.codex/skills/yss-userinfo/SKILL.md +1 -1
  168. package/template/.codex/skills/yss-validation/SKILL.md +5 -1
  169. package/template/.codex/skills/yss-web-controller/SKILL.md +5 -1
  170. package/template/.codex/skills/yss-web-controller/scripts/generate_controller.mjs +5 -2
  171. package/template/.codex/skills/ytable-usage/SKILL.md +1 -1
  172. package/template/.codex/skills/ytree-usage/SKILL.md +1 -1
  173. package/template/.cursor/skills/archify/SKILL.md +1 -1
  174. package/template/.cursor/skills/code-review/SKILL.md +12 -8
  175. package/template/.cursor/skills/file-export-download/SKILL.md +1 -1
  176. package/template/.cursor/skills/frontend-commit/SKILL.md +1 -1
  177. package/template/.cursor/skills/java-backend-commit/SKILL.md +1 -1
  178. package/template/.cursor/skills/llm-wiki/SKILL.md +1 -6
  179. package/template/.cursor/skills/lombok/SKILL.md +10 -336
  180. package/template/.cursor/skills/lombok/references/annotation-examples.md +307 -0
  181. package/template/.cursor/skills/maintaining-skills/SKILL.md +2 -1
  182. package/template/.cursor/skills/maintaining-skills/references/authoring.md +27 -0
  183. package/template/.cursor/skills/mapstruct/SKILL.md +11 -318
  184. package/template/.cursor/skills/mapstruct/references/annotation-examples.md +300 -0
  185. package/template/.cursor/skills/page-form-module/SKILL.md +1 -1
  186. package/template/.cursor/skills/page-skeleton/SKILL.md +1 -1
  187. package/template/.cursor/skills/theme-token-usage/SKILL.md +1 -1
  188. package/template/.cursor/skills/to-tickets/SKILL.md +1 -1
  189. package/template/.cursor/skills/using-git-worktrees/SKILL.md +1 -1
  190. package/template/.cursor/skills/wayfinder/SKILL.md +1 -1
  191. package/template/.cursor/skills/yedit-table-usage/SKILL.md +1 -1
  192. package/template/.cursor/skills/yss-api-integration/SKILL.md +1 -1
  193. package/template/.cursor/skills/yss-audit-log/SKILL.md +1 -1
  194. package/template/.cursor/skills/yss-cache/SKILL.md +1 -1
  195. package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +15 -2
  196. package/template/.cursor/skills/yss-ddd-scaffold-generator/assets/templates/pom/application-pom.xml.template +1 -1
  197. package/template/.cursor/skills/yss-ddd-scaffold-generator/assets/templates/pom/parent-pom.xml.template +15 -10
  198. package/template/.cursor/skills/yss-ddd-scaffold-generator/assets/templates/pom/web-pom.xml.template +3 -3
  199. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +3 -3
  200. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +5 -1
  201. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +5 -2
  202. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +13 -10
  203. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -1
  204. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +35 -3
  205. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  206. package/template/.cursor/skills/yss-distributed-id/SKILL.md +1 -1
  207. package/template/.cursor/skills/yss-dto/SKILL.md +5 -1
  208. package/template/.cursor/skills/yss-excel-mvc/SKILL.md +1 -1
  209. package/template/.cursor/skills/yss-exception/SKILL.md +5 -1
  210. package/template/.cursor/skills/yss-formily-schema-generator/SKILL.md +1 -1
  211. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +13 -5
  212. package/template/.cursor/skills/yss-implementation-contract-compiler/agents/openai.yaml +1 -1
  213. package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -0
  214. package/template/.cursor/skills/yss-implementation-contract-compiler/references/slice-implementation-contract-v2.md +214 -0
  215. package/template/.cursor/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +66 -204
  216. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +15 -2
  217. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +28 -19
  218. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +10 -10
  219. package/template/.cursor/skills/yss-mybatis/SKILL.md +4 -0
  220. package/template/.cursor/skills/yss-openapi-draft-review/SKILL.md +1 -1
  221. package/template/.cursor/skills/yss-openapi-governance/SKILL.md +1 -1
  222. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +4 -4
  223. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +7 -2
  224. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +4 -0
  225. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +2 -0
  226. package/template/.cursor/skills/yss-product-lifecycle/references/user-decisions.md +23 -3
  227. package/template/.cursor/skills/yss-prototype-stage/SKILL.md +1 -1
  228. package/template/.cursor/skills/yss-repository/SKILL.md +4 -0
  229. package/template/.cursor/skills/yss-research/SKILL.md +1 -1
  230. package/template/.cursor/skills/yss-resilience4j/SKILL.md +1 -1
  231. package/template/.cursor/skills/yss-security-algorithm/SKILL.md +1 -1
  232. package/template/.cursor/skills/yss-tactical-design/SKILL.md +4 -0
  233. package/template/.cursor/skills/yss-technical-design/SKILL.md +4 -0
  234. package/template/.cursor/skills/yss-technical-design/scripts/validate-technical-design.mjs +2 -2
  235. package/template/.cursor/skills/yss-ui/SKILL.md +1 -1
  236. package/template/.cursor/skills/yss-ui-business-page-generation/SKILL.md +1 -1
  237. package/template/.cursor/skills/yss-up-springboot3/SKILL.md +1 -1
  238. package/template/.cursor/skills/yss-use-table-height/SKILL.md +1 -1
  239. package/template/.cursor/skills/yss-use-tree-height/SKILL.md +1 -1
  240. package/template/.cursor/skills/yss-userinfo/SKILL.md +1 -1
  241. package/template/.cursor/skills/yss-validation/SKILL.md +5 -1
  242. package/template/.cursor/skills/yss-web-controller/SKILL.md +5 -1
  243. package/template/.cursor/skills/yss-web-controller/scripts/generate_controller.mjs +5 -2
  244. package/template/.cursor/skills/ytable-usage/SKILL.md +1 -1
  245. package/template/.cursor/skills/ytree-usage/SKILL.md +1 -1
  246. package/template/.pi/skills/archify/SKILL.md +1 -1
  247. package/template/.pi/skills/code-review/SKILL.md +12 -8
  248. package/template/.pi/skills/file-export-download/SKILL.md +1 -1
  249. package/template/.pi/skills/frontend-commit/SKILL.md +1 -1
  250. package/template/.pi/skills/java-backend-commit/SKILL.md +1 -1
  251. package/template/.pi/skills/llm-wiki/SKILL.md +1 -6
  252. package/template/.pi/skills/lombok/SKILL.md +10 -336
  253. package/template/.pi/skills/lombok/references/annotation-examples.md +307 -0
  254. package/template/.pi/skills/maintaining-skills/SKILL.md +2 -1
  255. package/template/.pi/skills/maintaining-skills/references/authoring.md +27 -0
  256. package/template/.pi/skills/mapstruct/SKILL.md +11 -318
  257. package/template/.pi/skills/mapstruct/references/annotation-examples.md +300 -0
  258. package/template/.pi/skills/page-form-module/SKILL.md +1 -1
  259. package/template/.pi/skills/page-skeleton/SKILL.md +1 -1
  260. package/template/.pi/skills/theme-token-usage/SKILL.md +1 -1
  261. package/template/.pi/skills/to-tickets/SKILL.md +1 -1
  262. package/template/.pi/skills/using-git-worktrees/SKILL.md +1 -1
  263. package/template/.pi/skills/wayfinder/SKILL.md +1 -1
  264. package/template/.pi/skills/yedit-table-usage/SKILL.md +1 -1
  265. package/template/.pi/skills/yss-api-integration/SKILL.md +1 -1
  266. package/template/.pi/skills/yss-audit-log/SKILL.md +1 -1
  267. package/template/.pi/skills/yss-cache/SKILL.md +1 -1
  268. package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +15 -2
  269. package/template/.pi/skills/yss-ddd-scaffold-generator/assets/templates/pom/application-pom.xml.template +1 -1
  270. package/template/.pi/skills/yss-ddd-scaffold-generator/assets/templates/pom/parent-pom.xml.template +15 -10
  271. package/template/.pi/skills/yss-ddd-scaffold-generator/assets/templates/pom/web-pom.xml.template +3 -3
  272. package/template/.pi/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +3 -3
  273. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-compatibility.test.mjs +5 -1
  274. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/first-slice-verification.test.mjs +5 -2
  275. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +13 -10
  276. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_first_slice_verification.mjs +2 -1
  277. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +35 -3
  278. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +1 -1
  279. package/template/.pi/skills/yss-distributed-id/SKILL.md +1 -1
  280. package/template/.pi/skills/yss-dto/SKILL.md +5 -1
  281. package/template/.pi/skills/yss-excel-mvc/SKILL.md +1 -1
  282. package/template/.pi/skills/yss-exception/SKILL.md +5 -1
  283. package/template/.pi/skills/yss-formily-schema-generator/SKILL.md +1 -1
  284. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +13 -5
  285. package/template/.pi/skills/yss-implementation-contract-compiler/agents/openai.yaml +1 -1
  286. package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -0
  287. package/template/.pi/skills/yss-implementation-contract-compiler/references/slice-implementation-contract-v2.md +214 -0
  288. package/template/.pi/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +66 -204
  289. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +15 -2
  290. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +28 -19
  291. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +10 -10
  292. package/template/.pi/skills/yss-mybatis/SKILL.md +4 -0
  293. package/template/.pi/skills/yss-openapi-draft-review/SKILL.md +1 -1
  294. package/template/.pi/skills/yss-openapi-governance/SKILL.md +1 -1
  295. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +4 -4
  296. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +7 -2
  297. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +4 -0
  298. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +2 -0
  299. package/template/.pi/skills/yss-product-lifecycle/references/user-decisions.md +23 -3
  300. package/template/.pi/skills/yss-prototype-stage/SKILL.md +1 -1
  301. package/template/.pi/skills/yss-repository/SKILL.md +4 -0
  302. package/template/.pi/skills/yss-research/SKILL.md +1 -1
  303. package/template/.pi/skills/yss-resilience4j/SKILL.md +1 -1
  304. package/template/.pi/skills/yss-security-algorithm/SKILL.md +1 -1
  305. package/template/.pi/skills/yss-tactical-design/SKILL.md +4 -0
  306. package/template/.pi/skills/yss-technical-design/SKILL.md +4 -0
  307. package/template/.pi/skills/yss-technical-design/scripts/validate-technical-design.mjs +2 -2
  308. package/template/.pi/skills/yss-ui/SKILL.md +1 -1
  309. package/template/.pi/skills/yss-ui-business-page-generation/SKILL.md +1 -1
  310. package/template/.pi/skills/yss-up-springboot3/SKILL.md +1 -1
  311. package/template/.pi/skills/yss-use-table-height/SKILL.md +1 -1
  312. package/template/.pi/skills/yss-use-tree-height/SKILL.md +1 -1
  313. package/template/.pi/skills/yss-userinfo/SKILL.md +1 -1
  314. package/template/.pi/skills/yss-validation/SKILL.md +5 -1
  315. package/template/.pi/skills/yss-web-controller/SKILL.md +5 -1
  316. package/template/.pi/skills/yss-web-controller/scripts/generate_controller.mjs +5 -2
  317. package/template/.pi/skills/ytable-usage/SKILL.md +1 -1
  318. package/template/.pi/skills/ytree-usage/SKILL.md +1 -1
  319. package/template/AGENTS.md +1 -0
  320. package/template/CONTEXT.md +2 -1
  321. package/template/docs/agents/backend-architecture-profiles.md +1 -1
  322. package/template/docs/agents/digital-human-roles.yaml +25 -1
  323. package/template/docs/agents/issue-tracker.md +2 -0
  324. package/template/docs/engineering/backend-platforms.json +174 -0
  325. package/template/docs/engineering/backend-platforms.md +77 -0
  326. package/template/docs/process/MATT-POCOCK-ENGINEERING-SKILLS.md +1 -0
  327. package/template/docs/process/harness-process-tailoring.md +9 -1
  328. package/template/docs/process/lifecycle-artifact-map.md +4 -4
  329. package/template/docs/process/lifecycle-registry-baseline.json +1 -1
  330. package/template/docs/process/lifecycle-registry.yaml +4 -4
  331. package/template/docs/process/schemas/backend-architecture-identity.schema.json +91 -0
  332. package/template/docs/process/schemas/digital-human-task-package.schema.json +2 -1
  333. package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +4 -0
  334. package/template/docs/process/schemas/project-scaffold-contract.schema.json +602 -83
  335. package/template/docs/process/schemas/scaffold-architecture-decisions.schema.json +323 -39
  336. package/template/docs/process/schemas/slice-implementation-contract-v3.schema.json +925 -0
  337. package/template/docs/templates/approval-record-template.yaml +2 -0
  338. package/template/docs/templates/vertical-slice-ticket-template.md +22 -31
  339. package/template/scripts/backend-platforms +14 -0
  340. package/template/scripts/lib/approval-record.mjs +32 -6
  341. package/template/scripts/lib/approved-execution-context.mjs +31 -8
  342. package/template/scripts/lib/backend-architecture.mjs +6 -0
  343. package/template/scripts/lib/backend-platform-provenance.mjs +67 -0
  344. package/template/scripts/lib/backend-platform-verification.mjs +210 -0
  345. package/template/scripts/lib/backend-platform.mjs +175 -0
  346. package/template/scripts/lib/backend-scaffold-prerequisites.mjs +1 -1
  347. package/template/scripts/lib/decision-continuation.mjs +79 -0
  348. package/template/scripts/lib/delivery-preflight.mjs +6 -5
  349. package/template/scripts/lib/digital-human-roles.mjs +10 -0
  350. package/template/scripts/lib/frontend-delivery-boundary.mjs +3 -0
  351. package/template/scripts/lib/implementation-contract-compiler.mjs +42 -9
  352. package/template/scripts/lib/lifecycle-controls.mjs +2 -2
  353. package/template/scripts/lib/lifecycle-transition.mjs +3 -1
  354. package/template/scripts/lib/plan-spec-entry.mjs +3 -3
  355. package/template/scripts/lib/scaffold-local-database.mjs +1 -0
  356. package/template/scripts/lib/slice-applicability.mjs +10 -0
  357. package/template/scripts/lib/slice-contract-preparation.mjs +257 -0
  358. package/template/scripts/lib/slice-contract-views.mjs +52 -0
  359. package/template/scripts/lib/slice-contract.mjs +211 -0
  360. package/template/scripts/lib/slice-repositories.mjs +49 -0
  361. package/template/scripts/lib/slice-task-package.mjs +66 -0
  362. package/template/scripts/lib/strategic-handoff.mjs +12 -1
  363. package/template/scripts/lib/task-package.mjs +6 -2
  364. package/template/scripts/lib/technical-design-boundary.mjs +1 -0
  365. package/template/scripts/lib/user-decision-reuse.mjs +1 -0
  366. package/template/scripts/lib/user-decision.mjs +4 -1
  367. package/template/scripts/preflight-delivery +2 -2
  368. package/template/scripts/slice-contract +30 -0
  369. package/template/scripts/verify-backend-platform-matrix +69 -0
  370. package/template/scripts/verify-scaffold-architecture-decisions +5 -0
  371. package/template/scripts/verify-user-decision +7 -2
  372. package/template/skills-lock.json +60 -55
  373. package/template.snapshot.json +3 -3
@@ -0,0 +1,175 @@
1
+ import { assertSourceFingerprint } from "./backend-platform-provenance.mjs";
2
+ /** Shared, exact backend platform selection. Catalog entries are maintenance-owned. */
3
+ import { createHash } from "node:crypto";
4
+ import { readFileSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ export const PLATFORM_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
9
+ export const PLATFORM_CATALOG_REF = "docs/engineering/backend-platforms.json";
10
+ export const PLATFORM_SKILLS = ["yss-ddd-scaffold-generator", "yss-layered-mvc-scaffold-generator"];
11
+ const fail = (message) => { throw new TypeError(`backend-platform: ${message}`); };
12
+ 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
+ export const platformDigest = value => `sha256:${createHash("sha256").update(typeof value === "string" || Buffer.isBuffer(value) ? value : JSON.stringify(stable(value ?? null))).digest("hex")}`;
14
+ export function loadBackendPlatforms(root = PLATFORM_ROOT) {
15
+ 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");
17
+ 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");
19
+ return value;
20
+ }
21
+ export function platformProfile(id, catalog = loadBackendPlatforms(), version) {
22
+ const matches = catalog.profiles.filter(item => item.id === id && (!version || item.spring_boot_version === version));
23
+ if (matches.length > 1) fail("multiple patches: select an exact spring_boot_version");
24
+ const result = matches[0];
25
+ if (!result) fail(`unsupported platform_profile: ${id}`);
26
+ return result;
27
+ }
28
+ export function platformRecipeDigest(profile, entry) {
29
+ 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 ?? {} } });
31
+ }
32
+ 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) };
34
+ }
35
+ export function resolveBackendPlatform(binding, { catalog = loadBackendPlatforms(), requireVerified = true, root = PLATFORM_ROOT } = {}) {
36
+ if (!binding || binding.schema_version !== 2) fail("missing platform_configuration v2 (v1 is historical read-only); 生命周期须展示 Boot/Java/YSS 组合并取得用户确认");
37
+ const profile = platformProfile(binding.profile_id, catalog, binding.spring_boot_version);
38
+ 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)");
39
+ const entry = catalog.compatibility.find(item => item.id === binding.compatibility_id);
40
+ const evidenceReports = [];
41
+ 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");
42
+ if (platformDigest(binding) !== platformDigest(platformBinding(profile, entry))) fail("stale compatibility digest or YSS coordinates");
43
+ if (requireVerified) {
44
+ if (entry.status !== "verified") fail(`YSS combination ${entry.id} is not verified`);
45
+ if (!Array.isArray(entry.evidence) || !entry.evidence.length) fail("verified combination lacks evidence");
46
+ for (const item of entry.evidence) {
47
+ if (!item.ref || !item.digest || path.isAbsolute(item.ref) || item.ref.split(/[\\/]/).includes("..")) fail("invalid portable evidence reference");
48
+ const bytes = readFileSync(path.join(root, item.ref));
49
+ if (platformDigest(bytes) !== item.digest) fail("compatibility evidence drift");
50
+ const report = JSON.parse(bytes);
51
+ if (report.verification_scope !== "empty-scaffold") fail("qualification requires empty-scaffold evidence");
52
+ if (report.recipe_digest !== platformRecipeDigest(profile, entry)) fail("evidence recipe drift");
53
+ assertSourceFingerprint(report.source_fingerprint, report.architecture_family);
54
+ if (!/^sha256:[a-f0-9]{64}$/.test(report.generated_tree_digest ?? "")) fail("missing generated tree digest");
55
+ evidenceReports.push(report);
56
+ if (report.status !== "passed" || report.spring_boot_version !== profile.spring_boot_version || report.java_version !== profile.java_version || report.architecture_family !== item.architecture_family || platformDigest(report.parent) !== platformDigest(entry.parent) || platformDigest(report.bom) !== platformDigest(entry.bom)) fail("compatibility evidence identity mismatch");
57
+ for (const phase of ["validate", "test", "package"]) if (!report.commands?.some(cmd => cmd.command === `./mvnw ${phase}` && cmd.exit_code === 0 && cmd.stdout_ref && cmd.stderr_ref && cmd.executed_at)) fail("missing real Maven evidence");
58
+ if (report.dependency_check !== "passed" || report.startup_check !== "passed" || report.integration_tests?.status !== "passed") fail("missing dependency/startup/integration-test evidence");
59
+ const required = ["effective-pom.xml", "dependency-trees.json", "platform-tests.xml", "boot-bom-effective.xml", "runtime-jar-entries.log", "startup.stdout.log", "startup.stderr.log", ...["validate", "test", "package"].flatMap(phase => [`mvnw-${phase}.stdout.log`, `mvnw-${phase}.stderr.log`])];
60
+ if (!Array.isArray(report.evidence_artifacts) || required.some(ref => !report.evidence_artifacts.some(artifact => artifact.ref === ref))) fail("missing portable evidence artifacts");
61
+ for (const artifact of report.evidence_artifacts) {
62
+ if (!artifact.ref || path.isAbsolute(artifact.ref) || artifact.ref.split(/[\\/]/).includes("..")) fail("invalid evidence artifact path");
63
+ if (platformDigest(readFileSync(path.join(root, path.dirname(item.ref), artifact.ref))) !== artifact.digest) fail("evidence artifact drift");
64
+ }
65
+ }
66
+ }
67
+ return { profile, entry, evidenceReports };
68
+ }
69
+ export function assertContractPlatform(contract, decision, options = {}) {
70
+ const binding = contract.platform_configuration;
71
+ const resolved = resolveBackendPlatform(binding, options);
72
+ if (contract.profiles?.platform !== resolved.profile.id || contract.profiles?.validation_namespace !== resolved.profile.validation_namespace) fail("platform and validation_namespace are inconsistent");
73
+ if (platformDigest(contract.maven_coordinates?.parent) !== platformDigest(binding.parent) || contract.maven_coordinates?.yss_components_version !== binding.bom.version || binding.bom.group_id !== "com.yss.cloud" || binding.bom.artifact_id !== "yss-components-bom") fail("YSS Maven coordinates mismatch");
74
+ if (decision && platformDigest(decision.platform_configuration) !== platformDigest(binding)) fail("decision/contract platform_configuration mismatch");
75
+ if (options.requireVerified !== false && !resolved.entry.evidence?.some(item => item.architecture_family === contract.architecture_family)) fail("architecture has no compatibility evidence");
76
+ for (const capability of contract.module_profile?.requested_capabilities ?? []) if (!resolved.entry.capabilities?.includes(capability)) fail(`unverified capability: ${capability}`);
77
+ if (options.requireVerified !== false && !resolved.evidenceReports.some(report => report.architecture_family === contract.architecture_family && (contract.module_profile?.requested_capabilities ?? []).every(capability => report.verified_capabilities?.includes(capability)))) fail("architecture/capability combination lacks evidence");
78
+ return resolved;
79
+ }
80
+ export function assertPlatformAgreement(left, right) {
81
+ if (platformDigest(left) !== platformDigest(right)) fail("platform_configuration drift between contract and Manifest");
82
+ }
83
+ export function javaMajor(output) {
84
+ const value = output.match(/(?:java|openjdk) version "(?:1\.)?(\d+)|Java version:\s*(?:1\.)?(\d+)/i);
85
+ return value ? Number(value[1] ?? value[2]) : null;
86
+ }
87
+ export function assertJavaPlatform(output, binding) {
88
+ if (javaMajor(output) !== binding.java_version) fail(`JDK mismatch: expected Java ${binding.java_version}`);
89
+ }
90
+ export function platformTemplateVars(profile) {
91
+ return { boot_version: profile.spring_boot_version, java_version: profile.java_version === 8 ? "1.8" : String(profile.java_version), java_range: profile.java_version === 8 ? "[1.8,1.9)" : `[${profile.java_version},${profile.java_version + 1})`, web_starter: profile.web_starter, web_test_starter: profile.web_test_starter, aop_starter: profile.aop_starter, swagger_artifact: profile.swagger_artifact, ...Object.fromEntries(Object.entries(profile.versions).map(([key, value]) => [`${key}_version`, value])) };
92
+ }
93
+
94
+ export function platformSmokeTest(basePackage, profile, capabilities = []) {
95
+ const mapper = profile.jackson_major === 3 ? "tools.jackson.databind.json.JsonMapper" : "com.fasterxml.jackson.databind.ObjectMapper";
96
+ return `package ${basePackage};
97
+
98
+ import ${profile.validation_namespace}.validation.Validator;
99
+ import ${profile.validation_namespace}.validation.Valid;
100
+ import org.springframework.beans.factory.annotation.Value;
101
+ import org.springframework.context.annotation.Import;
102
+ import org.springframework.web.bind.annotation.RestController;
103
+ import org.springframework.web.bind.annotation.PostMapping;
104
+ import org.springframework.web.bind.annotation.RequestBody;
105
+ import ${profile.validation_namespace}.validation.constraints.NotBlank;
106
+ import ${mapper};
107
+ import org.apache.ibatis.annotations.Select;
108
+ import org.apache.ibatis.session.SqlSession;
109
+ import org.apache.ibatis.session.SqlSessionFactory;
110
+ import org.junit.jupiter.api.Test;
111
+ import org.springframework.beans.factory.annotation.Autowired;
112
+ import org.springframework.boot.test.context.SpringBootTest;
113
+ import org.springframework.test.context.ActiveProfiles;
114
+ import static org.junit.jupiter.api.Assertions.*;
115
+
116
+ /** Mechanical integration only: no business endpoint or production storage. */
117
+ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
118
+ @Import(PlatformIntegrationTest.ProbeController.class)
119
+ @ActiveProfiles("scaffold-test")
120
+ class PlatformIntegrationTest {
121
+ @Value("\${local.server.port}") int port;
122
+ @Autowired Validator validator;
123
+ public static class ProbePayload {
124
+ @NotBlank private String value;
125
+ public String getValue() { return value; }
126
+ public void setValue(String value) { this.value = value; }
127
+ }
128
+ @RestController
129
+ public static class ProbeController {
130
+ @PostMapping(value = "/__scaffold_probe", consumes = "application/json", produces = "application/json")
131
+ public ProbePayload echo(@Valid @RequestBody ProbePayload body) { return body; }
132
+ }
133
+ @Test void httpJsonRoundTrip() throws Exception { httpProbe("probe", 200); }
134
+ @Test void httpValidationRejectsBlank() throws Exception { httpProbe("", 400); }
135
+ private void httpProbe(String value, int expectedStatus) throws Exception {
136
+ java.net.HttpURLConnection connection = (java.net.HttpURLConnection) new java.net.URL("http://127.0.0.1:" + port + "/__scaffold_probe").openConnection();
137
+ connection.setConnectTimeout(5000); connection.setReadTimeout(5000);
138
+ connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/json"); connection.setDoOutput(true);
139
+ ProbePayload request = new ProbePayload(); request.setValue(value);
140
+ try {
141
+ try (java.io.OutputStream stream = connection.getOutputStream()) { stream.write(mapper.writeValueAsBytes(request)); }
142
+ assertEquals(expectedStatus, connection.getResponseCode());
143
+ if (expectedStatus == 200) {
144
+ assertTrue(connection.getContentType().startsWith("application/json"));
145
+ try (java.io.InputStream stream = connection.getInputStream()) { assertEquals(value, mapper.readValue(stream, ProbePayload.class).getValue()); }
146
+ }
147
+ } finally { connection.disconnect(); }
148
+ }
149
+ @Autowired ${mapper.split(".").at(-1)} mapper;
150
+ @Autowired SqlSessionFactory sqlSessionFactory;
151
+ static final class ValidationProbe { @NotBlank String value = ""; }
152
+ @Test void validationAndJsonAutoConfiguration() throws Exception {
153
+ assertFalse(validator.validate(new ValidationProbe()).isEmpty());
154
+ assertEquals("\\\"probe\\\"", mapper.writeValueAsString("probe"));
155
+ }
156
+ interface ProbeMapper { @Select("SELECT 1") int probe(); }
157
+ @Test void mybatisCanMapVerificationQuery() throws Exception {
158
+ try (SqlSession session = sqlSessionFactory.openSession()) {
159
+ if (!session.getConfiguration().hasMapper(ProbeMapper.class)) session.getConfiguration().addMapper(ProbeMapper.class);
160
+ assertEquals(1, session.getMapper(ProbeMapper.class).probe());
161
+ }
162
+ }
163
+ ${capabilities.includes("feign-client") ? ` @Autowired org.springframework.cloud.openfeign.${profile.java_version === 8 ? "FeignContext" : "FeignClientFactory"} feignFactory;
164
+ @Test void feignCanDecodeJson() throws Exception {
165
+ feign.codec.Decoder decoder = feignFactory.getInstance("platform-probe", feign.codec.Decoder.class);
166
+ assertNotNull(decoder);
167
+ feign.Request request = feign.Request.create(feign.Request.HttpMethod.GET, "http://localhost/probe", java.util.Collections.emptyMap(), (byte[]) null, java.nio.charset.StandardCharsets.UTF_8, null);
168
+ feign.Response response = feign.Response.builder().request(request).status(200).reason("OK")
169
+ .headers(java.util.Collections.singletonMap("Content-Type", java.util.Collections.singletonList("application/json")))
170
+ .body("{}", java.nio.charset.StandardCharsets.UTF_8).build();
171
+ assertTrue(decoder.decode(response, java.util.Map.class) instanceof java.util.Map);
172
+ }
173
+ ` : ""}}
174
+ `;
175
+ }
@@ -102,7 +102,7 @@ export async function validateBackendScaffoldPrerequisites(contract, { contractF
102
102
  const approvalRef = prerequisites.engineering_contract_approval_ref;
103
103
  if (approvalRef !== contract.lifecycle_approval_ref || approvalRef !== contract.approval?.approval_ref) fail("工程合同批准引用与脚手架合同不一致");
104
104
  const approvalFile = resolveLocalRef(root, approvalRef, "工程合同批准记录");
105
- const approval = loadApprovalRecord(approvalFile);
105
+ const approval = loadApprovalRecord(approvalFile, 'gate.engineering-contract-approved');
106
106
  validateApprovalRecord(approval, { requireApproved: true, root });
107
107
  if (approval.gate_id !== "gate.engineering-contract-approved") fail("工程合同批准记录 gate_id 必须为 gate.engineering-contract-approved");
108
108
  if (!Array.isArray(approval.approval_scope) || !approval.approval_scope.includes(contract.contract_id) || !approval.approval_scope.includes(contract.project_name)) fail("工程合同批准范围未覆盖当前合同和项目");
@@ -0,0 +1,79 @@
1
+ import { decisionIO, decisionDigest, decisionError, assertUserDecisionRequirement } from './user-decision.mjs';
2
+
3
+ export const CONTINUATION_CAPABILITY = 'approved-scope-continuation-v1';
4
+ const fail = message => decisionError('user-decision-continuation-invalid', message);
5
+ const strings = value => Array.isArray(value) && value.length > 0 && value.every(x => typeof x === 'string' && x.trim()) && new Set(value).size === value.length;
6
+ const sameSet = (a, b) => strings(a) && strings(b) && a.length === b.length && a.every(x => b.includes(x));
7
+ const basisFields = ['business_scope', 'acceptance', 'contract_commitments', 'authorization', 'risk_acceptance', 'quality', 'external_commitments'];
8
+
9
+ // A continuation validates an explicit human mandate and an independent current
10
+ // review. It never infers semantic equivalence from whitespace or a boolean flag.
11
+ export function assertDecisionContinuation(requirement, roles, options = {}) {
12
+ const io = decisionIO(options);
13
+ const policy = roles.user_decision_policy.continuation;
14
+ if (policy?.capability !== CONTINUATION_CAPABILITY || !policy.boundaries.includes(requirement.boundary)) fail('未授权的延续边界');
15
+ const proof = io.document(requirement.continuation_ref);
16
+ if (proof.schema_version !== 1 || proof.kind !== CONTINUATION_CAPABILITY || proof.boundary !== requirement.boundary || proof.subject?.ref !== requirement.subject_ref || !sameSet(proof.scope, requirement.scope)) fail('当前边界、资产或范围不匹配');
17
+ const current = (asset, parse = true) => {
18
+ if (!asset?.ref || !asset.version || !asset.digest || decisionDigest(io.bytes(asset.ref)) !== asset.digest) fail(`当前证据缺失或过期: ${asset?.ref}`);
19
+ return parse ? io.document(asset.ref) : null;
20
+ };
21
+ if (!proof.source || proof.source.continuation_ref || proof.source.boundary !== 'delivery-scope') fail('必须引用原始交付范围批准,不能链式扩权');
22
+ const sourceResult = assertUserDecisionRequirement(proof.source, { ...options, rolesDoc: roles });
23
+ const mandate = io.document(proof.source.subject_ref);
24
+ if (mandate.schema_version !== 1 || mandate.kind !== 'delivery-authorization' || !Array.isArray(mandate.targets)) fail('缺少已展示并批准的交付授权清单');
25
+ if (!requirement.scope.every(x => proof.source.scope.includes(x))) fail('超出原始批准范围');
26
+ const matches = mandate.targets.filter(x => x.boundary === requirement.boundary && x.subject_ref === requirement.subject_ref && requirement.scope.every(s => x.scope?.includes(s)));
27
+ if (matches.length !== 1) fail('原授权未唯一覆盖当前边界、资产和范围');
28
+ const target = matches[0];
29
+ if (!basisFields.every(key => strings(target.decision_basis?.[key]))) fail('原授权缺少业务、验收、契约、授权、风险、质量或对外承诺依据');
30
+ if (!Array.isArray(mandate.basis) || !mandate.basis.length) fail('原授权缺少可读取的决定依据');
31
+ for (const asset of mandate.basis) {
32
+ if (!asset.ref || !asset.version || decisionDigest(io.bytes(asset.ref)) !== asset.digest) fail('原授权决定依据变化,须重新决定');
33
+ }
34
+ const external = current(mandate.external_policy);
35
+ if (external.status !== 'confirmed' || !Array.isArray(external.requirements)) fail('项目外部审批要求尚未确认,不能自动延续');
36
+ current(proof.subject, false);
37
+ if (requirement.boundary === 'implementation-scope') {
38
+ const manifest = io.document(proof.subject.ref);
39
+ if (manifest.kind !== 'implementation-scope' || !Array.isArray(manifest.slices)) fail('实施范围清单无效');
40
+ for (const ticket of requirement.scope) {
41
+ const slices = manifest.slices.filter(x => x.ticket_ref === ticket);
42
+ const limit = target.implementation_limits?.[ticket];
43
+ if (slices.length !== 1 || !limit || !sameSet(slices[0].repositories, limit.repositories) || !sameSet(slices[0].allowed_write_paths, limit.allowed_write_paths)) fail('实施仓库或写路径超出原授权边界');
44
+ }
45
+ }
46
+ if (!Array.isArray(proof.basis) || !proof.basis.length) fail('缺少本次实际验证证据');
47
+ for (const asset of proof.basis) {
48
+ if (!asset.ref || !asset.version || decisionDigest(io.bytes(asset.ref)) !== asset.digest) fail('本次验证证据过期');
49
+ }
50
+ const review = current(proof.review);
51
+ const actor = roles.roles.find(x => x.id === review.role_id);
52
+ if (!actor || !roles.runtimes.some(x => x.id === review.runtime_id) || !review.principal_ref || !review.drafter_principal_ref || review.principal_ref === review.drafter_principal_ref) fail('缺少独立专业审查身份');
53
+ const eligible = roles.gate_policy.continuation_reviews?.[requirement.boundary] || roles.gate_policy.dual_digital_human?.find(x => x.gate === requirement.boundary)?.countersigners;
54
+ if (!eligible?.includes(review.role_id)) fail('审查能力不覆盖当前边界');
55
+ if (review.decision !== 'approved' || !['within-approved-scope', 'presentation-only', 'implementation-detail'].includes(review.classification)) fail('未知或实质变化须重新决定');
56
+ if (!Array.isArray(review.material_changes) || review.material_changes.length || !Array.isArray(review.findings)) fail('存在实质变化或未完成影响分析');
57
+ for (const finding of review.findings) {
58
+ if (!finding.id || !finding.reason || !['requirement-violation', 'missing-evidence', 'important-risk', 'suggestion'].includes(finding.kind)) fail('审查发现未分类');
59
+ if (finding.kind === 'suggestion' && !finding.follow_up) fail('非阻断建议缺少待办去向');
60
+ if (finding.kind !== 'suggestion' && finding.status !== 'resolved') fail('未解决的缺陷、证据缺口或重要风险');
61
+ }
62
+ if (review.boundary !== requirement.boundary || !sameSet(review.scope, requirement.scope) || decisionDigest(review.subject) !== decisionDigest(proof.subject) || decisionDigest(review.basis) !== decisionDigest(proof.basis)) fail('审查未绑定当前资产、范围和验证证据');
63
+ if (decisionDigest(review.decision_basis) !== decisionDigest(target.decision_basis)) fail('决定依据有实质变化');
64
+ if (!review.reason?.trim() || !review.comparison?.before || !review.comparison?.after) fail('缺少可审阅的前后差异和等价性说明');
65
+ // Before is an immutable, originally approved snapshot; after is the current candidate.
66
+ const before = review.comparison.before;
67
+ if (!mandate.basis.some(x => decisionDigest(x) === decisionDigest(before)) || decisionDigest(review.comparison.after) !== decisionDigest(proof.subject)) fail('前后差异未绑定原授权快照和当前资产');
68
+ for (const obligation of external.requirements) {
69
+ if (!obligation.id || !strings(obligation.boundaries) || !strings(obligation.principals)) fail('外部审批制度记录不完整');
70
+ if (!obligation.boundaries.includes(requirement.boundary)) continue;
71
+ for (const principal of obligation.principals) {
72
+ const reply = proof.external_decisions?.find(x => x.obligation_id === obligation.id && x.principal_ref === principal);
73
+ if (!reply || reply.requirement?.continuation_ref || reply.requirement?.boundary !== requirement.boundary || reply.requirement?.subject_ref !== requirement.subject_ref || !sameSet(reply.requirement?.scope, requirement.scope)) fail('外部强制审批缺失或范围不符');
74
+ const result = assertUserDecisionRequirement(reply.requirement, { ...options, rolesDoc: roles });
75
+ if (!result.validated.length || result.validated.some(x => x.principal_ref !== principal)) fail('外部审批人与制度要求不符');
76
+ }
77
+ }
78
+ return { ...sourceResult, continued: true, review_ref: proof.review.ref };
79
+ }
@@ -1,3 +1,4 @@
1
+ import { normalizeSliceContract, sourceSliceContract, parseSliceYaml } from './slice-contract.mjs';
1
2
  import { assertExistingSliceStructure, createApprovedExecutionContext, verifySliceContractApproval } from './approved-execution-context.mjs';
2
3
  import path from 'node:path';
3
4
  import { readFileSync, existsSync } from 'node:fs';
@@ -46,7 +47,7 @@ function requireBackendCapability(key) {
46
47
  }
47
48
 
48
49
  /** Read-only: never executes input commands, starts services, unpacks archives or writes receipts. */
49
- export async function preflightDelivery(input,{stage,root=process.cwd()}={}) {
50
+ export async function preflightDelivery(input,{stage,root=process.cwd(),work_unit_id}={}) {
50
51
  try { ensure(STAGES.includes(stage),'未知阶段;必须是 prepare|build|export|accept');schema(input,'docs/process/schemas/delivery-preflight-input.schema.json'); }
51
52
  catch(error) { return invalidPreflightInput(error.message); }
52
53
  root=path.resolve(root,input.governance_root||'.');
@@ -78,7 +79,7 @@ export async function preflightDelivery(input,{stage,root=process.cwd()}={}) {
78
79
  if(input.architecture_identity.source_kind==='existing-registration')ensure(input.architecture_identity.repository_id===input.scope.repository_id&&input.architecture_identity.project_id===input.scope.project_id,'架构身份与预检目标仓库/项目不一致');
79
80
  },{source:'architecture_identity'});
80
81
  if(valid.has('architecture.identity'))await run('architecture.profile',()=>{ensure(architecture.validateArchitectureIdentity(input.architecture_identity).maturity==='supported','不支持未达到 supported 的 architecture_profile');},{source:'architecture_profile'});
81
- if(['build','export','accept'].includes(stage)&&assets.slice_contract)await run('slice_contract.execution',()=>{requireBackendCapability('slice_contract');execution=createApprovedExecutionContext(assets.slice_contract,{root});},{from:'build',source:assets.slice_contract.approval_ref||'slice_contract',evidence:[assets.slice_contract.ref,...(assets.slice_contract.approval_ref?[assets.slice_contract.approval_ref]:[])]});
82
+ if(['build','export','accept'].includes(stage)&&assets.slice_contract)await run('slice_contract.execution',()=>{requireBackendCapability('slice_contract');execution=createApprovedExecutionContext(assets.slice_contract,{root,work_unit_id});},{from:'build',source:assets.slice_contract.approval_ref||'slice_contract',evidence:[assets.slice_contract.ref,...(assets.slice_contract.approval_ref?[assets.slice_contract.approval_ref]:[])]});
82
83
  const archDeps=['architecture.identity',...['repository_registration','engineering_baseline','manifest'].map(x=>`architecture.${x}`)];
83
84
  if(archDeps.every(x=>valid.has(x)))await run('architecture',()=>{
84
85
  ensure(typeof architecture.verifyArchitectureEvidence==='function','不支持既有工程原始证据验证,请同步支持该身份版本的模板运行时');
@@ -143,12 +144,12 @@ async function verifyAsset(key,data,binding,{root,input,documents,assets,executi
143
144
  await validateTechnicalDesign(data,{root,sliceRef:input.scope.slice_id,readOnly:true,execution});
144
145
  await approved(root,binding,['gate.engineering-contract-approved','gate.technical-design-approved']);
145
146
  } else if(key==='slice_contract') {
146
- const contract=data.slice_contract||data;
147
+ const contract=normalizeSliceContract(data,{root});
147
148
  assertExistingSliceStructure(contract);
148
- ensure(contract.schema_version===2&&contract.status==='approved'&&contract.slice_id===input.scope.slice_id,'Slice 合同版本、批准状态或切片不匹配');
149
+ ensure([2,3].includes(contract.schema_version)&&contract.status==='approved'&&contract.slice_id===input.scope.slice_id,'Slice 合同版本、批准状态或切片不匹配');
149
150
  ensure(binding.id===contract.contract_id&&binding.version===contract.contract_version,'Slice 合同身份与引用不一致');
150
151
  const compiler=read(safe(ROOT,'.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml'));
151
- for(const [section,fields]of Object.entries(compiler.slice_contract_required))for(const field of fields)ensure(Object.hasOwn(section==='root'?contract:contract[section]||{},field),`合同缺少 ${section}.${field}`);
152
+ if(contract.schema_version===2)for(const [section,fields]of Object.entries(compiler.slice_contract_required))for(const field of fields)ensure(Object.hasOwn(section==='root'?contract:contract[section]||{},field),`合同缺少 ${section}.${field}`);
152
153
  ensure(contract.readiness.blockers.length===0&&contract.readiness.stale_inputs.length===0,'Slice 合同仍有 blocker 或 stale input');
153
154
  const resolution=contract.resolution;
154
155
  ensure(resolution.freshness==='current','Slice resolution 非 current');
@@ -388,6 +388,16 @@ export function validateDigitalHumanRoles(doc, { skillIds, stageIds, gateIds, ar
388
388
  }
389
389
 
390
390
  const decisions = doc.user_decision_policy;
391
+ if (decisions?.continuation) {
392
+ const continuation = decisions.continuation;
393
+ if (continuation.capability !== 'approved-scope-continuation-v1' || continuation.source_boundary !== 'delivery-scope' || continuation.unknown_change !== 'blocked' || continuation.external_policy_unconfirmed !== 'no-automatic-continuation') fail('授权延续策略不能省略未知变化或外部制度保护');
394
+ requireStringArray(continuation.boundaries, 'continuation.boundaries');
395
+ for (const boundary of continuation.boundaries) {
396
+ if (!gateIds.has(boundary) && boundary !== 'implementation-scope') fail(`未支持的延续边界: ${boundary}`);
397
+ requireStringArray(policy.continuation_reviews?.[boundary], `${boundary}.continuation_reviews`);
398
+ for (const role of policy.continuation_reviews[boundary]) if (!actors.has(role)) fail(`未知延续审查角色: ${role}`);
399
+ }
400
+ }
391
401
  if (decisions?.schema_version !== 1 || decisions.default_responder !== "requester" || decisions.delegate_requires_requester_evidence !== true) fail("缺少统一用户决定策略");
392
402
  requireStringArray(decisions.gates, "user_decision_policy.gates");
393
403
  for (const gate of decisions.gates) if (!gateIds.has(gate)) fail(`用户决定引用未知门禁: ${gate}`);
@@ -1,3 +1,4 @@
1
+ import { normalizeSliceContract, sourceSliceContract, parseSliceYaml } from './slice-contract.mjs';
1
2
  import { loadDeliveryProfile } from './harness-execution-scope.mjs';
2
3
  import { existsSync } from 'node:fs';
3
4
  import path from 'node:path';
@@ -8,6 +9,7 @@ import { ROOT, read, safe, ensure, digest } from './strategic-handoff-io.mjs';
8
9
  // Always re-executes the verifier; a caller-supplied "verified" flag is never evidence.
9
10
  export function enforceFrontendDelivery(state={}, {root=ROOT,phase='inputs'}={}) {
10
11
  ensure(['preflight','design','contract','inputs','implementation','verification'].includes(phase),`未知前端交付阶段: ${phase}`);
12
+ if(state.schema_version===3)state=normalizeSliceContract(state,{root});
11
13
  const profile=loadDeliveryProfile(root);
12
14
  let contract;
13
15
  const contractRef=state.slice_contract_ref||state.contract?.slice_contract_ref;
@@ -35,6 +37,7 @@ export function enforceFrontendDelivery(state={}, {root=ROOT,phase='inputs'}={})
35
37
  const file=path.resolve(root,contractRef);
36
38
  if(existsSync(file)) {
37
39
  const document=read(file);contract=document.slice_contract||document;
40
+ if(contract.schema_version===3)contract=normalizeSliceContract(contract,{root});
38
41
  const direct=contract.frontend?.delivery, resolved=contract.resolution?.frontend_delivery;
39
42
  ensure(!direct||!resolved||digest(direct)===digest(resolved),'Slice Contract 前端交付绑定冲突');
40
43
  binding=direct||resolved||binding;
@@ -1,3 +1,6 @@
1
+ import { resolveBackendPlatform } from "./backend-platform.mjs";
2
+ import { safe } from './strategic-handoff-io.mjs';
3
+ import { selectSliceWorkUnit, normalizeSliceContract, withinSlicePath } from './slice-contract.mjs';
1
4
  import { createApprovedExecutionContext, createApprovedRecompilationContext, assertApprovedExecutionContext } from './approved-execution-context.mjs';
2
5
  import { enforceTechnicalDesign } from './technical-design-boundary.mjs';
3
6
  import { enforceHarnessSkillScope } from "./harness-execution-scope.mjs";
@@ -67,13 +70,15 @@ export function compileImplementationContract({
67
70
  architecture_identity,
68
71
  architecture_evidence,
69
72
  approved_slice,
73
+ work_unit_id,
70
74
  root = ROOT,
71
75
  slice_id,
72
76
  frontend_delivery,
73
- technical_design
77
+ technical_design,
78
+ readOnly = false
74
79
  }) {
75
80
  assertV2(registry, compilerContract);
76
- const recompilationExecution=approved_slice?createApprovedRecompilationContext(approved_slice,{root}):undefined;
81
+ const recompilationExecution=approved_slice?createApprovedRecompilationContext(approved_slice,{root,work_unit_id}):undefined;
77
82
  const deliveryInput = enforceFrontendDelivery({ slice_id, frontend_delivery }, { root });
78
83
  if (!Array.isArray(recipeIds) || !Array.isArray(requiredCapabilities) || !Array.isArray(conditions)) {
79
84
  fail("recipeIds、requiredCapabilities 与 conditions 必须是数组");
@@ -96,7 +101,8 @@ export function compileImplementationContract({
96
101
  for (const recipe of orderedRecipes) if (recipe.architecture_family && recipe.architecture_family !== architecture_identity.architecture_family) fail(`Recipe ${recipe.id} 与架构族不匹配`);
97
102
  }
98
103
 
99
- enforceTechnicalDesign({ technical_design, conditions, architecture_identity, slice_id }, { root, execution:recompilationExecution });
104
+ if (architecture_identity?.platform_configuration) resolveBackendPlatform(architecture_identity.platform_configuration);
105
+ enforceTechnicalDesign({ technical_design, conditions, architecture_identity, slice_id }, { root, execution:recompilationExecution, readOnly });
100
106
 
101
107
  const capabilitySources = new Map();
102
108
  const orderedCapabilities = [];
@@ -206,14 +212,17 @@ export function compileDefaultImplementationContract(input = {}) {
206
212
  });
207
213
  }
208
214
 
209
- export function evaluateContractFreshness(contract, { registry, compilerContract, root = ROOT, approved_slice, readOnly = false }, execution) {
215
+ export function evaluateContractFreshness(contract, { registry, compilerContract, root = ROOT, approved_slice, readOnly = false, work_unit_id }, execution) {
210
216
  assertV2(registry, compilerContract);
211
- if (contract?.schema_version !== 2) fail("Slice Implementation Contract schema v1 已停止支持;必须重新编译 v2 合同");
217
+ try { contract=normalizeSliceContract(contract,{root}); } catch(error) { return {freshness:'stale',reasons:[error.message]}; }
218
+ if (![2,3].includes(contract?.schema_version)) fail("Slice Implementation Contract schema v1 已停止支持;必须重新编译 v2 合同");
219
+ const all=contract;
220
+ try {contract=selectSliceWorkUnit(contract,work_unit_id);} catch(error){return {freshness:'stale',reasons:[error.message]};}
212
221
  const resolution = contract.resolution ?? contract;
213
222
  const reasons = [];
214
223
  let trustedExecution;
215
224
  try {
216
- trustedExecution=approved_slice?createApprovedExecutionContext(approved_slice,{root,contract}):execution;
225
+ trustedExecution=approved_slice?createApprovedExecutionContext(approved_slice,{root,contract:all,work_unit_id}):execution;
217
226
  if(trustedExecution)assertApprovedExecutionContext(trustedExecution,{root,contract});
218
227
  } catch(error) { reasons.push(error.code||'EXECUTION_APPROVAL_INVALID');trustedExecution=undefined; }
219
228
  try { enforceTechnicalDesign({ ...resolution, slice_id: contract.slice_id ?? resolution.slice_id }, { root,execution:trustedExecution,readOnly }); }
@@ -236,11 +245,13 @@ export function evaluateContractFreshness(contract, { registry, compilerContract
236
245
 
237
246
  export function validateExecutionResult(result, contract, current) {
238
247
  if (result?.schema_version !== 2) fail("YSS Skill Execution Result schema v1 已停止支持;请迁移到 v2");
239
- if (contract?.schema_version !== 2) fail("Slice Implementation Contract schema v1 已停止支持;必须重新编译 v2 合同");
248
+ contract=normalizeSliceContract(contract,{root:current?.root || ROOT});
249
+ if (![2,3].includes(contract?.schema_version)) fail("Slice Implementation Contract schema v1 已停止支持;必须重新编译 v2 合同");
240
250
  if (!EXECUTION_STATUSES.has(result.status)) fail(`未知 execution result status: ${result.status}`);
241
- if(contract.resolution?.architecture_identity?.schema_version===2&&!current?.approved_slice)return {status:'stale',blockers:['EXECUTION_APPROVAL_REQUIRED']};
242
- const freshness = evaluateContractFreshness(contract, current);
251
+ if((contract.schema_version===3||contract.resolution?.architecture_identity?.schema_version===2)&&!current?.approved_slice)return {status:'stale',blockers:['EXECUTION_APPROVAL_REQUIRED']};
252
+ const freshness = evaluateContractFreshness(contract, {...current,work_unit_id:result.work_unit_id});
243
253
  if (freshness.freshness === "stale") return { status: "stale", blockers: freshness.reasons };
254
+ contract=selectSliceWorkUnit(contract,result.work_unit_id);
244
255
  const consumed = result.consumed_contract ?? {};
245
256
  const resolution = contract.resolution ?? contract;
246
257
  const blockers = [];
@@ -253,6 +264,28 @@ export function validateExecutionResult(result, contract, current) {
253
264
  if (!item?.command || item.exit_code === undefined || !item.executed_at) blockers.push("verification-result-incomplete");
254
265
  else if (item.exit_code !== 0) blockers.push("verification-failed");
255
266
  }
267
+ if(contract.schema_version===3) {
268
+ const unit=contract.work_units.find(item=>item.id===result.work_unit_id);
269
+ if(!unit)blockers.push('work-unit-mismatch');
270
+ else {
271
+ const checks=unit.work_unit.verification;
272
+ for(const check of checks)if(!result.verification_results?.some(item=>item.command===check.command&&item.exit_code===0&&item.cwd===check.cwd&&(!check.dependency_roots||JSON.stringify(item.dependency_roots)===JSON.stringify(check.dependency_roots))))blockers.push('verification-coverage-or-cwd-missing');
273
+ if(!Array.isArray(result.changed_files))blockers.push('changed-files-missing');
274
+ else for(const item of result.changed_files) {
275
+ const changed=typeof item==='string'?item:item.path;
276
+ if(contract.repositories&&(typeof item==='string'||item.project_root!==unit.project_root))blockers.push('changed-file-repository-mismatch');
277
+ if(!unit.allowed_write_paths.some(parent=>withinSlicePath(changed,parent)))blockers.push('write-scope-violation');
278
+ }
279
+ const evidence=result.evidence_files||[];
280
+ for(const ref of unit.work_unit.expected_evidence) {
281
+ if(!evidence.some(item=>(typeof item==='string'?item:item.path)===ref&&(!contract.repositories||item.project_root===unit.project_root)))blockers.push('expected-evidence-missing');
282
+ else {try {readFileSync(safe(contract.repositories?unit.project_root:(current.root||ROOT),ref));}catch {blockers.push('expected-evidence-unreadable');}}
283
+ }
284
+ }
285
+ if(['drift','violation'].includes(result.status))blockers.push(result.status);
286
+ if(result.status==='not-applicable'&&!result.not_applicable_reason?.trim())blockers.push('not-applicable-reason-missing');
287
+ if(result.status==='seam-deferred'&&(!result.seam_deferred?.length||result.seam_deferred.some(item=>['risk','owner','follow_up_ticket','verification_plan','target_version_or_release_date'].some(key=>!item[key]))))blockers.push('seam-deferred-incomplete');
288
+ }
256
289
  if (Array.isArray(result.new_impacts) && result.new_impacts.length) blockers.push("new-impacts");
257
290
  return { status: blockers.length ? "blocked" : "accepted", blockers: [...new Set(blockers)] };
258
291
  }
@@ -46,7 +46,7 @@ export function assertGateChecks(gateId, state, { root = ROOT, registry = loadRe
46
46
  const rule = countersignRuleForGate(rolesDoc.gate_policy, id);
47
47
  if (rule) {
48
48
  if (!refs.has(item.approval_ref) || !refs.has(item.subject_ref)) fail(`${id} 未绑定审查与资产`);
49
- const record = loadApprovalRecord(path.resolve(root, item.approval_ref));
49
+ const record = loadApprovalRecord(path.resolve(root, item.approval_ref), id);
50
50
  if (record.gate_id !== id || record.subject_ref !== item.subject_ref) fail(`${id} 审查对象不匹配`);
51
51
  if (!item.approval_scope?.length || JSON.stringify([...item.approval_scope].sort()) !== JSON.stringify([...(record.approval_scope || [])].sort())) fail(`${id} 审查范围不匹配`);
52
52
  const subjectDigest = createHash('sha256').update(readFileSync(path.resolve(root, item.subject_ref))).digest('hex');
@@ -65,7 +65,7 @@ export function assertGateChecks(gateId, state, { root = ROOT, registry = loadRe
65
65
  const approvalRequired = countersignRuleForGate(rolesDoc.gate_policy, gateId);
66
66
  if (approvalRequired) {
67
67
  if (!refs.has(item.approval_ref) || !refs.has(item.subject_ref)) fail(`${gateId} 缺少已绑定批准记录和审阅包`);
68
- const record = loadApprovalRecord(path.resolve(root, item.approval_ref));
68
+ const record = loadApprovalRecord(path.resolve(root, item.approval_ref), gateId);
69
69
  if (!record.drafter_principal_ref || record.drafter_principal_ref === record.principal_ref) fail(`${gateId} 缺少独立审查身份或起草者自签`);
70
70
  const bytes = readFileSync(path.resolve(root, item.subject_ref));
71
71
  if (record.subject_ref !== item.subject_ref || record.subject_digest !== createHash('sha256').update(bytes).digest('hex')) fail(`${gateId} 批准依据过期`);
@@ -1,3 +1,5 @@
1
+ // Wire capability marker: profile-local readiness rules are not interchangeable.
2
+ export const SLICE_REPOSITORY_PREPARATION_PROTOCOL = 1;
1
3
  import { createHash } from "node:crypto";
2
4
  import { existsSync, readFileSync } from "node:fs";
3
5
  import { parseDocument } from "../vendor/yaml.mjs";
@@ -168,7 +170,7 @@ function backendDesignPrerequisitesReady(prerequisites, exists, root, projectId)
168
170
  const approvalFile = path.isAbsolute(prerequisites.engineering_contract_approval_ref)
169
171
  ? prerequisites.engineering_contract_approval_ref
170
172
  : path.resolve(root, prerequisites.engineering_contract_approval_ref);
171
- const approval = loadApprovalRecord(approvalFile);
173
+ const approval = loadApprovalRecord(approvalFile, 'gate.engineering-contract-approved');
172
174
  validateApprovalRecord(approval, { requireApproved: true, root });
173
175
  if (approval.gate_id !== "gate.engineering-contract-approved" || !approval.approval_scope?.includes(projectId)) return false;
174
176
  if (!approvalHasBinding(approval, technical.expected) || !approvalHasBinding(approval, data.expected)) return false;
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { verifyContextReconciliation } from './context-reconciliation.mjs';
3
3
  import { decisionIO, decisionDigest, assertUserDecisionRequirement } from './user-decision.mjs';
4
- import { validateApprovalRecord } from './approval-record.mjs';
4
+ import { validateApprovalRecord, selectApprovalRecord } from './approval-record.mjs';
5
5
 
6
6
  const fail = message => { throw new TypeError(`plan-spec-entry-blocked: ${message}`); };
7
7
  const text = value => typeof value === 'string' && value.trim().length > 0;
@@ -56,7 +56,7 @@ export function assertPlanSpecEntry(state, options = {}) {
56
56
  evidence(gate?.evidence_refs);
57
57
  if (review.impacts[impact]) {
58
58
  if (gate.status !== 'approved' || !basis.has(gate.approval_ref) || !basis.has(gate.subject_ref)) fail(`命中门禁未批准或未绑定依据: ${gateId}`);
59
- const record = io.document(gate.approval_ref);
59
+ const record = selectApprovalRecord(io.document(gate.approval_ref), gateId);
60
60
  if (record.gate_id !== gateId || record.subject_ref !== gate.subject_ref || !gate.approval_scope?.includes(state.feature_id) || JSON.stringify([...(gate.approval_scope || [])].sort()) !== JSON.stringify([...(record.approval_scope || [])].sort())) fail(`会签资产或范围不匹配: ${gateId}`);
61
61
  validateApprovalRecord(record, { ...options, requireApproved: true });
62
62
  } else if (gate.status !== 'not-applicable' || !text(gate.reason)) fail(`未命中门禁须有原因和依据: ${gateId}`);
@@ -72,7 +72,7 @@ export function assertPlanSpecEntry(state, options = {}) {
72
72
  if (reconciliation.status !== 'reconciled' || reconciliation.repository_mode !== 'project-instance') fail('Context 未调和');
73
73
  try { verifyContextReconciliation(path.resolve(io.root, review.context_reconciliation_ref), { root: io.root }); }
74
74
  catch (error) { fail(`Context reconciliation 验证失败: ${error.message}\n`); }
75
- assertUserDecisionRequirement({ boundary: 'gate.plan-approved', subject_ref: state.plan_review_ref, scope: [state.feature_id], user_decision_ref: state.plan_user_decision_ref }, options);
75
+ assertUserDecisionRequirement({ boundary: 'gate.plan-approved', subject_ref: state.plan_review_ref, scope: [state.feature_id], user_decision_ref: state.plan_user_decision_ref, continuation_ref: state.plan_continuation_ref }, options);
76
76
  return { result: 'allowed', blocking_signals: [], missing_requirements: [], evidence_refs: [state.plan_review_ref, ...basis.keys()], next_work_unit: null };
77
77
  }
78
78
 
@@ -14,6 +14,7 @@ export function localDatabaseConfiguration(name) {
14
14
 
15
15
  export function scaffoldArchitectureIdentity(contract, contractDigest) {
16
16
  return {
17
+ ...(contract.platform_configuration ? { platform_configuration: contract.platform_configuration } : {}),
17
18
  architecture_family: contract.architecture_family,
18
19
  architecture_profile: contract.architecture_profile,
19
20
  generator_skill: contract.generator_skill,
@@ -0,0 +1,10 @@
1
+ // Interpret the published lifecycle check, without creating a second gate registry.
2
+ export function sliceCheckApplicability(scope,registry) {
3
+ if(!['low','medium','high'].includes(scope.risk_level))throw new TypeError('缺少明确风险等级,不能裁剪材料');
4
+ if(scope.impacted_areas.some(impact=>!['ui','frontend','backend','api','data','persistence','domain','architecture','cross-repo','cross-boundary','high-risk'].includes(impact)))throw new TypeError('未知影响不能裁剪材料,先补影响分析');
5
+ const check=registry.checks?.find(check=>check.id==='check.architecture-reviewed');
6
+ // Unknown source rule revisions need an adapter update, never a local default.
7
+ if(check?.trigger!=='高风险或跨边界变化。')throw new TypeError('不支持当前生命周期架构审查规则');
8
+ const required=scope.risk_level==='high'||scope.impacted_areas.includes('high-risk')||scope.impacted_areas.some(impact=>['architecture','cross-repo','cross-boundary'].includes(impact))||scope.project_roots.length>1;
9
+ return {[check.id]:{status:required?'required':'not-applicable',reason:`${check.trigger} 本切片风险 ${scope.risk_level},影响 ${scope.impacted_areas.join(', ')||'无'},工程数 ${scope.project_roots.length}。`}};
10
+ }