create-yss-spec 2.2.2 → 2.2.4

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 (356) 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 +9 -9
  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 +3 -3
  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 +8 -5
  11. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +9 -4
  12. package/template/.agents/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  50. package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +9 -4
  51. package/template/.claude/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  89. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +9 -4
  90. package/template/.codex/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  128. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +9 -4
  129. package/template/.cursor/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  167. package/template/.hermes/skills/yss-product-lifecycle/references/state-model.md +9 -4
  168. package/template/.hermes/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  206. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +9 -4
  207. package/template/.pi/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  245. package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +9 -4
  246. package/template/.qoder/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +9 -9
  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 +3 -3
  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 +8 -5
  284. package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +9 -4
  285. package/template/.trae/skills/yss-router/SKILL.md +5 -3
  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 +59 -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 +8 -4
  318. package/template/CONTEXT.md +14 -2
  319. package/template/docs/agents/digital-human-roles.md +83 -0
  320. package/template/docs/agents/digital-human-roles.yaml +259 -0
  321. package/template/docs/agents/triage-labels.md +5 -5
  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/lifecycle-checkpoint.schema.json +2 -1
  329. package/template/docs/process/schemas/subagent-task-package.schema.json +6 -0
  330. package/template/docs/process/subagent-collaboration.md +5 -3
  331. package/template/docs/process/templates/stage-checkpoint-template.md +3 -1
  332. package/template/docs/templates/approval-record-template.yaml +14 -0
  333. package/template/docs/templates/digital-human-runtime-profile-template.md +38 -0
  334. package/template/docs/templates/grok-bot-profile-template.md +24 -0
  335. package/template/docs/templates/implementation-routing-template.md +3 -3
  336. package/template/docs/templates/local-parent-ticket-template.md +8 -0
  337. package/template/docs/templates/subagent-task-package-template.md +43 -1
  338. package/template/docs/templates/vertical-slice-ticket-template.md +7 -0
  339. package/template/docs/user-guide//344/272/247/345/223/201/347/240/224/345/217/221/345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/346/234/200/344/275/263/345/256/236/350/267/265.md +2 -0
  340. package/template/scripts/lib/approval-record.mjs +123 -0
  341. package/template/scripts/lib/digital-human-roles.mjs +398 -0
  342. package/template/scripts/lib/lifecycle-transition.mjs +259 -0
  343. package/template/scripts/lib/scenario-checks.mjs +96 -2
  344. package/template/scripts/lib/task-package.mjs +214 -0
  345. package/template/scripts/verify-approval-record +13 -0
  346. package/template/scripts/verify-digital-human-roles +10 -0
  347. package/template/scripts/verify-digital-human-roles-scenarios +147 -0
  348. package/template/scripts/verify-digital-human-task-package +14 -0
  349. package/template/scripts/verify-digital-human-task-package-scenarios +8 -0
  350. package/template/scripts/verify-lifecycle-checkpoint +2 -0
  351. package/template/scripts/verify-lifecycle-transition-scenarios +105 -0
  352. package/template/scripts/verify-subagent-task-package +8 -0
  353. package/template/scripts/verify-subagent-task-package-scenarios +196 -0
  354. package/template/scripts/verify-template +16 -2
  355. package/template/skills-lock.json +35 -3
  356. package/template.snapshot.json +4 -4
@@ -3,12 +3,16 @@ import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { spawnSync } from "node:child_process";
5
5
  import { parseDocument } from "../vendor/yaml.mjs";
6
+ import { lifecycleTransitionContract, validateImplementationEntry, validateNextRoute } from "./lifecycle-transition.mjs";
6
7
 
7
8
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
8
9
  const read = (relative) => readFileSync(path.join(root, relative), "utf8");
9
10
  function ensure(condition, message) { if (!condition) throw new TypeError(message); }
10
11
  function exists(relative) { return existsSync(path.join(root, relative)); }
11
12
  function includesAll(actual, expected) { return Array.isArray(actual) && expected.every((item) => actual.includes(item)); }
13
+ function hasText(value) { return typeof value === "string" && value.trim().length > 0; }
14
+ const virtualTicketDecompositionRef = "docs/.scratch/demo/evidence/ticket-decomposition-result.yaml";
15
+ const virtualTicketDecomposition = "result_schema: workflow-execution-result-v1\nwork_unit: work-unit.ticket-decomposition\nresult: completed\nevidence_refs:\n - docs/.scratch/demo/evidence/ticket-decomposition-result.yaml\n";
12
16
 
