create-yss-spec 2.2.3 → 2.2.5

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 (341) hide show
  1. package/README.md +17 -1
  2. package/package.json +1 -1
  3. package/src/cli.js +15 -1
  4. package/src/self-update.js +277 -0
  5. package/template/.agents/skills/yss-domain/SKILL.md +5 -4
  6. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +15 -14
  7. package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  8. package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  9. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  10. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  11. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +7 -2
  12. package/template/.agents/skills/yss-router/SKILL.md +4 -2
  13. package/template/.agents/skills/yss-router/references/router-contract.yaml +18 -3
  14. package/template/.agents/skills/yss-router/references/slice-implementation-contract.md +58 -1
  15. package/template/.agents/skills/yss-stage-decision/SKILL.md +50 -0
  16. package/template/.agents/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  17. package/template/.agents/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  18. package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  19. package/template/.agents/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  20. package/template/.agents/skills/yss-stage-decision/references/validation-rules.md +18 -0
  21. package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  22. package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  23. package/template/.agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  24. package/template/.agents/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  25. package/template/.agents/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  26. package/template/.agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  27. package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  28. package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  29. package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  30. package/template/.agents/skills/yss-tactical-design/SKILL.md +33 -0
  31. package/template/.agents/skills/yss-tactical-design/agents/openai.yaml +4 -0
  32. package/template/.agents/skills/yss-tactical-design/references/output-template.md +28 -0
  33. package/template/.agents/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  34. package/template/.agents/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  35. package/template/.agents/skills/yss-tactical-design/references/validation-rules.md +13 -0
  36. package/template/.agents/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  37. package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  38. package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  39. package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  40. package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  41. package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  42. package/template/.agents/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  43. package/template/.agents/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  44. package/template/.claude/skills/yss-domain/SKILL.md +5 -4
  45. package/template/.claude/skills/yss-product-lifecycle/SKILL.md +15 -14
  46. package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  47. package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  48. package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  49. package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  50. package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +7 -2
  51. package/template/.claude/skills/yss-router/SKILL.md +4 -2
  52. package/template/.claude/skills/yss-router/references/router-contract.yaml +18 -3
  53. package/template/.claude/skills/yss-router/references/slice-implementation-contract.md +58 -1
  54. package/template/.claude/skills/yss-stage-decision/SKILL.md +50 -0
  55. package/template/.claude/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  56. package/template/.claude/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  57. package/template/.claude/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  58. package/template/.claude/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  59. package/template/.claude/skills/yss-stage-decision/references/validation-rules.md +18 -0
  60. package/template/.claude/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  61. package/template/.claude/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  62. package/template/.claude/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  63. package/template/.claude/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  64. package/template/.claude/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  65. package/template/.claude/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  66. package/template/.claude/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  67. package/template/.claude/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  68. package/template/.claude/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  69. package/template/.claude/skills/yss-tactical-design/SKILL.md +33 -0
  70. package/template/.claude/skills/yss-tactical-design/agents/openai.yaml +4 -0
  71. package/template/.claude/skills/yss-tactical-design/references/output-template.md +28 -0
  72. package/template/.claude/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  73. package/template/.claude/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  74. package/template/.claude/skills/yss-tactical-design/references/validation-rules.md +13 -0
  75. package/template/.claude/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  76. package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  77. package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  78. package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  79. package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  80. package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  81. package/template/.claude/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  82. package/template/.claude/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  83. package/template/.codex/skills/yss-domain/SKILL.md +5 -4
  84. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +15 -14
  85. package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  86. package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  87. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  88. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  89. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +7 -2
  90. package/template/.codex/skills/yss-router/SKILL.md +4 -2
  91. package/template/.codex/skills/yss-router/references/router-contract.yaml +18 -3
  92. package/template/.codex/skills/yss-router/references/slice-implementation-contract.md +58 -1
  93. package/template/.codex/skills/yss-stage-decision/SKILL.md +50 -0
  94. package/template/.codex/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  95. package/template/.codex/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  96. package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  97. package/template/.codex/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  98. package/template/.codex/skills/yss-stage-decision/references/validation-rules.md +18 -0
  99. package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  100. package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  101. package/template/.codex/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  102. package/template/.codex/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  103. package/template/.codex/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  104. package/template/.codex/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  105. package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  106. package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  107. package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  108. package/template/.codex/skills/yss-tactical-design/SKILL.md +33 -0
  109. package/template/.codex/skills/yss-tactical-design/agents/openai.yaml +4 -0
  110. package/template/.codex/skills/yss-tactical-design/references/output-template.md +28 -0
  111. package/template/.codex/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  112. package/template/.codex/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  113. package/template/.codex/skills/yss-tactical-design/references/validation-rules.md +13 -0
  114. package/template/.codex/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  115. package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  116. package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  117. package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  118. package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  119. package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  120. package/template/.codex/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  121. package/template/.codex/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  122. package/template/.cursor/skills/yss-domain/SKILL.md +5 -4
  123. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +15 -14
  124. package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  125. package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  126. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  127. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  128. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +7 -2
  129. package/template/.cursor/skills/yss-router/SKILL.md +4 -2
  130. package/template/.cursor/skills/yss-router/references/router-contract.yaml +18 -3
  131. package/template/.cursor/skills/yss-router/references/slice-implementation-contract.md +58 -1
  132. package/template/.cursor/skills/yss-stage-decision/SKILL.md +50 -0
  133. package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  134. package/template/.cursor/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  135. package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  136. package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  137. package/template/.cursor/skills/yss-stage-decision/references/validation-rules.md +18 -0
  138. package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  139. package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  140. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  141. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  142. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  143. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  144. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  145. package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  146. package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  147. package/template/.cursor/skills/yss-tactical-design/SKILL.md +33 -0
  148. package/template/.cursor/skills/yss-tactical-design/agents/openai.yaml +4 -0
  149. package/template/.cursor/skills/yss-tactical-design/references/output-template.md +28 -0
  150. package/template/.cursor/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  151. package/template/.cursor/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  152. package/template/.cursor/skills/yss-tactical-design/references/validation-rules.md +13 -0
  153. package/template/.cursor/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  154. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  155. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  156. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  157. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  158. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  159. package/template/.cursor/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  160. package/template/.cursor/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  161. package/template/.hermes/skills/yss-domain/SKILL.md +5 -4
  162. package/template/.hermes/skills/yss-product-lifecycle/SKILL.md +15 -14
  163. package/template/.hermes/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  164. package/template/.hermes/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  165. package/template/.hermes/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  166. package/template/.hermes/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  167. package/template/.hermes/skills/yss-product-lifecycle/references/state-model.md +7 -2
  168. package/template/.hermes/skills/yss-router/SKILL.md +4 -2
  169. package/template/.hermes/skills/yss-router/references/router-contract.yaml +18 -3
  170. package/template/.hermes/skills/yss-router/references/slice-implementation-contract.md +58 -1
  171. package/template/.hermes/skills/yss-stage-decision/SKILL.md +50 -0
  172. package/template/.hermes/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  173. package/template/.hermes/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  174. package/template/.hermes/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  175. package/template/.hermes/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  176. package/template/.hermes/skills/yss-stage-decision/references/validation-rules.md +18 -0
  177. package/template/.hermes/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  178. package/template/.hermes/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  179. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  180. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  181. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  182. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  183. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  184. package/template/.hermes/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  185. package/template/.hermes/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  186. package/template/.hermes/skills/yss-tactical-design/SKILL.md +33 -0
  187. package/template/.hermes/skills/yss-tactical-design/agents/openai.yaml +4 -0
  188. package/template/.hermes/skills/yss-tactical-design/references/output-template.md +28 -0
  189. package/template/.hermes/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  190. package/template/.hermes/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  191. package/template/.hermes/skills/yss-tactical-design/references/validation-rules.md +13 -0
  192. package/template/.hermes/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  193. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  194. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  195. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  196. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  197. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  198. package/template/.hermes/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  199. package/template/.hermes/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  200. package/template/.pi/skills/yss-domain/SKILL.md +5 -4
  201. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +15 -14
  202. package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  203. package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  204. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  205. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  206. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +7 -2
  207. package/template/.pi/skills/yss-router/SKILL.md +4 -2
  208. package/template/.pi/skills/yss-router/references/router-contract.yaml +18 -3
  209. package/template/.pi/skills/yss-router/references/slice-implementation-contract.md +58 -1
  210. package/template/.pi/skills/yss-stage-decision/SKILL.md +50 -0
  211. package/template/.pi/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  212. package/template/.pi/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  213. package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  214. package/template/.pi/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  215. package/template/.pi/skills/yss-stage-decision/references/validation-rules.md +18 -0
  216. package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  217. package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  218. package/template/.pi/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  219. package/template/.pi/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  220. package/template/.pi/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  221. package/template/.pi/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  222. package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  223. package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  224. package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  225. package/template/.pi/skills/yss-tactical-design/SKILL.md +33 -0
  226. package/template/.pi/skills/yss-tactical-design/agents/openai.yaml +4 -0
  227. package/template/.pi/skills/yss-tactical-design/references/output-template.md +28 -0
  228. package/template/.pi/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  229. package/template/.pi/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  230. package/template/.pi/skills/yss-tactical-design/references/validation-rules.md +13 -0
  231. package/template/.pi/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  232. package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  233. package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  234. package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  235. package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  236. package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  237. package/template/.pi/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  238. package/template/.pi/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  239. package/template/.qoder/skills/yss-domain/SKILL.md +5 -4
  240. package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +15 -14
  241. package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  242. package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  243. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  244. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  245. package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +7 -2
  246. package/template/.qoder/skills/yss-router/SKILL.md +4 -2
  247. package/template/.qoder/skills/yss-router/references/router-contract.yaml +18 -3
  248. package/template/.qoder/skills/yss-router/references/slice-implementation-contract.md +58 -1
  249. package/template/.qoder/skills/yss-stage-decision/SKILL.md +50 -0
  250. package/template/.qoder/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  251. package/template/.qoder/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  252. package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  253. package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  254. package/template/.qoder/skills/yss-stage-decision/references/validation-rules.md +18 -0
  255. package/template/.qoder/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  256. package/template/.qoder/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  257. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  258. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  259. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  260. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  261. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  262. package/template/.qoder/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  263. package/template/.qoder/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  264. package/template/.qoder/skills/yss-tactical-design/SKILL.md +33 -0
  265. package/template/.qoder/skills/yss-tactical-design/agents/openai.yaml +4 -0
  266. package/template/.qoder/skills/yss-tactical-design/references/output-template.md +28 -0
  267. package/template/.qoder/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  268. package/template/.qoder/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  269. package/template/.qoder/skills/yss-tactical-design/references/validation-rules.md +13 -0
  270. package/template/.qoder/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  271. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  272. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  273. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  274. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  275. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  276. package/template/.qoder/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  277. package/template/.qoder/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  278. package/template/.trae/skills/yss-domain/SKILL.md +5 -4
  279. package/template/.trae/skills/yss-product-lifecycle/SKILL.md +15 -14
  280. package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
  281. package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +2 -2
  282. package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
  283. package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +6 -3
  284. package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +7 -2
  285. package/template/.trae/skills/yss-router/SKILL.md +4 -2
  286. package/template/.trae/skills/yss-router/references/router-contract.yaml +18 -3
  287. package/template/.trae/skills/yss-router/references/slice-implementation-contract.md +58 -1
  288. package/template/.trae/skills/yss-stage-decision/SKILL.md +50 -0
  289. package/template/.trae/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
  290. package/template/.trae/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
  291. package/template/.trae/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
  292. package/template/.trae/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
  293. package/template/.trae/skills/yss-stage-decision/references/validation-rules.md +18 -0
  294. package/template/.trae/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
  295. package/template/.trae/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
  296. package/template/.trae/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
  297. package/template/.trae/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
  298. package/template/.trae/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
  299. package/template/.trae/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
  300. package/template/.trae/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
  301. package/template/.trae/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
  302. package/template/.trae/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
  303. package/template/.trae/skills/yss-tactical-design/SKILL.md +33 -0
  304. package/template/.trae/skills/yss-tactical-design/agents/openai.yaml +4 -0
  305. package/template/.trae/skills/yss-tactical-design/references/output-template.md +28 -0
  306. package/template/.trae/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
  307. package/template/.trae/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
  308. package/template/.trae/skills/yss-tactical-design/references/validation-rules.md +13 -0
  309. package/template/.trae/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
  310. package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
  311. package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
  312. package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
  313. package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
  314. package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
  315. package/template/.trae/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
  316. package/template/.trae/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
  317. package/template/AGENTS.md +22 -5
  318. package/template/CONTEXT.md +1 -1
  319. package/template/docs/agents/README.md +1 -1
  320. package/template/docs/agents/digital-human-roles.md +2 -2
  321. package/template/docs/agents/digital-human-roles.yaml +7 -1
  322. package/template/docs/agents/yss-skill-registry.yaml +12 -0
  323. package/template/docs/architecture/templates/system-overview-design-template.md +1 -0
  324. package/template/docs/process/lifecycle-artifact-map.md +8 -0
  325. package/template/docs/process/lifecycle-registry-baseline.json +11 -1
  326. package/template/docs/process/lifecycle-registry.yaml +46 -2
  327. package/template/docs/process/schemas/digital-human-task-package.schema.json +107 -0
  328. package/template/docs/process/schemas/subagent-task-package.schema.json +6 -0
  329. package/template/docs/process/subagent-collaboration.md +2 -2
  330. package/template/docs/templates/subagent-task-package-template.md +39 -1
  331. package/template/scripts/lib/lifecycle-transition.mjs +259 -0
  332. package/template/scripts/lib/scenario-checks.mjs +96 -2
  333. package/template/scripts/lib/task-package.mjs +214 -0
  334. package/template/scripts/verify-digital-human-task-package +14 -0
  335. package/template/scripts/verify-digital-human-task-package-scenarios +8 -0
  336. package/template/scripts/verify-lifecycle-transition-scenarios +105 -0
  337. package/template/scripts/verify-subagent-task-package +8 -0
  338. package/template/scripts/verify-subagent-task-package-scenarios +196 -0
  339. package/template/scripts/verify-template +13 -2
  340. package/template/skills-lock.json +36 -4
  341. package/template.snapshot.json +4 -4
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from "node:fs/promises";
3
+ import process from "node:process";
4
+ import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
5
+ import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecordFile } from "../../../../scripts/lib/approval-record.mjs";
6
+
7
+ const required = ["schema_version", "domain_strategy_id", "domain_version", "status", "contexts", "subdomains", "relationships", "scenarios", "concept_candidates", "invariants", "terminology_refs", "downstream_mapping", "evidence_refs", "approval"];
8
+ const idPatterns = {
9
+ context_id: /^[A-Z][A-Za-z0-9]+$/,
10
+ domain_strategy_id: /^domain-strategy\.[a-z0-9][a-z0-9-]*$/,
11
+ subdomain_id: /^subdomain\.[a-z0-9][a-z0-9-]*$/,
12
+ relationship_id: /^relationship\.[a-z0-9][a-z0-9-]*$/,
13
+ scenario_id: /^scenario\.[a-z0-9][a-z0-9-]*$/,
14
+ concept_id: /^domain-concept\.[a-z0-9][a-z0-9-]*$/,
15
+ invariant_id: /^invariant\.[a-z0-9][a-z0-9-]*$/
16
+ };
17
+ const relationshipPatterns = new Set(["Partnership", "Customer/Supplier", "Conformist", "Anti-Corruption Layer", "Open Host Service", "Published Language", "Shared Kernel", "Separate Ways"]);
18
+
19
+ function fail(errors) {
20
+ process.stderr.write(`${JSON.stringify({ result: "blocked", errors }, null, 2)}\n`);
21
+ process.exitCode = 1;
22
+ }
23
+
24
+ function nonEmpty(value) { return typeof value === "string" && value.trim().length > 0; }
25
+ function list(value) { return Array.isArray(value); }
26
+ function unique(items, label, errors) {
27
+ const seen = new Set();
28
+ for (const item of items) {
29
+ if (seen.has(item)) errors.push(`${label} 重复: ${item}`);
30
+ seen.add(item);
31
+ }
32
+ }
33
+ function requireField(object, field, path, errors) {
34
+ if (!(field in object) || object[field] === null || object[field] === undefined) errors.push(`${path}.${field} 缺失`);
35
+ }
36
+ function requireString(object, field, path, errors) {
37
+ requireField(object, field, path, errors);
38
+ if (field in object && !nonEmpty(object[field])) errors.push(`${path}.${field} 必须是非空字符串`);
39
+ }
40
+ function requireArray(object, field, path, errors, min = 0, itemKind = "string") {
41
+ requireField(object, field, path, errors);
42
+ if (field in object && (!list(object[field]) || object[field].length < min)) errors.push(`${path}.${field} 必须是至少 ${min} 项的数组`);
43
+ if (field in object && list(object[field]) && itemKind === "string") object[field].forEach((item, index) => { if (!nonEmpty(item)) errors.push(`${path}.${field}[${index}] 必须是非空字符串`); });
44
+ }
45
+
46
+ function validate(data) {
47
+ const errors = [];
48
+ if (!data || typeof data !== "object" || Array.isArray(data)) return ["合同必须是对象"];
49
+ for (const field of required) requireField(data, field, "root", errors);
50
+ if (data.schema_version !== 1) errors.push("schema_version 必须为 1");
51
+ if (!idPatterns.domain_strategy_id.test(String(data.domain_strategy_id ?? ""))) errors.push("domain_strategy_id 格式非法");
52
+ if (!/^v[0-9]+$/.test(String(data.domain_version ?? ""))) errors.push("domain_version 必须形如 v1");
53
+ if (!["draft", "ready-for-human", "approved", "stale", "blocked"].includes(data.status)) errors.push("status 非法");
54
+
55
+ requireArray(data, "contexts", "root", errors, 1, "object");
56
+ const contexts = list(data.contexts) ? data.contexts : [];
57
+ const contextIds = contexts.map((item) => item?.context_id).filter(Boolean);
58
+ unique(contextIds, "context_id", errors);
59
+ for (const [index, context] of contexts.entries()) {
60
+ const path = `contexts[${index}]`;
61
+ for (const field of ["context_id", "name", "owner", "status", "subdomain_type"]) requireString(context ?? {}, field, path, errors);
62
+ for (const field of ["responsibilities", "non_responsibilities"]) requireArray(context ?? {}, field, path, errors, field === "responsibilities" ? 1 : 0);
63
+ if (context?.context_id && !idPatterns.context_id.test(context.context_id)) errors.push(`${path}.context_id 格式非法`);
64
+ if (context?.status && !["candidate", "confirmed", "stale"].includes(context.status)) errors.push(`${path}.status 非法`);
65
+ if (context?.subdomain_type && !["Core Domain", "Supporting Subdomain", "Generic Subdomain"].includes(context.subdomain_type)) errors.push(`${path}.subdomain_type 非法`);
66
+ }
67
+
68
+ requireArray(data, "subdomains", "root", errors, 1, "object");
69
+ const subdomains = list(data.subdomains) ? data.subdomains : [];
70
+ unique(subdomains.map((item) => item?.subdomain_id).filter(Boolean), "subdomain_id", errors);
71
+ for (const [index, item] of subdomains.entries()) {
72
+ const path = `subdomains[${index}]`;
73
+ for (const field of ["subdomain_id", "name", "type", "rationale"]) requireString(item ?? {}, field, path, errors);
74
+ requireArray(item ?? {}, "evidence_refs", path, errors, 1);
75
+ if (item?.subdomain_id && !idPatterns.subdomain_id.test(item.subdomain_id)) errors.push(`${path}.subdomain_id 格式非法`);
76
+ if (item?.type && !["Core Domain", "Supporting Subdomain", "Generic Subdomain"].includes(item.type)) errors.push(`${path}.type 非法`);
77
+ }
78
+
79
+ const relationships = list(data.relationships) ? data.relationships : [];
80
+ unique(relationships.map((item) => item?.relationship_id).filter(Boolean), "relationship_id", errors);
81
+ for (const [index, relationship] of relationships.entries()) {
82
+ const path = `relationships[${index}]`;
83
+ for (const field of ["relationship_id", "from_context", "to_context", "relationship_pattern", "semantic_upstream", "semantic_downstream", "business_authority", "model_change_impact", "transport_direction", "translation_responsibility", "direction_explanation"]) requireString(relationship ?? {}, field, path, errors);
84
+ if (relationship?.relationship_id && !idPatterns.relationship_id.test(relationship.relationship_id)) errors.push(`${path}.relationship_id 格式非法`);
85
+ for (const field of ["from_context", "to_context", "semantic_upstream", "semantic_downstream"]) {
86
+ if (relationship?.[field] && !contextIds.includes(relationship[field])) errors.push(`${path}.${field} 未引用已声明上下文`);
87
+ }
88
+ if (relationship?.from_context === relationship?.to_context) errors.push(`${path} 不允许上下文自环`);
89
+ if (relationship?.semantic_upstream && ![relationship.from_context, relationship.to_context].includes(relationship.semantic_upstream)) errors.push(`${path}.semantic_upstream 必须是关系端点`);
90
+ if (relationship?.semantic_downstream && ![relationship.from_context, relationship.to_context].includes(relationship.semantic_downstream)) errors.push(`${path}.semantic_downstream 必须是关系端点`);
91
+ if (relationship?.relationship_pattern && !relationshipPatterns.has(relationship.relationship_pattern)) errors.push(`${path}.relationship_pattern 非法`);
92
+ if (relationship?.relationship_pattern === "Shared Kernel" && !nonEmpty(relationship.shared_kernel_approval_ref)) errors.push(`${path} Shared Kernel 必须有 shared_kernel_approval_ref`);
93
+ if (relationship?.semantic_upstream && relationship?.semantic_downstream && relationship.semantic_upstream === relationship.semantic_downstream) errors.push(`${path} semantic_upstream 与 semantic_downstream 不能相同`);
94
+ }
95
+
96
+ requireArray(data, "scenarios", "root", errors, 1, "object");
97
+ const scenarios = list(data.scenarios) ? data.scenarios : [];
98
+ const scenarioIds = scenarios.map((item) => item?.scenario_id).filter(Boolean);
99
+ unique(scenarioIds, "scenario_id", errors);
100
+ for (const [index, scenario] of scenarios.entries()) {
101
+ const path = `scenarios[${index}]`;
102
+ for (const field of ["scenario_id", "actor", "responsible_context", "status"]) requireString(scenario ?? {}, field, path, errors);
103
+ for (const field of ["preconditions", "commands", "rules", "events", "failure_results", "consumers"]) requireArray(scenario ?? {}, field, path, errors, field === "commands" || field === "rules" || field === "failure_results" ? 1 : 0);
104
+ if (scenario?.scenario_id && !idPatterns.scenario_id.test(scenario.scenario_id)) errors.push(`${path}.scenario_id 格式非法`);
105
+ if (scenario?.responsible_context && !contextIds.includes(scenario.responsible_context)) errors.push(`${path}.responsible_context 未声明`);
106
+ for (const consumer of scenario?.consumers ?? []) if (!contextIds.includes(consumer)) errors.push(`${path}.consumers 引用了未声明上下文: ${consumer}`);
107
+ }
108
+
109
+ const concepts = list(data.concept_candidates) ? data.concept_candidates : [];
110
+ unique(concepts.map((item) => item?.concept_id).filter(Boolean), "concept_id", errors);
111
+ for (const [index, concept] of concepts.entries()) {
112
+ const path = `concept_candidates[${index}]`;
113
+ for (const field of ["concept_id", "name", "context_id", "confidence", "status"]) requireString(concept ?? {}, field, path, errors);
114
+ for (const field of ["identity_features", "lifecycle"]) requireArray(concept ?? {}, field, path, errors, 1);
115
+ if (concept?.concept_id && !idPatterns.concept_id.test(concept.concept_id)) errors.push(`${path}.concept_id 格式非法`);
116
+ if (concept?.context_id && !contextIds.includes(concept.context_id)) errors.push(`${path}.context_id 未声明`);
117
+ if (concept?.confidence && !["low", "medium", "high"].includes(concept.confidence)) errors.push(`${path}.confidence 非法`);
118
+ }
119
+
120
+ const invariants = list(data.invariants) ? data.invariants : [];
121
+ unique(invariants.map((item) => item?.invariant_id).filter(Boolean), "invariant_id", errors);
122
+ for (const [index, invariant] of invariants.entries()) {
123
+ const path = `invariants[${index}]`;
124
+ for (const field of ["invariant_id", "statement", "responsible_context", "verification_method"]) requireString(invariant ?? {}, field, path, errors);
125
+ requireArray(invariant ?? {}, "scenario_refs", path, errors, 1);
126
+ if (invariant?.invariant_id && !idPatterns.invariant_id.test(invariant.invariant_id)) errors.push(`${path}.invariant_id 格式非法`);
127
+ if (invariant?.responsible_context && !contextIds.includes(invariant.responsible_context)) errors.push(`${path}.responsible_context 未声明`);
128
+ for (const reference of invariant?.scenario_refs ?? []) if (!scenarioIds.includes(reference)) errors.push(`${path}.scenario_refs 引用了未声明场景: ${reference}`);
129
+ }
130
+
131
+ requireArray(data, "terminology_refs", "root", errors, 0);
132
+ requireArray(data, "evidence_refs", "root", errors, 1);
133
+ const mappings = list(data.downstream_mapping) ? data.downstream_mapping : [];
134
+ for (const [index, mapping] of mappings.entries()) {
135
+ const path = `downstream_mapping[${index}]`;
136
+ for (const field of ["domain_change", "propagation", "reapproval_condition"]) requireString(mapping ?? {}, field, path, errors);
137
+ requireArray(mapping ?? {}, "impacts", path, errors, 1);
138
+ if (mapping?.propagation && !["direct", "transitive", "stale"].includes(mapping.propagation)) errors.push(`${path}.propagation 非法`);
139
+ }
140
+ const approval = data.approval ?? {};
141
+ for (const field of ["approval_ref", "approver", "persisted_ref", "current_version"]) requireString(approval, field, "approval", errors);
142
+ if (data.status === "approved") {
143
+ if (contexts.some((context) => context.status !== "confirmed")) errors.push("approved 合同要求所有上下文 status=confirmed");
144
+ if (approval.current_version !== data.domain_version) errors.push("approval.current_version 必须等于 domain_version");
145
+ try {
146
+ const approvalPath = resolveApprovalRef(approval.approval_ref);
147
+ validateApprovalRecordFile(approvalPath, { requireApproved: true });
148
+ const record = loadApprovalRecord(approvalPath);
149
+ if (record.gate_id !== "gate.domain-strategy-approved") errors.push("approval.approval_ref 的 gate_id 必须为 gate.domain-strategy-approved");
150
+ if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
151
+ } catch (error) { errors.push(`approval.approval_ref 会签记录无效: ${error.message}`); }
152
+ }
153
+ return errors;
154
+ }
155
+
156
+ const file = process.argv[2];
157
+ if (!file) fail(["用法: validate-domain-strategy.mjs <contract.yaml>"]);
158
+ else {
159
+ try {
160
+ const source = await readFile(file, "utf8");
161
+ const document = parseDocument(source, { maxAliasCount: 0, uniqueKeys: true });
162
+ if (document.errors.length) fail([document.errors[0].message]);
163
+ else {
164
+ const errors = validate(document.toJS({ maxAliasCount: 0 }));
165
+ if (errors.length) fail(errors);
166
+ else process.stdout.write(JSON.stringify({ result: "completed", contract: file }, null, 2) + "\n");
167
+ }
168
+ } catch (error) { fail([error.message]); }
169
+ }
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from "node:fs/promises";
3
+ import { createHash } from "node:crypto";
4
+ import { resolve } from "node:path";
5
+ import process from "node:process";
6
+ import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
7
+ import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecordFile } from "../../../../scripts/lib/approval-record.mjs";
8
+
9
+ const required = ["schema_version", "stage_decision_id", "package_version", "status", "problem_statement", "target_users", "mvp", "non_goals", "success_criteria", "test_seams", "confirmed_decisions", "assumptions", "constraints", "unresolved_items", "terminology_refs", "domain_strategy_ref", "impact_assessment", "downstream_mapping", "evidence_refs", "approval"];
10
+ const idPattern = /^stage-decision\.[a-z0-9][a-z0-9-]*$/;
11
+
12
+ function fail(errors) {
13
+ process.stderr.write(`${JSON.stringify({ result: "blocked", errors }, null, 2)}\n`);
14
+ process.exitCode = 1;
15
+ }
16
+ function nonEmpty(value) { return typeof value === "string" && value.trim().length > 0; }
17
+ function requireField(object, field, path, errors) { if (!(field in object) || object[field] === null || object[field] === undefined) errors.push(`${path}.${field} 缺失`); }
18
+ function requireString(object, field, path, errors) { requireField(object, field, path, errors); if (field in object && !nonEmpty(object[field])) errors.push(`${path}.${field} 必须是非空字符串`); }
19
+ function requireArray(object, field, path, errors, min = 0) { requireField(object, field, path, errors); if (field in object && (!Array.isArray(object[field]) || object[field].length < min)) errors.push(`${path}.${field} 必须是至少 ${min} 项的数组`); if (field in object && Array.isArray(object[field])) object[field].forEach((item, index) => { if (!nonEmpty(item)) errors.push(`${path}.${field}[${index}] 必须是非空字符串`); }); }
20
+ function canonical(value) { if (Array.isArray(value)) return value.map(canonical); if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonical(value[key])])); return value; }
21
+ function digest(value) { return `sha256:${createHash("sha256").update(JSON.stringify(canonical(value))).digest("hex")}`; }
22
+
23
+ async function validate(data) {
24
+ const errors = [];
25
+ if (!data || typeof data !== "object" || Array.isArray(data)) return ["合同必须是对象"];
26
+ for (const field of required) requireField(data, field, "root", errors);
27
+ if (data.schema_version !== 1) errors.push("schema_version 必须为 1");
28
+ if (!idPattern.test(String(data.stage_decision_id ?? ""))) errors.push("stage_decision_id 格式非法");
29
+ if (!/^v[0-9]+$/.test(String(data.package_version ?? ""))) errors.push("package_version 必须形如 v1");
30
+ if (!["draft", "ready-for-human", "approved", "stale", "blocked"].includes(data.status)) errors.push("status 非法");
31
+ for (const field of ["problem_statement"]) requireString(data, field, "root", errors);
32
+ for (const field of ["target_users", "mvp", "non_goals", "success_criteria", "test_seams", "confirmed_decisions", "assumptions", "constraints", "terminology_refs", "evidence_refs"]) requireArray(data, field, "root", errors, ["target_users", "mvp", "success_criteria", "test_seams", "confirmed_decisions", "evidence_refs"].includes(field) ? 1 : 0);
33
+
34
+ const unresolved = Array.isArray(data.unresolved_items) ? data.unresolved_items : [];
35
+ for (const [index, item] of unresolved.entries()) {
36
+ const path = `unresolved_items[${index}]`;
37
+ for (const field of ["item", "type", "owner", "next_action", "target_version"]) requireString(item ?? {}, field, path, errors);
38
+ if (item?.type && !["blocker", "deferred"].includes(item.type)) errors.push(`${path}.type 非法`);
39
+ }
40
+ const domainRef = data.domain_strategy_ref ?? {};
41
+ for (const field of ["domain_strategy_id", "domain_version", "digest", "status", "persisted_ref"]) requireString(domainRef, field, "domain_strategy_ref", errors);
42
+ if (domainRef.status && !["approved", "stale", "blocked"].includes(domainRef.status)) errors.push("domain_strategy_ref.status 非法");
43
+ if (data.status === "approved" && domainRef.status !== "approved") errors.push("approved 阶段包必须引用 approved 的 domain strategy");
44
+ if (nonEmpty(domainRef.persisted_ref)) {
45
+ try {
46
+ const strategySource = await readFile(resolve(process.cwd(), domainRef.persisted_ref), "utf8");
47
+ const strategyDocument = parseDocument(strategySource, { maxAliasCount: 0, uniqueKeys: true });
48
+ if (strategyDocument.errors.length) errors.push(`domain_strategy_ref.persisted_ref YAML 非法: ${strategyDocument.errors[0].message}`);
49
+ else {
50
+ const strategy = strategyDocument.toJS({ maxAliasCount: 0 });
51
+ if (strategy.domain_strategy_id !== domainRef.domain_strategy_id) errors.push("domain_strategy_ref.domain_strategy_id 与实际文件不一致");
52
+ if (strategy.domain_version !== domainRef.domain_version) errors.push("domain_strategy_ref.domain_version 与实际文件不一致");
53
+ if (strategy.status !== domainRef.status) errors.push("domain_strategy_ref.status 与实际文件不一致");
54
+ if (domainRef.digest !== digest(strategy)) errors.push("domain_strategy_ref.digest 与实际领域战略内容不一致");
55
+ }
56
+ } catch (error) { errors.push(`domain_strategy_ref.persisted_ref 无法读取: ${error.message}`); }
57
+ }
58
+
59
+ const impact = data.impact_assessment ?? {};
60
+ for (const field of ["ui", "api", "data", "backend", "frontend", "cross_repo", "high_risk"]) {
61
+ requireField(impact, field, "impact_assessment", errors);
62
+ if (field in impact && typeof impact[field] !== "boolean") errors.push(`impact_assessment.${field} 必须是 boolean`);
63
+ }
64
+ const mappings = Array.isArray(data.downstream_mapping) ? data.downstream_mapping : [];
65
+ if (mappings.length < 1) errors.push("downstream_mapping 至少需要一项");
66
+ for (const [index, mapping] of mappings.entries()) {
67
+ const path = `downstream_mapping[${index}]`;
68
+ for (const field of ["domain_change", "consumer", "propagation", "reapproval_condition"]) requireString(mapping ?? {}, field, path, errors);
69
+ if (mapping?.propagation && !["direct", "transitive", "not-applicable", "stale"].includes(mapping.propagation)) errors.push(`${path}.propagation 非法`);
70
+ }
71
+ const approval = data.approval ?? {};
72
+ for (const field of ["approval_ref", "approver", "persisted_ref", "current_version"]) requireString(approval, field, "approval", errors);
73
+ if (data.status === "approved" && approval.current_version !== data.package_version) errors.push("approval.current_version 必须等于 package_version");
74
+ if (unresolved.some((item) => item?.type === "blocker") && data.status === "approved") errors.push("存在 blocker 未决项时不得 approved");
75
+ if (data.status === "approved" && nonEmpty(approval.approval_ref)) {
76
+ try {
77
+ const approvalPath = resolveApprovalRef(approval.approval_ref);
78
+ validateApprovalRecordFile(approvalPath, { requireApproved: true });
79
+ const record = loadApprovalRecord(approvalPath);
80
+ if (record.gate_id !== "gate.stage-decision-package-approved") errors.push("approval_ref 的 gate_id 必须为 gate.stage-decision-package-approved");
81
+ if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
82
+ } catch (error) { errors.push(`approval_ref 会签记录无效: ${error.message}`); }
83
+ }
84
+ return errors;
85
+ }
86
+
87
+ const file = process.argv[2];
88
+ if (!file) fail(["用法: validate-stage-decision-package.mjs <package.yaml>"]);
89
+ else {
90
+ try {
91
+ const source = await readFile(file, "utf8");
92
+ const document = parseDocument(source, { maxAliasCount: 0, uniqueKeys: true });
93
+ if (document.errors.length) fail([document.errors[0].message]);
94
+ else {
95
+ const errors = await validate(document.toJS({ maxAliasCount: 0 }));
96
+ if (errors.length) fail(errors);
97
+ else process.stdout.write(JSON.stringify({ result: "completed", contract: file }, null, 2) + "\n");
98
+ }
99
+ } catch (error) { fail([error.message]); }
100
+ }
@@ -0,0 +1,15 @@
1
+ schema_version: 1
2
+ gate_id: gate.domain-strategy-approved
3
+ decision: approved
4
+ actor_kind: digital-human
5
+ role_id: role.product-manager
6
+ runtime_id: runtime.generic
7
+ runtime_instance_ref: "runtime.generic:role.product-manager"
8
+ principal_ref: "instance:role.product-manager"
9
+ drafter_role_id: role.requirements-manager
10
+ countersigner_role_ids:
11
+ - role.product-manager
12
+ evidence_refs:
13
+ - evidence.domain-strategy-review.supplier
14
+ biological_veto: false
15
+ notes: DDD 战略设计由需求经理起草,产品经理独立会签。
@@ -0,0 +1,58 @@
1
+ schema_version: 1
2
+ domain_strategy_id: domain-strategy.invalid-direction
3
+ domain_version: v1
4
+ status: ready-for-human
5
+ contexts:
6
+ - context_id: A
7
+ name: A
8
+ responsibilities: [rule]
9
+ non_responsibilities: []
10
+ subdomain_type: Supporting Subdomain
11
+ owner: owner
12
+ status: confirmed
13
+ - context_id: B
14
+ name: B
15
+ responsibilities: [consume]
16
+ non_responsibilities: []
17
+ subdomain_type: Supporting Subdomain
18
+ owner: owner
19
+ status: confirmed
20
+ subdomains:
21
+ - subdomain_id: subdomain.a
22
+ name: A
23
+ type: Supporting Subdomain
24
+ rationale: test
25
+ evidence_refs: [e]
26
+ relationships:
27
+ - relationship_id: relationship.a-b
28
+ from_context: A
29
+ to_context: B
30
+ relationship_pattern: Published Language
31
+ semantic_upstream: A
32
+ semantic_downstream: B
33
+ business_authority: A
34
+ model_change_impact: B adapts
35
+ transport_direction: B calls A
36
+ translation_responsibility: B
37
+ direction_explanation: ""
38
+ scenarios:
39
+ - scenario_id: scenario.test
40
+ actor: actor
41
+ preconditions: []
42
+ commands: [command]
43
+ rules: [rule]
44
+ events: []
45
+ failure_results: [failure]
46
+ responsible_context: A
47
+ consumers: [B]
48
+ status: confirmed
49
+ concept_candidates: []
50
+ invariants: []
51
+ terminology_refs: [t]
52
+ downstream_mapping: []
53
+ evidence_refs: [e]
54
+ approval:
55
+ approval_ref: a
56
+ approver: a
57
+ persisted_ref: p
58
+ current_version: v1
@@ -0,0 +1,44 @@
1
+ schema_version: 1
2
+ stage_decision_id: stage-decision.invalid-blocker
3
+ package_version: v1
4
+ status: approved
5
+ problem_statement: 示例
6
+ target_users: [用户]
7
+ mvp: [功能]
8
+ non_goals: []
9
+ success_criteria: [标准]
10
+ test_seams: [seam]
11
+ confirmed_decisions: [决定]
12
+ assumptions: []
13
+ constraints: []
14
+ unresolved_items:
15
+ - item: 规则所有权未确认
16
+ type: blocker
17
+ owner: role.product-manager
18
+ next_action: 召开领域评审
19
+ target_version: 2026-Q4
20
+ terminology_refs: [CONTEXT.md#Example]
21
+ domain_strategy_ref:
22
+ domain_strategy_id: domain-strategy.invalid
23
+ domain_version: v1
24
+ digest: sha256:invalid
25
+ status: approved
26
+ impact_assessment:
27
+ ui: false
28
+ api: false
29
+ data: false
30
+ backend: true
31
+ frontend: false
32
+ cross_repo: false
33
+ high_risk: false
34
+ downstream_mapping:
35
+ - domain_change: example
36
+ consumer: spec-synthesis
37
+ propagation: direct
38
+ reapproval_condition: 规则确认
39
+ evidence_refs: [evidence.invalid]
40
+ approval:
41
+ approval_ref: docs/.scratch/invalid/gate.yaml
42
+ approver: role.lifecycle-orchestrator
43
+ persisted_ref: docs/.scratch/invalid/package.yaml
44
+ current_version: v1
@@ -0,0 +1,15 @@
1
+ schema_version: 1
2
+ gate_id: gate.stage-decision-package-approved
3
+ decision: approved
4
+ actor_kind: digital-human
5
+ role_id: role.product-manager
6
+ runtime_id: runtime.generic
7
+ runtime_instance_ref: "runtime.generic:role.product-manager"
8
+ principal_ref: "instance:role.product-manager"
9
+ drafter_role_id: role.requirements-manager
10
+ countersigner_role_ids:
11
+ - role.product-manager
12
+ evidence_refs:
13
+ - evidence.stage-decision-package.supplier
14
+ biological_veto: false
15
+ notes: 阶段决策包由需求经理起草,产品经理独立会签。
@@ -0,0 +1,49 @@
1
+ schema_version: 1
2
+ stage_decision_id: stage-decision.supplier-admission
3
+ package_version: v1
4
+ status: approved
5
+ problem_statement: 合规准入决定分散,采购无法稳定判断当前有效资格。
6
+ target_users: [采购专员、合规专员]
7
+ mvp: [提交供应商申请、合规准入决定、采购侧有效性校验]
8
+ non_goals: [供应商结算、采购付款、通用工作流平台]
9
+ success_criteria: [新采购订单 100% 校验当前有效准入决定]
10
+ test_seams: [supplier-application-submit, admission-validity-check]
11
+ confirmed_decisions: [ComplianceReview 拥有准入规则语义,ProcurementExecution 只消费决定]
12
+ assumptions: [供应商已有唯一 subject_ref]
13
+ constraints: [保留现有采购订单流程]
14
+ unresolved_items:
15
+ - item: 供应商历史资料迁移范围
16
+ type: deferred
17
+ owner: role.product-manager
18
+ next_action: 在 Spec synthesis 前完成数据盘点
19
+ target_version: 2026-Q4
20
+ terminology_refs: [CONTEXT.md#SupplierAdmission]
21
+ domain_strategy_ref:
22
+ domain_strategy_id: domain-strategy.supplier-admission
23
+ domain_version: v1
24
+ digest: sha256:a1a4df23fdb59ab8b4433cedba8271c8a7f11bc8a38abe675d3c7b645d51d7a1
25
+ status: approved
26
+ persisted_ref: .agents/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml
27
+ impact_assessment:
28
+ ui: true
29
+ api: true
30
+ data: true
31
+ backend: true
32
+ frontend: true
33
+ cross_repo: false
34
+ high_risk: false
35
+ downstream_mapping:
36
+ - domain_change: admission-decision-validity
37
+ consumer: spec-synthesis
38
+ propagation: direct
39
+ reapproval_condition: 领域策略版本或有效性规则变化
40
+ - domain_change: admission-decision-validity
41
+ consumer: ticket-decomposition
42
+ propagation: transitive
43
+ reapproval_condition: Spec 基线变更
44
+ evidence_refs: [evidence.discovery.supplier, evidence.domain-strategy-review.supplier]
45
+ approval:
46
+ approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml
47
+ approver: role.product-manager
48
+ persisted_ref: docs/.scratch/supplier/stage-decision/stage-decision-package-v1.yaml
49
+ current_version: v1
@@ -0,0 +1,108 @@
1
+ schema_version: 1
2
+ domain_strategy_id: domain-strategy.supplier-admission
3
+ domain_version: v1
4
+ status: approved
5
+ contexts:
6
+ - context_id: SupplierManagement
7
+ name: 供应商管理
8
+ responsibilities: [供应商申请、资料生命周期]
9
+ non_responsibilities: [合规决定、采购订单]
10
+ subdomain_type: Supporting Subdomain
11
+ owner: requirements-manager
12
+ status: confirmed
13
+ - context_id: ComplianceReview
14
+ name: 合规审查
15
+ responsibilities: [资质审查、准入决定、有效期]
16
+ non_responsibilities: [供应商主档、采购订单]
17
+ subdomain_type: Core Domain
18
+ owner: product-manager
19
+ status: confirmed
20
+ - context_id: ProcurementExecution
21
+ name: 采购执行
22
+ responsibilities: [采购选择、采购订单履行]
23
+ non_responsibilities: [合规规则、供应商申请]
24
+ subdomain_type: Supporting Subdomain
25
+ owner: project-manager
26
+ status: confirmed
27
+ subdomains:
28
+ - subdomain_id: subdomain.supplier-management
29
+ name: Supplier Management
30
+ type: Supporting Subdomain
31
+ rationale: 管理申请与资料生命周期,不承载差异化合规决策。
32
+ evidence_refs: [evidence.discovery.supplier]
33
+ - subdomain_id: subdomain.compliance-review
34
+ name: Compliance Review
35
+ type: Core Domain
36
+ rationale: 核心价值候选是企业自有的合规判断和风险规则。
37
+ evidence_refs: [evidence.discovery.compliance]
38
+ relationships:
39
+ - relationship_id: relationship.supplier-to-compliance
40
+ from_context: SupplierManagement
41
+ to_context: ComplianceReview
42
+ relationship_pattern: Customer/Supplier
43
+ semantic_upstream: SupplierManagement
44
+ semantic_downstream: ComplianceReview
45
+ business_authority: SupplierManagement owns applicant facts
46
+ model_change_impact: applicant schema changes require review adaptation
47
+ transport_direction: SubmitSupplierForComplianceReview command
48
+ translation_responsibility: ComplianceReview ACL
49
+ direction_explanation: 申请资料由 SupplierManagement 拥有,但技术请求方向不代表合规规则所有权。
50
+ - relationship_id: relationship.compliance-to-procurement
51
+ from_context: ComplianceReview
52
+ to_context: ProcurementExecution
53
+ relationship_pattern: Published Language
54
+ semantic_upstream: ComplianceReview
55
+ semantic_downstream: ProcurementExecution
56
+ business_authority: ComplianceReview owns admission validity
57
+ model_change_impact: decision validity changes invalidate procurement acceptance
58
+ transport_direction: admission decision events
59
+ translation_responsibility: ProcurementExecution local projection
60
+ direction_explanation: 合规决定是语义上游;采购侧可通过事件接收并在下单时实时校验。
61
+ scenarios:
62
+ - scenario_id: scenario.supplier-submits
63
+ actor: supplier
64
+ preconditions: [供应商资料可编辑]
65
+ commands: [SubmitSupplierApplication]
66
+ rules: [申请材料必须完整]
67
+ events: [SupplierApplicationSubmitted]
68
+ failure_results: [材料不完整时拒绝提交]
69
+ responsible_context: SupplierManagement
70
+ consumers: [ComplianceReview]
71
+ status: confirmed
72
+ - scenario_id: scenario.admission-expires
73
+ actor: compliance-officer
74
+ preconditions: [批准决定存在]
75
+ commands: [EvaluateAdmissionValidity]
76
+ rules: [过期决定不得支持新采购订单]
77
+ events: [SupplierAdmissionExpired]
78
+ failure_results: [采购下单时资格校验失败]
79
+ responsible_context: ComplianceReview
80
+ consumers: [SupplierManagement, ProcurementExecution]
81
+ status: confirmed
82
+ concept_candidates:
83
+ - concept_id: domain-concept.admission-decision
84
+ name: AdmissionDecision
85
+ context_id: ComplianceReview
86
+ identity_features: [decision_id、subject_ref、rule_version]
87
+ lifecycle: [proposed、approved、rejected、expired、revoked]
88
+ possible_tactical_role: Entity candidate
89
+ confidence: high
90
+ status: confirmed
91
+ invariants:
92
+ - invariant_id: invariant.current-admission-required
93
+ statement: 新采购订单必须引用当前有效的准入决定。
94
+ responsible_context: ComplianceReview
95
+ scenario_refs: [scenario.admission-expires]
96
+ verification_method: 领域场景测试和事件版本校验
97
+ terminology_refs: [contexts/SupplierManagement/CONTEXT.md, contexts/ComplianceReview/CONTEXT.md]
98
+ downstream_mapping:
99
+ - domain_change: admission-decision-validity
100
+ impacts: [spec, openapi, procurement-acceptance-tests]
101
+ propagation: stale
102
+ reapproval_condition: ComplianceReview 决定和有效期重新批准
103
+ evidence_refs: [evidence.discovery.supplier, evidence.discovery.compliance]
104
+ approval:
105
+ approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml
106
+ approver: role.product-manager
107
+ persisted_ref: docs/.scratch/supplier/domain/domain-strategy-v1.yaml
108
+ current_version: v1
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { tmpdir } from "node:os";
7
+
8
+ const root = dirname(fileURLToPath(import.meta.url));
9
+ const validator = join(root, "..", "scripts", "validate-domain-strategy.mjs");
10
+ const packageValidator = join(root, "..", "scripts", "validate-stage-decision-package.mjs");
11
+ const valid = join(root, "fixtures", "valid-supplier-domain.yaml");
12
+ const invalid = join(root, "fixtures", "invalid-direction.yaml");
13
+ const validPackage = join(root, "fixtures", "valid-stage-decision-package.yaml");
14
+ const invalidPackage = join(root, "fixtures", "invalid-stage-decision-blocker.yaml");
15
+ const run = (file) => spawnSync(process.execPath, [validator, file], { encoding: "utf8" });
16
+ const pass = run(valid);
17
+ if (pass.status !== 0) throw new Error(`valid fixture should pass: ${pass.stderr}`);
18
+ const fail = run(invalid);
19
+ if (fail.status === 0 || !fail.stderr.includes("direction_explanation")) throw new Error("invalid direction fixture should be blocked");
20
+ const packagePass = spawnSync(process.execPath, [packageValidator, validPackage], { encoding: "utf8" });
21
+ if (packagePass.status !== 0) throw new Error(`valid stage decision package should pass: ${packagePass.stderr}`);
22
+ const packageFail = spawnSync(process.execPath, [packageValidator, invalidPackage], { encoding: "utf8" });
23
+ if (packageFail.status === 0 || !packageFail.stderr.includes("blocker")) throw new Error("blocker package should be blocked");
24
+
25
+ const temporaryRoot = await mkdtemp(join(tmpdir(), "yss-stage-decision-pressure-"));
26
+ try {
27
+ const validSource = await readFile(valid, "utf8");
28
+ const sharedKernel = join(temporaryRoot, "shared-kernel.yaml");
29
+ await writeFile(sharedKernel, validSource.replace("relationship_pattern: Customer/Supplier", "relationship_pattern: Shared Kernel"));
30
+ const sharedKernelResult = run(sharedKernel);
31
+ if (sharedKernelResult.status === 0 || !sharedKernelResult.stderr.includes("shared_kernel_approval_ref")) throw new Error("unapproved Shared Kernel should be blocked");
32
+ const unknownContext = join(temporaryRoot, "unknown-context.yaml");
33
+ await writeFile(unknownContext, validSource.replace("to_context: ComplianceReview", "to_context: UnknownContext"));
34
+ const unknownContextResult = run(unknownContext);
35
+ if (unknownContextResult.status === 0 || !unknownContextResult.stderr.includes("未引用已声明上下文")) throw new Error("unknown context should be blocked");
36
+ const wrongArrayType = join(temporaryRoot, "wrong-array-type.yaml");
37
+ await writeFile(wrongArrayType, validSource.replace("responsibilities: [供应商申请、资料生命周期]", "responsibilities: [42]"));
38
+ const wrongArrayTypeResult = run(wrongArrayType);
39
+ if (wrongArrayTypeResult.status === 0 || !wrongArrayTypeResult.stderr.includes("responsibilities[0]")) throw new Error("non-string array item should be blocked");
40
+ const missingSubdomainType = join(temporaryRoot, "missing-subdomain-type.yaml");
41
+ await writeFile(missingSubdomainType, validSource.replace(" subdomain_type: Supporting Subdomain\n", ""));
42
+ const missingSubdomainTypeResult = run(missingSubdomainType);
43
+ if (missingSubdomainTypeResult.status === 0 || !missingSubdomainTypeResult.stderr.includes("subdomain_type 缺失")) throw new Error("missing subdomain type should be blocked");
44
+ const wrongReferenceType = join(temporaryRoot, "wrong-reference-type.yaml");
45
+ await writeFile(wrongReferenceType, validSource.replace("terminology_refs: [contexts/SupplierManagement/CONTEXT.md, contexts/ComplianceReview/CONTEXT.md]", "terminology_refs: [42]"));
46
+ const wrongReferenceTypeResult = run(wrongReferenceType);
47
+ if (wrongReferenceTypeResult.status === 0 || !wrongReferenceTypeResult.stderr.includes("terminology_refs[0]")) throw new Error("non-string terminology reference should be blocked");
48
+ const emptyDomainCollections = join(temporaryRoot, "empty-domain-collections.yaml");
49
+ await writeFile(emptyDomainCollections, validSource.replace(/contexts:\n[\s\S]*?subdomains:/, "contexts: []\nsubdomains:").replace(/subdomains:\n[\s\S]*?relationships:/, "subdomains: []\nrelationships:").replace(/scenarios:\n[\s\S]*?concept_candidates:/, "scenarios: []\nconcept_candidates:"));
50
+ const emptyDomainCollectionsResult = run(emptyDomainCollections);
51
+ if (emptyDomainCollectionsResult.status === 0 || !emptyDomainCollectionsResult.stderr.includes("contexts 必须是至少 1 项的数组")) throw new Error("empty DDD collections should be blocked");
52
+ const wrongDomainApproval = join(temporaryRoot, "wrong-domain-approval.yaml");
53
+ await writeFile(wrongDomainApproval, validSource.replace("approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml", "approval_ref: docs/.scratch/does-not-exist.yaml"));
54
+ const wrongDomainApprovalResult = run(wrongDomainApproval);
55
+ if (wrongDomainApprovalResult.status === 0 || !wrongDomainApprovalResult.stderr.includes("approval.approval_ref")) throw new Error("unreadable domain approval ref should be blocked");
56
+ const packageSource = await readFile(validPackage, "utf8");
57
+ const packageWrongArrayType = join(temporaryRoot, "package-wrong-array-type.yaml");
58
+ await writeFile(packageWrongArrayType, packageSource.replace("target_users: [采购专员、合规专员]", "target_users: [42]"));
59
+ const packageWrongArrayTypeResult = spawnSync(process.execPath, [packageValidator, packageWrongArrayType], { encoding: "utf8" });
60
+ if (packageWrongArrayTypeResult.status === 0 || !packageWrongArrayTypeResult.stderr.includes("target_users[0]")) throw new Error("package non-string array item should be blocked");
61
+ const packageWrongApproval = join(temporaryRoot, "package-wrong-approval.yaml");
62
+ await writeFile(packageWrongApproval, packageSource.replace("approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml", "approval_ref: docs/.scratch/does-not-exist.yaml"));
63
+ const packageWrongApprovalResult = spawnSync(process.execPath, [packageValidator, packageWrongApproval], { encoding: "utf8" });
64
+ if (packageWrongApprovalResult.status === 0 || !packageWrongApprovalResult.stderr.includes("approval_ref")) throw new Error("unreadable approval ref should be blocked");
65
+ } finally {
66
+ await rm(temporaryRoot, { recursive: true, force: true });
67
+ }
68
+ process.stdout.write("DDD strategic design scenarios passed\n");