13
17
  function validateMattContract(data) {
14
18
  const direct = data.entry_routing?.direct_matt_entry;
@@ -84,13 +88,52 @@ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
84
88
  for (const field of contract.workflow_reference.required) ensure(typeof payload.workflow_reference?.[field] === "string" && payload.workflow_reference[field].trim(), `workflow_reference.${field} 无效`);
85
89
  const workUnit = workUnitRoutes?.[payload.work_unit];
86
90
  ensure(workUnit, `未知 Workflow Execution Result work_unit: ${payload.work_unit}`);
91
+ if (payload.result === "completed") {
92
+ const routeResult = validateNextRoute(payload.work_unit, payload.next_route);
93
+ ensure(routeResult.result === "allowed", `Workflow Execution Result next_route 非法: ${routeResult.blocking_signals.join(", ")}`);
94
+ }
87
95
  const accepted = [workUnit.native, workUnit.compatibility].filter(Boolean);
88
96
  ensure(contract.workflow_reference.allowed_sources.includes(payload.workflow_reference.source) && accepted.some((route) => route.source === payload.workflow_reference.source && route.skill === payload.workflow_reference.skill && route.invocation_mode === payload.workflow_reference.invocation_mode), "Workflow Execution Result workflow_reference 与 work_unit route 不匹配");
97
+ const workUnitRequirements = contract.work_unit_requirements?.[payload.work_unit];
98
+ if (workUnitRequirements && payload.result === "completed") {
99
+ for (const field of [...(workUnitRequirements.required ?? []), ...(workUnitRequirements.completed_requires ?? [])]) {
100
+ ensure(hasText(payload[field]), `Workflow Execution Result ${payload.work_unit} 缺少 ${field}`);
101
+ }
102
+ for (const field of workUnitRequirements.boolean_required ?? []) {
103
+ ensure(typeof payload[field] === "boolean", `Workflow Execution Result ${payload.work_unit} 缺少布尔字段 ${field}`);
104
+ }
105
+ }
106
+ if (payload.work_unit === "work-unit.slice-implementation" && payload.result === "completed") {
107
+ const implementationState = {
108
+ tracker_kind: payload.tracker_kind,
109
+ predecessor_work_unit: payload.predecessor_work_unit,
110
+ ready_for_agent: payload.ready_for_agent,
111
+ ticket_decomposition_result_ref: payload.ticket_decomposition_result_ref,
112
+ vertical_slice_ticket_ref: payload.vertical_slice_ticket_ref,
113
+ vertical_slice_ticket_role: payload.vertical_slice_ticket_role,
114
+ vertical_slice_ticket_kind: payload.vertical_slice_ticket_kind,
115
+ ticket_decomposition_result: { result: payload.ticket_decomposition_result_status, evidence_refs: payload.evidence_refs },
116
+ vertical_slice_ticket: { ref: payload.vertical_slice_ticket_ref, role: payload.vertical_slice_ticket_role, kind: payload.vertical_slice_ticket_kind },
117
+ slice_contract: {
118
+ ticket_ref: payload.slice_contract_ticket_ref,
119
+ status: payload.slice_contract_status,
120
+ persisted: payload.slice_contract_persisted,
121
+ current_version: payload.slice_contract_current_version,
122
+ },
123
+ };
124
+ const semantic = validateImplementationEntry(implementationState, {
125
+ // The scenario uses one explicit virtual fixture; arbitrary local refs
126
+ // must still pass the real readability check and cannot use a fallback.
127
+ exists: (ref) => exists(ref) || ref === "docs/.scratch/demo/issues/01-valid-slice.md" || ref === virtualTicketDecompositionRef,
128
+ read: (ref) => ref === virtualTicketDecompositionRef ? virtualTicketDecomposition : readFileSync(path.join(root, ref), "utf8"),
129
+ });
130
+ ensure(semantic.result === "allowed", `Workflow Execution Result implementation Ticket 语义非法: ${semantic.blocking_signals.join(", ")}`);
131
+ }
89
132
  if (payload.result !== "completed") return;
90
133
  for (const field of contract.completed_requires_empty) ensure(Array.isArray(payload[field]) && payload[field].length === 0, `completed 的 ${field} 必须为空`);
91
134
  for (const field of contract.completed_requires_non_empty) ensure(Array.isArray(payload[field]) && payload[field].length > 0, `completed 的 ${field} 不能为空`);
92
135
  if (contract.completed_requires_readable_evidence_refs) {
93
- for (const reference of payload.evidence_refs) ensure(typeof reference === "string" && reference.trim() && exists(reference), `completed 证据不可读取: ${reference}`);
136
+ for (const reference of payload.evidence_refs) ensure(typeof reference === "string" && reference.trim() && (exists(reference) || reference === virtualTicketDecompositionRef), `completed 证据不可读取: ${reference}`);
94
137
  }
95
138
  if (contract.completed_requires_no_blocking_signals) ensure(Array.isArray(payload.blocking_signals) && payload.blocking_signals.length === 0, "completed 不得携带 blocking_signals");
96
139
  }
@@ -177,6 +220,16 @@ export function runScenario(name) {
177
220
  const releaseGate = registry.gates.find((gate) => gate.id === "gate.release-ready");
178
221
  ensure(releaseGate?.requires_gates?.includes("gate.frontend-implementation-verified"), "发布就绪未依赖前端实现还原门禁");
179
222
  const contract = parseDocument(read(".agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml"), { uniqueKeys: true }).toJS({ maxAliasCount: 0 });
223
+ ensure(contract.ready_for_agent?.requires_vertical_slice_ticket === true && contract.ready_for_agent?.parent_ticket_as_implementation_ref === "forbidden", "ready_for_agent 未强制垂直切片且禁止父 Ticket 实现引用");
224
+ ensure(includesAll(contract.ready_for_agent?.required, ["ticket_decomposition_result_ref", "vertical_slice_ticket_ref", "vertical_slice_ticket_role", "vertical_slice_ticket_kind"]), "ready_for_agent 缺少 Ticket 正式化必填字段");
225
+ ensure(contract.ticket_formalization?.implementation_predecessor === "work-unit.ticket-decomposition" && contract.ticket_formalization?.vertical_slice_ticket?.parent_ticket_ref_forbidden === true, "Ticket 正式化实现前置或父 Ticket 禁止规则缺失");
226
+ ensure(contract.transition_graph?.implementation_requires_predecessor === "work-unit.ticket-decomposition", "生命周期转换图未声明实现前置工作单元");
227
+ ensure(JSON.stringify(contract.transition_graph?.forbidden_shortcuts) === JSON.stringify([
228
+ { from: "work-unit.spec-synthesis", to: "work-unit.slice-implementation" },
229
+ { from: "work-unit.prototype-design", to: "work-unit.slice-implementation" },
230
+ { from: "work-unit.technical-analysis", to: "work-unit.slice-implementation" },
231
+ ]), "生命周期转换图缺少 Spec/原型/技术分析到实现的越级阻断");
232
+ ensure(lifecycleTransitionContract.next_routes["work-unit.ticket-decomposition"]?.includes("work-unit.slice-implementation"), "转换校验器未允许 Ticket 正式化后进入实现");
180
233
  ensure(contract.release_readiness?.conditional?.ui_impact?.includes("gate.frontend-implementation-verified") && contract.frontend_implementation_plan?.acceptance?.includes("no_template_placeholders"), "发布公式或前端计划实质校验不完整");
181
234
  const templateRejected = spawnSync("scripts/verify-frontend-implementation-evidence", ["docs/process/templates/frontend-implementation-plan-template.yaml"], { cwd: root, encoding: "utf8" });
182
235
  ensure(templateRejected.status !== 0 && templateRejected.stderr.includes("template: false"), "前端实现计划占位模板可冒充正式批准证据");
@@ -200,6 +253,46 @@ export function runScenario(name) {
200
253
  blocking_signals: []
201
254
  };
202
255
  validateWorkflowExecutionResult(validResult, data.workflow_execution_result, data.work_unit_routes);
256
+ const validTicketResult = {
257
+ ...validResult,
258
+ work_unit: "work-unit.ticket-decomposition",
259
+ next_route: "work-unit.slice-implementation",
260
+ ticket_decomposition_result_ref: "docs/.scratch/demo/evidence/ticket-decomposition-result.yaml",
261
+ vertical_slice_ticket_ref: "docs/.scratch/demo/issues/01-valid-slice.md",
262
+ };
263
+ validateWorkflowExecutionResult(validTicketResult, data.workflow_execution_result, data.work_unit_routes);
264
+ const validImplementationResult = {
265
+ ...validResult,
266
+ evidence_refs: [virtualTicketDecompositionRef, "docs/process/lifecycle-registry.yaml"],
267
+ work_unit: "work-unit.slice-implementation",
268
+ next_route: "work-unit.code-review",
269
+ predecessor_work_unit: "work-unit.ticket-decomposition",
270
+ ready_for_agent: true,
271
+ ticket_decomposition_result_ref: "docs/.scratch/demo/evidence/ticket-decomposition-result.yaml",
272
+ ticket_decomposition_result_status: "completed",
273
+ vertical_slice_ticket_ref: "docs/.scratch/demo/issues/01-valid-slice.md",
274
+ vertical_slice_ticket_role: "ready-for-agent",
275
+ vertical_slice_ticket_kind: "vertical-slice-ticket",
276
+ slice_contract_ticket_ref: "docs/.scratch/demo/issues/01-valid-slice.md",
277
+ slice_contract_status: "approved",
278
+ slice_contract_persisted: true,
279
+ slice_contract_current_version: true,
280
+ };
281
+ validateWorkflowExecutionResult(validImplementationResult, data.workflow_execution_result, data.work_unit_routes);
282
+ for (const mutate of [
283
+ (item) => { item.vertical_slice_ticket_role = "ready-for-human"; },
284
+ (item) => { item.vertical_slice_ticket_kind = "parent-ticket"; },
285
+ (item) => { item.vertical_slice_ticket_ref = "docs/.scratch/demo/parent-ticket.md"; },
286
+ (item) => { item.slice_contract_ticket_ref = "docs/.scratch/demo/issues/02-other.md"; },
287
+ (item) => { item.predecessor_work_unit = "work-unit.spec-synthesis"; },
288
+ (item) => { item.ticket_decomposition_result_status = "blocked"; },
289
+ (item) => { item.ticket_decomposition_result_status = "needs-human"; },
290
+ ]) {
291
+ const invalid = structuredClone(validImplementationResult); mutate(invalid);
292
+ let rejected = false;
293
+ try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes); } catch { rejected = true; }
294
+ ensure(rejected, "实现 Workflow Execution Result 的 Ticket 语义变异未被拒绝");
295
+ }
203
296
  const unavailableResult = structuredClone(validResult);
204
297
  unavailableResult.result = "blocked";
205
298
  unavailableResult.unavailable_skill = { skill: "yss-ui", provider: "codex", fallback: "manual-review", resolution: "needs-human" };
@@ -221,7 +314,8 @@ export function runScenario(name) {
221
314
  (item) => { item.new_impacts = ["new-api"]; },
222
315
  (item) => { item.workflow_reference.source = "untrusted/source"; },
223
316
  (item) => { item.workflow_reference.skill = "implement"; },
224
- (item) => { item.workflow_reference.invocation_mode = "reference"; }
317
+ (item) => { item.workflow_reference.invocation_mode = "reference"; },
318
+ (item) => { item.next_route = "work-unit.slice-implementation"; }
225
319
  ]) {
226
320
  const invalid = structuredClone(validResult); mutate(invalid);
227
321
  let rejected = false;
@@ -0,0 +1,214 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { spawnSync } from "node:child_process";
3
+ import path from "node:path";
4
+ import { parseDocument } from "../vendor/yaml.mjs";
5
+ import { loadDigitalHumanRoles, taskPackageDefaults } from "./digital-human-roles.mjs";
6
+ import { loadRegistry, ROOT } from "./lifecycle-registry.mjs";
7
+ import { loadMaintenanceCheckpoint, validateMaintenanceCheckpoint } from "./maintenance-intensity.mjs";
8
+ import { validateNextRoute } from "./lifecycle-transition.mjs";
9
+
10
+ export const TASK_PACKAGE_SCHEMA = path.join(ROOT, "docs/process/schemas/digital-human-task-package.schema.json");
11
+ export const LEGACY_TASK_PACKAGE_SCHEMA = path.join(ROOT, "docs/process/schemas/subagent-task-package.schema.json");
12
+ export const TASK_PACKAGE_REGISTRY_REF = "docs/agents/digital-human-roles.yaml";
13
+ export const CONTRACT_KINDS = new Set(["lifecycle-work-unit", "slice-implementation", "template-maintenance"]);
14
+ export const EXECUTION_STATES = new Set(["Explorer", "Drafter", "Worker", "Reviewer", "Verifier"]);
15
+ export const WORKFLOW_STATUSES = new Set(["not-started", "active", "paused", "resolved", "failed"]);
16
+
17
+ function fail(message) { throw new TypeError(message); }
18
+ function requireString(value, field) { if (typeof value !== "string" || !value.trim()) fail(`${field} 不能为空`); }
19
+ function equalArrays(actual, expected) { return Array.isArray(actual) && actual.length === expected.length && actual.every((value, index) => value === expected[index]); }
20
+
21
+ function parseYaml(source, label) {
22
+ const document = parseDocument(source, { maxAliasCount: 0, uniqueKeys: true });
23
+ if (document.errors.length > 0) fail(`无法解析${label}: ${document.errors[0].message}`);
24
+ return document.toJS({ maxAliasCount: 0 });
25
+ }
26
+
27
+ function assertSafeRelativePath(value, field) {
28
+ requireString(value, field);
29
+ if (path.isAbsolute(value)) fail(`${field} 必须是仓库相对路径`);
30
+ const resolved = path.resolve(ROOT, value);
31
+ const relative = path.relative(ROOT, resolved);
32
+ if (relative === ".." || relative.startsWith(`..${path.sep}`)) fail(`${field} 不得越出仓库根目录`);
33
+ return resolved;
34
+ }
35
+
36
+ function assertReadableEvidenceRef(value, field) {
37
+ requireString(value, field);
38
+ if (/^https?:\/\//.test(value)) return;
39
+ const evidencePath = assertSafeRelativePath(value, field);
40
+ if (!existsSync(evidencePath)) fail(`${field} 不可读: ${value}`);
41
+ }
42
+
43
+ export function loadTaskPackage(filePath) {
44
+ const sourcePath = path.resolve(filePath);
45
+ if (!existsSync(sourcePath)) fail(`任务包不存在: ${filePath}`);
46
+ const value = parseYaml(readFileSync(sourcePath, "utf8"), "任务包");
47
+ if (!value || typeof value !== "object" || Array.isArray(value)) fail("任务包必须是对象");
48
+ return { value, sourcePath };
49
+ }
50
+
51
+ export function validateTaskPackageSchema(value, schemaPath = TASK_PACKAGE_SCHEMA) {
52
+ const effectiveSchema = path.resolve(schemaPath) === path.resolve(LEGACY_TASK_PACKAGE_SCHEMA) ? TASK_PACKAGE_SCHEMA : schemaPath;
53
+ if (!existsSync(effectiveSchema)) fail(`缺少任务包 schema: ${effectiveSchema}`);
54
+ const validator = String.raw`
55
+ import json
56
+ import sys
57
+ from jsonschema import Draft202012Validator
58
+ schema = json.load(open(sys.argv[1], encoding="utf-8"))
59
+ value = json.load(sys.stdin)
60
+ errors = sorted(Draft202012Validator(schema).iter_errors(value), key=lambda error: list(error.absolute_path))
61
+ for error in errors:
62
+ location = ".".join(str(part) for part in error.absolute_path) or "<root>"
63
+ print(f"{location}: {error.message}", file=sys.stderr)
64
+ sys.exit(1 if errors else 0)
65
+ `;
66
+ const result = spawnSync("python3", ["-c", validator, effectiveSchema], { cwd: ROOT, encoding: "utf8", input: JSON.stringify(value) });
67
+ if (result.status !== 0) fail(`${result.stdout}${result.stderr}`.trim());
68
+ }
69
+
70
+ function validateSkillSource(value, registry) {
71
+ const defaults = taskPackageDefaults(value.role_id, registry);
72
+ if (value.skill_source.registry_ref !== TASK_PACKAGE_REGISTRY_REF) fail(`skill_source.registry_ref 必须为 ${TASK_PACKAGE_REGISTRY_REF}`);
73
+ if (value.skill_source.defaults_ref !== `taskPackageDefaults(${value.role_id})`) fail(`skill_source.defaults_ref 必须为 taskPackageDefaults(${value.role_id})`);
74
+ if (!equalArrays(value.skill_source.core_skills, defaults.core_skills)) fail("skill_source.core_skills 必须与角色注册表完全一致");
75
+ if (!equalArrays(value.skill_source.forbidden_skills, defaults.forbidden_skills)) fail("skill_source.forbidden_skills 必须与角色注册表完全一致");
76
+ }
77
+
78
+ function validateCommon(value, registry, lifecycle) {
79
+ const workUnit = lifecycle.work_units.find((item) => item.id === value.work_unit_id);
80
+ if (!workUnit && value.contract.kind !== "slice-implementation") fail(`未知 work_unit_id: ${value.work_unit_id}`);
81
+ const roleDefaults = taskPackageDefaults(value.role_id, registry);
82
+ const runtimeIds = new Set((registry.runtimes || []).map((runtime) => runtime.id));
83
+ if (!runtimeIds.has(value.runtime_id)) fail(`未知 runtime_id: ${value.runtime_id}`);
84
+ if (!EXECUTION_STATES.has(value.execution_state)) fail(`execution_state 无效: ${value.execution_state}`);
85
+ if (!WORKFLOW_STATUSES.has(value.workflow_status)) fail(`workflow_status 无效: ${value.workflow_status}`);
86
+ if (value.stage_id) {
87
+ if (!lifecycle.stages.some((stage) => stage.id === value.stage_id)) fail(`未知 stage_id: ${value.stage_id}`);
88
+ if (!roleDefaults.stages.includes(value.stage_id)) fail(`role_id 未覆盖 stage_id: ${value.role_id} -> ${value.stage_id}`);
89
+ }
90
+ validateSkillSource(value, registry);
91
+ for (const allowed of value.allowed_write_paths) assertSafeRelativePath(allowed, "allowed_write_paths 条目");
92
+ if (value.execution_state === "Reviewer" && value.review_context.implementation_actor_id === value.actor_id) fail("Reviewer 必须与实现者使用不同 actor_id");
93
+ const commands = new Set(value.verification_commands);
94
+ for (const result of value.verification_results) {
95
+ if (!commands.has(result.command)) fail(`verification_results 命令未声明: ${result.command}`);
96
+ assertReadableEvidenceRef(result.evidence_ref, "verification_results.evidence_ref");
97
+ }
98
+ const completed = value.workflow_status === "resolved" || value.result?.result === "completed";
99
+ if (completed) {
100
+ if (!value.result || value.result.result !== "completed") fail("resolved/完成任务必须返回 result=completed 的 Workflow Execution Result");
101
+ if (value.workflow_status !== "resolved") fail("result=completed 的任务包必须处于 resolved 状态");
102
+ for (const field of ["result_schema", "work_unit", "workflow_reference", "skill", "changed_files", "evidence_refs", "deferred_seams", "drift", "violation", "new_impacts", "stale_candidates", "next_route", "blocking_signals"]) {
103
+ if (value.result[field] === undefined) fail(`result=completed 时 ${field} 不能为空`);
104
+ }
105
+ if (value.result.result_schema !== "workflow-execution-result-v1") fail("result_schema 必须为 workflow-execution-result-v1");
106
+ if (value.result.work_unit !== value.work_unit_id) fail("Workflow Execution Result.work_unit 必须与任务包 work_unit_id 一致");
107
+ const routeResult = validateNextRoute(value.result.work_unit, value.result.next_route);
108
+ if (routeResult.result !== "allowed") fail(`Workflow Execution Result next_route 非法: ${routeResult.blocking_signals.join(", ")}`);
109
+ value.expected_evidence_files.forEach((ref) => assertReadableEvidenceRef(ref, "expected_evidence_files"));
110
+ if (value.verification_results.length === 0) fail("已完成任务必须包含 verification_results");
111
+ if (value.verification_results.some((result) => result.exit_code !== 0)) fail("已完成任务的验证命令必须全部成功");
112
+ const resultCommands = new Set(value.verification_results.map((result) => result.command));
113
+ if (value.verification_commands.some((command) => !resultCommands.has(command))) fail("已完成任务必须覆盖全部 verification_commands");
114
+ }
115
+ if (value.result) {
116
+ for (const field of ["new_impacts", "stale_candidates", "blocking_signals", "drift", "violation"]) {
117
+ if (value.result.result === "completed" && Array.isArray(value.result[field]) && value.result[field].length > 0) fail(`result=completed 时 ${field} 必须为空`);
118
+ }
119
+ if (value.result.result === "completed") {
120
+ if (!Array.isArray(value.result.evidence_refs) || value.result.evidence_refs.length === 0) fail("result=completed 时 evidence_refs 不能为空");
121
+ value.result.evidence_refs.forEach((ref) => assertReadableEvidenceRef(ref, "result.evidence_refs"));
122
+ }
123
+ if (Array.isArray(value.result.changed_files)) {
124
+ for (const changed of value.result.changed_files) {
125
+ const changedPath = assertSafeRelativePath(changed, "changed_files 条目");
126
+ if (!value.allowed_write_paths.some((allowed) => {
127
+ const allowedPath = assertSafeRelativePath(allowed, "allowed_write_paths 条目");
128
+ const relative = path.relative(allowedPath, changedPath);
129
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`));
130
+ })) fail(`changed_files 超出 allowed_write_paths: ${changed}`);
131
+ }
132
+ }
133
+ }
134
+ return workUnit;
135
+ }
136
+
137
+ function validateContract(value, registry, lifecycle) {
138
+ const contract = value.contract;
139
+ const implementationWorkUnit = "work-unit.slice-implementation";
140
+ const workUnit = lifecycle.work_units.find((item) => item.id === value.work_unit_id);
141
+ if (!CONTRACT_KINDS.has(contract.kind)) fail(`未知 contract.kind: ${contract.kind}`);
142
+ if (!new Set(["issued", "stale", "blocked"]).has(contract.status)) fail(`contract.status 无效: ${contract.status}`);
143
+ if (contract.status === "stale" && value.workflow_status !== "paused") fail("stale 任务包必须暂停,待主控重新路由");
144
+ assertReadableEvidenceRef(contract.contract_ref, "contract.contract_ref");
145
+ if (contract.kind === "lifecycle-work-unit") {
146
+ if (value.work_unit_id === implementationWorkUnit || value.convergence.parent_work_unit === implementationWorkUnit) {
147
+ fail("lifecycle-work-unit 不得冒充垂直切片实现任务;实现任务必须使用 slice-implementation");
148
+ }
149
+ if (workUnit?.scope === "template-source") fail("template-source 工作单元必须使用 template-maintenance");
150
+ if (contract.slice_contract_ref || contract.maintenance_ref) fail("lifecycle-work-unit 不得携带专项合同引用");
151
+ assertReadableEvidenceRef(contract.lifecycle_ref, "contract.lifecycle_ref");
152
+ return;
153
+ }
154
+ if (contract.kind === "template-maintenance") {
155
+ if (contract.slice_contract_ref || contract.lifecycle_ref) fail("template-maintenance 不得携带其他合同引用");
156
+ const checkpointPath = assertSafeRelativePath(contract.maintenance_ref, "contract.maintenance_ref");
157
+ if (!existsSync(checkpointPath)) fail(`维护 checkpoint 不存在: ${contract.maintenance_ref}`);
158
+ validateMaintenanceCheckpoint(loadMaintenanceCheckpoint(contract.maintenance_ref));
159
+ if (lifecycle.work_units.find((item) => item.id === value.work_unit_id)?.scope !== "template-source") fail("template-maintenance 必须绑定 template-source work unit");
160
+ return;
161
+ }
162
+ if (contract.lifecycle_ref || contract.maintenance_ref) fail("slice-implementation 不得携带其他合同引用");
163
+ if (!/^stage\.vertical-slice-implementation$/.test(value.stage_id)) fail("slice-implementation 必须绑定垂直切片实现阶段");
164
+ if (value.convergence.parent_work_unit !== implementationWorkUnit) fail("slice-implementation 必须汇合到 work-unit.slice-implementation");
165
+ if (/^https?:\/\//.test(contract.slice_contract_ref)) fail("slice_contract_ref 必须引用本地已持久化的 Slice Implementation Contract");
166
+ const contractPath = assertSafeRelativePath(contract.slice_contract_ref, "contract.slice_contract_ref");
167
+ if (!existsSync(contractPath)) fail(`Slice Implementation Contract 不存在: ${contract.slice_contract_ref}`);
168
+ const document = parseYaml(readFileSync(contractPath, "utf8"), "Slice Implementation Contract");
169
+ const slice = document.slice_contract || document;
170
+ if (slice.schema_version !== 1 || typeof slice.slice_id !== "string" || !slice.lifecycle_refs || !slice.readiness || !Array.isArray(slice.work_units)) fail("Slice Implementation Contract 缺少 schema_version/slice_id/lifecycle_refs/readiness/work_units");
171
+ if (slice.contract_id !== contract.contract_id || slice.contract_version !== contract.contract_version || slice.status !== "approved") fail("Slice Contract 必须是当前 approved 版本");
172
+ const sliceUnit = slice.work_units.find((item) => item && item.id === value.work_unit_id);
173
+ if (!sliceUnit) fail(`Slice Implementation Contract 缺少 work_unit_id: ${value.work_unit_id}`);
174
+ for (const field of ["role_id", "runtime_id", "task_package_ref", "contract_id", "contract_version", "allowed_write_paths"]) if (sliceUnit[field] === undefined) fail(`Slice Contract work_unit 缺少 ${field}`);
175
+ if (sliceUnit.role_id !== value.role_id || sliceUnit.runtime_id !== value.runtime_id || sliceUnit.contract_id !== contract.contract_id || sliceUnit.contract_version !== contract.contract_version || sliceUnit.task_package_ref !== value.work_unit_id) fail("任务包与 Slice Contract work_unit 不一致");
176
+ for (const allowed of value.allowed_write_paths) if (!sliceUnit.allowed_write_paths.includes(allowed)) fail(`allowed_write_paths 未获 Slice Contract 授权: ${allowed}`);
177
+ }
178
+
179
+ export function validateTaskPackage(value, { rolesDoc, lifecycleDoc } = {}) {
180
+ validateTaskPackageSchema(value);
181
+ const registry = rolesDoc || loadDigitalHumanRoles();
182
+ const lifecycle = lifecycleDoc || loadRegistry();
183
+ validateCommon(value, registry, lifecycle);
184
+ validateContract(value, registry, lifecycle);
185
+ return value;
186
+ }
187
+
188
+ export function generateTaskPackageDefaults(roleId, overrides = {}, { rolesDoc } = {}) {
189
+ const defaults = taskPackageDefaults(roleId, rolesDoc || loadDigitalHumanRoles());
190
+ return {
191
+ schema_version: 1,
192
+ role_id: defaults.role_id,
193
+ skill_source: {
194
+ registry_ref: TASK_PACKAGE_REGISTRY_REF,
195
+ defaults_ref: `taskPackageDefaults(${roleId})`,
196
+ core_skills: defaults.core_skills,
197
+ forbidden_skills: defaults.forbidden_skills
198
+ },
199
+ ...overrides
200
+ };
201
+ }
202
+
203
+ export function validateTaskPackageSet(packages, options = {}) {
204
+ if (!Array.isArray(packages) || packages.length === 0) fail("任务包集合不能为空");
205
+ packages.forEach((pkg) => validateTaskPackage(pkg, options));
206
+ const slicePackages = packages.filter((pkg) => pkg.contract.kind === "slice-implementation");
207
+ if (slicePackages.length > 0) {
208
+ const contracts = new Set(slicePackages.map((pkg) => `${pkg.contract.contract_id}@${pkg.contract.contract_version}`));
209
+ if (contracts.size !== 1) fail("同一切片的任务包必须消费同一 contract_id/contract_version");
210
+ const workers = new Set(slicePackages.filter((pkg) => pkg.execution_state === "Worker").map((pkg) => pkg.actor_id));
211
+ slicePackages.filter((pkg) => pkg.execution_state === "Reviewer").forEach((pkg) => { if (workers.has(pkg.actor_id)) fail("Reviewer 不得与实现者使用同一 actor_id"); });
212
+ }
213
+ return packages;
214
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { validateApprovalRecordFile } from "./lib/approval-record.mjs";
4
+
5
+ try {
6
+ const { positionals } = parseArgs({ allowPositionals: true, strict: true });
7
+ if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-approval-record <approval-record.yaml>");
8
+ validateApprovalRecordFile(positionals[0]);
9
+ process.stdout.write("会签记录校验通过\n");
10
+ } catch (error) {
11
+ process.stderr.write(`会签记录校验失败: ${error.message}\n`);
12
+ process.exitCode = 1;
13
+ }
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { validateDefaultDigitalHumanRoles } from "./lib/digital-human-roles.mjs";
3
+
4
+ try {
5
+ const result = validateDefaultDigitalHumanRoles();
6
+ process.stdout.write(`数字人角色注册表校验通过(${result.role_count} 个角色,${result.group_count} 个协作组,${result.runtime_count} 个运行时)\n`);
7
+ } catch (error) {
8
+ process.stderr.write(`数字人角色注册表校验失败: ${error.message}\n`);
9
+ process.exitCode = 1;
10
+ }
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ import { validateDefaultDigitalHumanRoles, validateDigitalHumanRoles, loadDigitalHumanRoles, skillIdsFromRegistry } from "./lib/digital-human-roles.mjs";
3
+ import { loadRegistry } from "./lib/lifecycle-registry.mjs";
4
+ import { loadSkillRegistry } from "./lib/skill-registry.mjs";
5
+ import { validateApprovalRecord, validateApprovalRecordFile } from "./lib/approval-record.mjs";
6
+
7
+ function clone() {
8
+ return structuredClone(loadDigitalHumanRoles());
9
+ }
10
+
11
+ function deps() {
12
+ const lifecycle = loadRegistry();
13
+ const skills = loadSkillRegistry();
14
+ const ids = (records) => new Set(records.map((record) => record.id));
15
+ return {
16
+ skillIds: skillIdsFromRegistry(skills),
17
+ stageIds: ids(lifecycle.stages),
18
+ gateIds: ids(lifecycle.gates),
19
+ artifactIds: ids(lifecycle.artifacts),
20
+ evidenceIds: ids(lifecycle.evidence),
21
+ workUnitIds: ids(lifecycle.work_units),
22
+ skillRegistry: skills
23
+ };
24
+ }
25
+
26
+ function mustFail(doc, pattern, label) {
27
+ let failed = false;
28
+ let message = "";
29
+ try {
30
+ validateDigitalHumanRoles(doc, deps());
31
+ } catch (error) {
32
+ failed = true;
33
+ message = error.message;
34
+ }
35
+ if (!failed) throw new TypeError(`错误配置未被拒绝: ${label}`);
36
+ if (!pattern.test(message)) throw new TypeError(`${label} 失败原因不符合预期: ${message}`);
37
+ }
38
+
39
+ validateDefaultDigitalHumanRoles();
40
+
41
+ const seven = [
42
+ "role.lifecycle-orchestrator",
43
+ "role.requirements-manager",
44
+ "role.product-manager",
45
+ "role.business",
46
+ "role.frontend-engineer",
47
+ "role.backend-engineer",
48
+ "role.test-engineer"
49
+ ];
50
+
51
+ const genericAllowsSeven = clone();
52
+ genericAllowsSeven.stage_groups[0].members = seven;
53
+ validateDigitalHumanRoles(genericAllowsSeven, deps());
54
+
55
+ const grokForbidsSeven = clone();
56
+ grokForbidsSeven.stage_groups[0].members = seven;
57
+ grokForbidsSeven.runtimes.find((runtime) => runtime.id === "runtime.grok").overflow = "forbid";
58
+ mustFail(grokForbidsSeven, /禁止超过 6 人/, "Grok 适配器在 overflow=forbid 时拒绝七人协作组");
59
+
60
+ const coupled = clone();
61
+ coupled.roles[0].grok_title = "legacy";
62
+ mustFail(coupled, /平台耦合字段/, "角色上残留 grok_title");
63
+
64
+ const unknownSkill = clone();
65
+ unknownSkill.roles[0].core_skills = ["not-a-registered-skill"];
66
+ mustFail(unknownSkill, /未登记技能/, "未知技能");
67
+
68
+ const overlap = clone();
69
+ overlap.roles.find((role) => role.id === "role.frontend-engineer").forbidden_skills.push("yss-ui");
70
+ mustFail(overlap, /重叠/, "启用且禁止同一技能");
71
+
72
+ const selfSign = clone();
73
+ selfSign.gate_policy.dual_digital_human[0].countersigners = ["role.requirements-manager"];
74
+ mustFail(selfSign, /起草者不得会签自己/, "起草者自签");
75
+
76
+ const releaseByBot = clone();
77
+ releaseByBot.gate_policy.biological_human = ["gate.architecture-reviewed"];
78
+ releaseByBot.gate_policy.digital_human_review.push({
79
+ gate: "gate.release-ready",
80
+ countersigners: ["role.product-manager"]
81
+ });
82
+ mustFail(releaseByBot, /gate\.release-ready/, "数字人关闭发布门禁");
83
+
84
+ const missingSigners = clone();
85
+ missingSigners.gate_policy.digital_human_review[0].countersigners = [];
86
+ mustFail(missingSigners, /countersigners/, "单审门禁缺 countersigners");
87
+
88
+ const stringReview = clone();
89
+ stringReview.gate_policy.digital_human_review = ["gate.prototype-reviewed"];
90
+ mustFail(stringReview, /必须是含 gate/, "单审门禁仍用字符串名单");
91
+
92
+ const missingGeneric = clone();
93
+ missingGeneric.runtimes = missingGeneric.runtimes.filter((runtime) => runtime.id !== "runtime.generic");
94
+ mustFail(missingGeneric, /缺少运行时绑定: runtime.generic/, "缺少通用运行时");
95
+
96
+ validateApprovalRecordFile("docs/templates/approval-record-template.yaml");
97
+
98
+ const rolesDoc = loadDigitalHumanRoles();
99
+ try {
100
+ validateApprovalRecord({
101
+ schema_version: 1,
102
+ gate_id: "gate.spec-baseline-approved",
103
+ decision: "approved",
104
+ actor_kind: "digital-human",
105
+ role_id: "role.requirements-manager",
106
+ runtime_id: "runtime.generic",
107
+ principal_ref: "instance:wrong"
108
+ }, { rolesDoc });
109
+ throw new TypeError("错误配置未被拒绝: 错误角色会签");
110
+ } catch (error) {
111
+ if (!/会签角色必须是/.test(error.message)) throw new TypeError(`错误角色会签 失败原因不符合预期: ${error.message}`);
112
+ }
113
+
114
+ try {
115
+ validateApprovalRecord({
116
+ schema_version: 1,
117
+ gate_id: "gate.spec-baseline-approved",
118
+ decision: "approved",
119
+ actor_kind: "digital-human",
120
+ role_id: "role.requirements-manager",
121
+ runtime_id: "runtime.generic",
122
+ principal_ref: "instance:req",
123
+ drafter_role_id: "role.requirements-manager"
124
+ }, { rolesDoc });
125
+ throw new TypeError("错误配置未被拒绝: 起草者自签会签记录");
126
+ } catch (error) {
127
+ if (!/会签角色必须是|起草者不得会签自己/.test(error.message)) {
128
+ throw new TypeError(`起草者自签会签记录 失败原因不符合预期: ${error.message}`);
129
+ }
130
+ }
131
+
132
+ try {
133
+ validateApprovalRecord({
134
+ schema_version: 1,
135
+ gate_id: "gate.release-ready",
136
+ decision: "approved",
137
+ actor_kind: "digital-human",
138
+ role_id: "role.product-manager",
139
+ runtime_id: "runtime.generic",
140
+ principal_ref: "instance:pm"
141
+ }, { rolesDoc });
142
+ throw new TypeError("错误配置未被拒绝: 数字人关发布会签记录");
143
+ } catch (error) {
144
+ if (!/必须由生物人会签/.test(error.message)) throw new TypeError(`数字人关发布会签记录 失败原因不符合预期: ${error.message}`);
145
+ }
146
+
147
+ process.stdout.write("数字人角色压力场景验证通过\n");
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { loadTaskPackage, validateTaskPackage } from "./lib/task-package.mjs";
4
+
5
+ try {
6
+ const { positionals } = parseArgs({ allowPositionals: true, strict: true });
7
+ if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-digital-human-task-package <task-package.yaml|task-package.json>");
8
+ const { value } = loadTaskPackage(positionals[0]);
9
+ validateTaskPackage(value);
10
+ process.stdout.write("数字人任务包验证通过\n");
11
+ } catch (error) {
12
+ process.stderr.write(`数字人任务包验证失败: ${error.message}\n`);
13
+ process.exitCode = 1;
14
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
7
+ const result = spawnSync(process.execPath, [path.join(root, "scripts/verify-subagent-task-package-scenarios"), ...process.argv.slice(2)], { stdio: "inherit" });
8
+ process.exitCode = result.status ?? 1;
@@ -5,6 +5,7 @@ import path from "node:path";
5
5
  import { parseArgs } from "node:util";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { parseDocument } from "./vendor/yaml.mjs";
8
+ import { assertCheckpointApprovals } from "./lib/approval-record.mjs";
8
9
 
9
10
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
11
  const schemaPath = path.join(root, "docs/process/schemas/lifecycle-checkpoint.schema.json");
@@ -30,6 +31,7 @@ try {
30
31
  const value = document.toJS({ maxAliasCount: 0 });
31
32
  const result = spawnSync("python3", ["-c", validator, schemaPath], { cwd: root, encoding: "utf8", input: JSON.stringify(value) });
32
33
  if (result.status !== 0) throw new TypeError(`${result.stdout}${result.stderr}`.trim());
34
+ assertCheckpointApprovals(value, sourcePath);
33
35
  process.stdout.write("生命周期 checkpoint 验证通过\n");
34
36
  } catch (error) {
35
37
  process.stderr.write(`生命周期 checkpoint 验证失败: ${error.message}\n`);